Bonding C and C ++ object files without source code

There are two object files. They contain the definition (body) of a function. This object file was compiled using the C ++ compiler, so the function name is garbled. The second object file refers to (calls) the function from the first object file. However, the second object file was compiled using the C compiler, so the function name is not distorted. When linking these two object files, there is an error for the undefined character. It is not possible to modify the source files so that the C ++ object file uses extern "C" definitions and does not distort the function name. Nevertheless, you can write some kind of glue code (wrapper), compile it with the C ++ compiler and link it with these object files. Here is a simple example:

$ cat file1.cpp

int fun(int in1, int in2) { return in1+in2; } 

$ cat file2.c

 #include <stdio.h> int fun(int, int); int main() { printf("%d\n",fun(3, 4)); return 0; } 

These two files are compiled into objects without any possibility of changing them:

 g++ -c file1.cpp -o file1.o gcc -c file2.c -o file2.o 

Writing glue code seems like a simple task, but the problem is that we have to export the function name in C and at the same time import it from C ++. The only solution I could come up with was to write two wrappers. One of them basically renames the C ++ function, and the other provides the renamed C function:

$ cat glue.cpp

 int cppfun(int, int); #ifdef __cplusplus extern "C" { #endif int fun(int in1, int in2) { return cppfun(in1, in2); } #ifdef __cplusplus } #endif 

$ cat gluecpp.cpp

 int fun(int, int); int cppfun(int in1, int in2) { return fun(in1, in2); } 

Compile and combine these wrappers with the original objects:

 g++ -c glue.cpp -o glue.o g++ -c gluecpp.cpp -o gluecpp.o g++ file1.o file2.o glue.o gluecpp.o -o exe.out 

Do you guys think there is another way? It became for me just an academic interest :)

+5
source share
3 answers

This works with gcc and clang, but in my reading of the standard this is not legal:

 int fun(int a, int b); namespace C { extern "C" int fun(int a, int b) { return ::fun(a, b); } } 

In fact, names declared extern "C" do not have an external namespace (& sect; 7.5 [dcl.link], clause 6):

No more than one function with a specific name can have a C-language connection. Two declarations for a function with C-language connection with the same function name (ignoring the namespace names that qualify it) that appear in different areas of the namespace refer to the same function.

Thus, the declaration and definition of the "C" function inside the namespace is in order. However, the same paragraph states:

An entity with a C language binding should not be declared with the same name as an object on a global scale unless both declarations designate the same person; no diagnostics are required if declarations appear in different translation units.

With g++ -c -o glue.o -Wall -Wextra --pedantic -std=c++11 glue.cc I received no warning, although the two declarations are in the same translation unit.

+1
source

This glue works with GCC.

 extern "C" { static int fun_c(int, int) __attribute__ ((weakref ("fun"))); }; int fun(int a, int b) { return fun_c(a, b); } 

No special linker flags are required.

Update: the above code does this in the opposite direction, C ++ - call-C. The requested direction is as follows:

 static int fun_cpp(int, int) __attribute__ ((weakref ("manglednameforfun"))); extern "C" int fun(int a, int b) { return fun_cpp(a, b); } 

Obviously, you need to know the name you are looking for for "fun."

As a side note, none of the solutions can be standard-compatible, since standard views do not allow you to have two functions with the same name and different language relationships.

+2
source

The following @Deduplicator suggestion, here's how to do it with the linker and only one wrapper file:

$ cat glue.cpp

 int fun(int, int); #ifdef __cplusplus extern "C" { #endif int __wrap_fun(int in1, int in2) { return fun(in1, in2); } #ifdef __cplusplus } #endif 

Pass --wrap = fun for the linker:

 g++ -Wl,--wrap=fun file1.o file2.o glue.o -o exe.out 

It works, thanks!

Any other ideas? :)

+1
source

Source: https://habr.com/ru/post/1208368/


All Articles