-->

Linking in several C object files that contain fun

2020-08-01 03:21发布

问题:

Lets say I have a C++ program and I want to call functions from a C object file in it. The constraint is that I'm not allowed to make any changes to the C source files.

In this case I would include the C header as extern "C" in my C++ file, call the function, compile the C object using gcc -c, and pass the result to g++ along with the actual C++ sources.

I guess what I would also do is to put the C-header #include inside a named namespace block in the C++ file, as to keep the local namespace clean (who knows what other fancy stuff there is in the .h file).

What now if I need to call functions from two C object files. Lets say that they have different signatures. But there are also some duplicate functions in the object files. Wouldn't my linker blow up at this point if I tried to pass both objects to g++ at the same time? Same for globals.

Again: I'm not allowed to change ANY of the C sources. Else I would just rename the .c files to .cxx, wrap their contents and the contents of the corresponding headers inside namespace bla { } and feed everything to g++.

(Yes, C is not a subset of C++, as has already been mentioned in one of the comments)

回答1:

Your last paragraph has a good solution - why not make a C++ file something like this:

namespace c_namespace_1 {
    #include "CFile1.c"
}

namespace c_namespace_2 {
    #include "CFile2.c"
}

And so on.... then you could compile this file as C++ and not have to modify the original sources.



回答2:

You could bring the C executable codes in as individual binary data files and handle the function pointer casting yourself - basically do the linker's job for it. If the binary directly wouldn't work, get the assembler output of the C files and wrap them in functions similiar to the above suggestion of namespaces.



回答3:

How about compile each C subsystem to its own LIB file, then compile a separate C++ LIB file that includes the appropriate C LIB and provides wrapped function calls to only the C functions in its .LIB

ie:

file1.c => file1.lib
file2.c => file2.lib

Wrapper1.cpp + file1.lib => Wrapper1.lib
Wrapper2.cpp + file2.lib => Wrapper2.lib

Application.cpp + Wrapper1.lib + wrapper2.lib => Application.exe

Note that this off the top of my head and I have no idea if the linker will still go boom

Of course you could compile Wrapper1 and Wrapper2 to dll's instead of Lib's and that would ensure the linker doesn't go boom!



回答4:

This is pretty hacky, but one solution is to rename the function(s) in question via macros, so that they have different names as far as the linker is concerned.

For example, if you have too functions called foo, one of which takes an int and the other of which takes a double, in files IntFoo.c and DoubleFoo.c, you can compile them like this:

cc -Dfoo=IntFoo -o IntFoo.o IntFoo.c
cc -Dfoo=DoubleFoo -o DoubleFoo.o DoubleFoo.c

Then in your C++, you can do this:

#define foo IntFoo
extern "C" {
    #include "IntFoo.h"
}

#define foo DoubleFoo
extern "C" {
    #include "DoubleFoo.h"
}

#undef foo

There are lot of caveats here: you have to ensure that the symbol foo is used only as the name of the function you want, you have to ensure that you define the macros appropriately everywhere that the symbol foo is used. If there are duplicate symbols, you have to define macros for those as well.

It is probably a much better solution to just fix the C files.