Is there anything special I need to do in order to mix object filescreated by the C and the C++ comp

Discussion in 'C++' started by Ramon F Herrera, Sep 11, 2009.

  1. I created one *.o file from a C source, using gcc

    I created another *.o file from a C++ source, using g++.

    The linking pass is failing.

    Should I use gcc, g++ or ld for linking? I am guessing the latter.

    Are there any special flags, steps or gotchas?

    TIA,

    -Ramon
    Ramon F Herrera, Sep 11, 2009
    #1
    1. Advertising

  2. Re: Is there anything special I need to do in order to mix objectfiles created by the C and the C++ compilers?

    On Sep 10, 7:49 pm, Ramon F Herrera <> wrote:
    > I created one *.o file from a C source, using gcc
    >
    > I created another *.o file from a C++ source, using g++.
    >
    > The linking pass is failing.
    >
    > Should I use gcc, g++ or ld for linking? I am guessing the latter.
    >
    > Are there any special flags, steps or gotchas?
    >
    > TIA,
    >
    > -Ramon



    If it matters, the C++ program is the main one, and it makes a call to
    a function in the C program.

    -RFH
    Ramon F Herrera, Sep 11, 2009
    #2
    1. Advertising

  3. Re: Is there anything special I need to do in order to mix objectfiles created by the C and the C++ compilers?

    On Sep 10, 4:49 pm, Ramon F Herrera <> wrote:
    > I created one *.o file from a C source, using gcc
    >
    > I created another *.o file from a C++ source, using g++.
    >
    > The linking pass is failing.
    >
    > Should I use gcc, g++ or ld for linking? I am guessing the latter.
    >
    > Are there any special flags, steps or gotchas?


    What exactly is failing?

    Possibly your problem: A C++ function is not a C function. They look
    different to the linker.

    //AA.c
    int foo() { return 1; }

    //BB.cpp
    int foo();
    int main() { return foo(); }

    When these two source files are given to gcc, for example, they will
    both compile fine, but you will get an unresolved symbol error when
    you try to link it into an executable. The "int foo();" in the C++
    source file defines a C++ function, which has a different kind of
    linkage than a C function. The linker will treat them as two different
    functions.

    //CC.c
    int foo() { return 1; }

    //DD.cpp
    extern "C" int foo();
    int main() { return foo(); }

    When you try to compile and link CC and DD, it should link
    successfully. The
    extern "C"
    tells the C++ compiler to use C rules for linkage, and then the linker
    will see that the foo's "are the same" and do what you want.
    Joshua Maurice, Sep 11, 2009
    #3
  4. Re: Is there anything special I need to do in order to mix objectfiles created by the C and the C++ compilers?

    On Sep 10, 7:55 pm, Joshua Maurice <> wrote:
    > On Sep 10, 4:49 pm, Ramon F Herrera <> wrote:
    >
    > > I created one *.o file from a C source, using gcc

    >
    > > I created another *.o file from a C++ source, using g++.

    >
    > > The linking pass is failing.

    >
    > > Should I use gcc, g++ or ld for linking? I am guessing the latter.

    >
    > > Are there any special flags, steps or gotchas?

    >
    > What exactly is failing?
    >
    > Possibly your problem: A C++ function is not a C function. They look
    > different to the linker.
    >
    > //AA.c
    > int foo() { return 1; }
    >
    > //BB.cpp
    > int foo();
    > int main() { return foo(); }
    >
    > When these two source files are given to gcc, for example, they will
    > both compile fine, but you will get an unresolved symbol error when
    > you try to link it into an executable. The "int foo();" in the C++
    > source file defines a C++ function, which has a different kind of
    > linkage than a C function. The linker will treat them as two different
    > functions.
    >
    > //CC.c
    > int foo() { return 1; }
    >
    > //DD.cpp
    > extern "C" int foo();
    > int main() { return foo(); }
    >
    > When you try to compile and link CC and DD, it should link
    > successfully. The
    >     extern "C"
    > tells the C++ compiler to use C rules for linkage, and then the linker
    > will see that the foo's "are the same" and do what you want.



    The problem was fixed by the extern "C" statement, Josh.

    How about the opposite, how should I refer to to an extern C++
    function?

    Let me guess:

    extern "C++"

    -Ramon
    Ramon F Herrera, Sep 11, 2009
    #4
  5. Re: Is there anything special I need to do in order to mix object files created by the C and the C++ compilers?

    Ramon F Herrera <> writes:

    > The problem was fixed by the extern "C" statement, Josh.


    Notice that you can wrap several declarations in a block:

    extern "C"{
    #include <c_code.h>
    int foo(int);
    }


    > How about the opposite, how should I refer to to an extern C++
    > function?
    >
    > Let me guess:
    >
    > extern "C++"


    If that was that easy!

    Since a lot of C code can be compiled by C++ compilers, the easiest is
    to consider the C code as C++ code, and just call the other C++
    functions without further ado.

    However, if you have non-C++ conciscous C code, you might have to
    review it and modify it slightly to avoid the things that are excluded
    by C++. For example you cannot use the identifier 'new' in C++ code
    since it's a keyword, so any C code that would it would have to be
    edited. There are a number of similar gotchas.


    Technically, the problem is that C++ function names are mangled, and
    this mangling is implementation dependant! The signature of the
    function is encoded into the external name of C++ functions.

    So a C++ function such as int foo(int,char*); will actually be named
    something like __Z3fooiPc in the object file.



    From C code, compiled with a C program, you could call it as:

    // C code:

    extern int _Z3fooiPc(int i,char* c);

    int f(){
    char a[]="abc";
    _Z3fooiPc(3,a);
    }

    Not funny.



    The solution is to define C wrapper functions, in C++ (ie. you still
    need the C++ compiler).

    -------------------------------- c.cxx
    // A C++ function:
    int bar(int i,char* c){
    return(c);
    }

    // A C++ function whose name won't be mangled:
    extern "C" int foo(int i,char* c){
    return(bar(i,c));
    }
    ---------------------------------

    % g++ -c -o c.o c.cxx && nm c.o
    00000000 T __Z3bariPc
    00000000 A __Z3bariPc.eh
    00000014 T _foo
    00000000 A _foo.eh


    Notably, in the case of C++ objects, your wrapper will have to
    explicitely pass the 'this' parameter:

    -------------------------------- o.cxx
    // A C++ class:
    class Example {
    int i;
    public:
    Example(int aI):i(aI){}
    int foo(char* c){
    return(c[this->i]);
    }
    };


    // A C wrapper over the C++ class:
    extern "C"{
    typedef void* ExampleP;
    ExampleP Example_new(int aI){ return new Example(aI); }
    Example_foo(ExampleP that,char* c){ return(((Example*)that)->foo(c)); }

    }
    ---------------------------------

    % g++ -c -o o.o o.cxx && nm o.o
    0000006c s EH_frame1
    0000002c T _Example_foo
    00000000 A _Example_foo.eh
    00000000 T _Example_new
    000000d0 S _Example_new.eh
    00000056 S __ZN7Example3fooEPc
    000000ac S __ZN7Example3fooEPc.eh
    00000046 S __ZN7ExampleC1Ei
    00000088 S __ZN7ExampleC1Ei.eh
    U __Znwm
    U ___gxx_personality_v0





    --
    __Pascal Bourguignon__
    Pascal J. Bourguignon, Sep 11, 2009
    #5
  6. Ramon F Herrera

    mac Guest

    Re: Is there anything special I need to do in order to mix object files created by the C and the C++ compilers?

    > > extern "C++"
    >
    > If that was that easy!


    As noted, C++ functions can be overloaded, so their names are extended
    (mangled) to distinguish them.

    But it goes much deeper than that. C++ has a more complex runtime
    environment than C. Unless the C library is written to support both
    languages, it may not handle some C++ features.

    C++ code can have static constructors, which are called before main()
    starts. C has no such thing (unless the standards committee has been
    meddling), so there's no way a C program can initialize static C++ data.

    C++ has exceptions, which C does not. So C code may not correctly handle
    exceptions. C++ exceptions delete local objects as they go out of scope.
    C won't.

    C runtime, on the other hand, is pretty simple, so it's supported by C++.

    Mixing malloc() and operator new may also lead to trouble.
    Mixing stdio and iostreams is likely to lead to trouble.
    mac, Sep 11, 2009
    #6
  7. Re: Is there anything special I need to do in order to mix object files created by the C and the C++ compilers?

    mac <> writes:

    [...]

    > C++ has exceptions, which C does not. So C code may not correctly handle
    > exceptions. C++ exceptions delete local objects as they go out of scope.
    > C won't.


    That should have been 'C++ object can have destructors which are
    automatically called for objects with storage class auto whenever
    those go out of scope' (for instance, because of an exception).
    Storage used by 'auto' objects themselves is freed when their lifetime
    ends in C, too.
    Rainer Weikusat, Sep 11, 2009
    #7
  8. Re: Is there anything special I need to do in order to mix object files created by the C and the C++ compilers?

    mac <> writes:

    > C++ code can have static constructors, which are called before main()
    >starts. C has no such thing (unless the standards committee has been
    >meddling), so there's no way a C program can initialize static C++ data.


    From a standards perspective, perhaps. Most C implementations however
    have some manner of pre-main initialization (e.g. .init/.fini sections
    in the ELF file and shared objects).

    scott
    Scott Lurndal, Sep 11, 2009
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.

Share This Page