Data handling between combined c - c++ code

Discussion in 'C++' started by mobz, Mar 23, 2010.

  1. mobz

    mobz New Member

    Joined:
    Mar 23, 2010
    Messages:
    1
    Likes Received:
    0
    Trophy Points:
    0
    I was combining C and C++ codes for a certain application when I came across a peculiar feature. When I return a 'double' from cpp function called inside a c function the double values are not held. Here is a simple example:

    File plus.cpp (cpp code)
    PHP:
    #include <stdio.h>
    extern "C" double f();
    double f()
    {
       
    double val=2.134;
       
    printf("%lf\n",val);
      return 
    val;
    }
    file main.c (c code)
    PHP:
    #include <stdio.h>
    int main()
    {
      
    double w;
      
    f();
      
    printf("%lf\n",w);
      return 
    0;
    }
    Compiling :
    PHP:
    gcc -c main.c
    g
    ++ -c plus.cpp
    g
    ++ -o test *.o
    Result:
    PHP:
    2.134000
    -1752346657.000000
    The double value does not translate to the c code. Any ideas?

    Thanks in advance

    (PS: Things I cannot do -
    1. Compiling C code using C++ compiler. The actual problem is a complex set of functions and libraries and this is not do able.
    2. Convert C code to C++ or vice-versa. Same reason as above.
    I am just trying to understand how the compilers work and/or reasons this happens.
    )
     
  2. xpi0t0s

    xpi0t0s Mentor

    Joined:
    Aug 6, 2004
    Messages:
    3,009
    Likes Received:
    203
    Trophy Points:
    63
    Occupation:
    Senior Support Engineer
    Location:
    England
    f() is not defined in main.c. So the compiler assumes this is an int with no parameters, i.e. int f(); If you want something other than that then you have to prototype it (as you have done, unnecessarily, in plus.cpp).

    You cannot compile C code with a C++ compiler because it is a different language. Use a C compiler. However you can integrate C code with C++ code, in the C++ code you have to declare the functions extern "C" to prevent name mangling.

    C++ is a superset of C so converting C to C++ should be fairly easy. There are some significant differences though and you should read up on those before trying. It may be easier to compile the C code with a C compiler, and the C++ code with a C++ compiler, and link the resulting objects together.

    Regarding the vice versa, no, obviously this is mostly impossible. C does not support all the object stuff you get in C++ and there are other major differences too. Don't even try.
     
  3. xpi0t0s

    xpi0t0s Mentor

    Joined:
    Aug 6, 2004
    Messages:
    3,009
    Likes Received:
    203
    Trophy Points:
    63
    Occupation:
    Senior Support Engineer
    Location:
    England
    There are probably other things you need to do to make the above code work. Is there any reason why your main is C and plus is C++? If it was the other way round this would be fairly easy to fix. The f() name will most likely be mangled and C won't be able to find it; there is no extern "C++" in C. extern "C" is a C++ specific feature for integrating C code into a C++ program.

    What is Name Mangling I hear you cry. C++ supports function overloading, e.g.
    Code:
    double f(double x);
    int f(int x);
    char f(char x);
    
    but the linker does not. So when the compiler compiles these to object code, it has to modify these names so that the linker does not throw "duplicate symbol" errors. So the first might become f$dbl, the second f$int, the third f$ch, in a hypothetical compiler where the name mangling works that way, and when some other C++ function calls f(double) it would look for f$dbl.

    The reason this is a problem when integrating C code into C++ is that C does not support function overloading and knows nothing about name mangling. So the above three declarations will cause errors, and if you remove the 2nd and 3rd leaving double f(double) then this will be compiled (by a C compiler) into a function simply named f (actually _f but don't worry about the underscore). So a C++ program won't find this, because it's looking for f$dbl. So you have to prototype f in the C++ program as:
    Code:
    extern "C" {
      double f(double);
    }
    
    so that the C++ compiler knows f(double) exists and IS NOT called f$dbl.

    But as you've declared f() in the C++ code and want to call it in the C code, this probably won't be fixable. I don't know if you can force f not to be mangled by prototyping it in the C++ code as extern "C" - probably not.
     

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice