5

In a C program I need to get a reference to a function located in a library written in C++.
Here is the part of the code

// Some C includes
#include <cpplib.h>
.
.
.
// A C structure attribute pointing to the C++ function
infoptr.EXT_meshAdapt = &meshAdapt;

The problem is the compiler tell me there is a undefined reference to meshAdapt, while when I do the same with a C library there is no problems.

In this thread I saw we can call a C++ function in C by making a wrapper. But is there a way to refer a C++ function without making a wrapper ?

Community
  • 1
  • 1
Phantom
  • 833
  • 1
  • 9
  • 26
  • 1
    You might be able to do it by using the mangled name of the C++ function, but it seems like an ugly hack. – Paul R Apr 27 '16 at 07:41
  • What do you mean ? (i don't really know C++) – Phantom Apr 27 '16 at 07:46
  • If `meshAdapt` is supposed to be callable from `C`, then you should likely declare it in the header (and implement it in its lib) as `extern "C"`. The only way I see that not working is if the function needs overloads, in which case an `extern "C"` wrapper is about your only near-trivial option. – WhozCraig Apr 27 '16 at 07:48
  • The problem is i can't modify the C++ header. – Phantom Apr 27 '16 at 07:58
  • @Phantom : Are you getting only one such error? Or many undefined references? Also which compiler and what environment? – sjsam Apr 27 '16 at 08:00
  • Yes, it's the only call to a C++ function in the program – Phantom Apr 27 '16 at 08:00
  • @Phantom : Updated the comment, Do you have access to the source code for C++ library? – sjsam Apr 27 '16 at 08:01
  • I'm under linux, using gcc. Yes I do, but it's preferable to do not change anything in it. – Phantom Apr 27 '16 at 08:04

4 Answers4

7

Usually, compilers in C++ mangles the name of functions. Which means function you write to add two numbers as

int add(int a, int b);

would be mangled. ( means it would look something like @ZVVVZaddDFD ). So, if you want to use this function from C code then you have to call @ZVVVZaddDFD not add.

Or better option is to request the compiler to avoid mangling for your functions which you intend to use in C code.

You can do that by :-

extern "C"
{
    int add(int a, int b);
}
ravi
  • 10,994
  • 1
  • 18
  • 36
4

As said in other answers, C++ mangles the identifiers of function. This is done to allow function overloads, since different overloads get different mangled names and the linker can then identify them.

Unfortunately, name mangling is not specified by the standard, so different compilers (or different versions of a compiler) can use different mangling scheme.

So the only portable way is to declare the function itself or a wrapper around it if it could support overloads as extern "C" to ask the compiler to generate an unmangled identifier.

So here you could do (in C++ code):

extern "C" {
    int c_meshAdapt() {
        return meshAdapt();
    }
}

and in C code:

infoptr.EXT_meshAdapt = &c_meshAdapt;
Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252
1

When compiling a C++ program, names are mangled. Using an extern "C" block prevents the compiler from mangling what's inside of it.

Now if you don't want to use the "wrapper" extern "C" @Paul suggested that you used the mangled name.

Unda
  • 1,827
  • 3
  • 23
  • 35
0

This is based on the assumption that you have only one undefined reference error.

From the C++ source copy the function to which you get an undefined reference. Suppose that it is calsum() . Lets do it the C++ way.

Create C-ified version of the function

Write a new program say mymath.cpp with just the function. Suppose the source code for the function is below.

extern "C" int calsum(int x,int y) 
/*I have added an extern "C" for the reasons others suggested*/
{
return x+y;
}

compile the program

g++ -c mymath.cpp -o mymath.o

By now you should have the object code in the file mymath.o

Create a library

Do :

ar -src libmymath.a mymath.o

In the above step, you're just adding creating a static library named libmymath.a and adding mymath.o to it. See the man page for ar in case of doubt. Replace all these names with sensible names

Finally

Compile your C program, do

gcc your_c_program.c -o your_c_program.elf -L. -lmymath

and you're done.

sjsam
  • 21,411
  • 5
  • 55
  • 102