Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Glueing C and C++ object files without source code

Tags:

c++

c

linker

There are two object files. On of them contains definition (the body) of a function. This object file was compiled with C++ compiler, so the function name is mangled. The second object file references (calls) the function from the first object file. However, the second object file was compiled with C compiler, so the function name is not mangled. When linking these two object files, there is an error for undefined symbol. It is not possible to change the source files so that the C++ object file uses extern "C" definitions and doesn't mangle the function name. It is however possible to write whatever glue (wrapper) code, compile it with C++ compiler and link together with those 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 to change those:

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

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

$ 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 link those wrappers together with 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

What do you think, guys, is there another way? This have become simply an academic interest now for me :)

like image 847
Bessel Avatar asked Sep 29 '22 07:09

Bessel


1 Answers

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 needed.

Update: the above code does it in the opposite direction, C++-calling-C. The requested direction goes like this:

static int fun_cpp(int, int) __attribute__ ((weakref ("manglednameforfun")));


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

You need to know the mangled name for "fun" obviously.

As a side note, no solution can be standard-conforming, as the standard dows not allow to have two functions with the same name and different language linkages.

like image 163
3 revs Avatar answered Oct 04 '22 03:10

3 revs