Mitaka
Mitaka

Reputation: 27

Calling a global function defined in C++ source file , from a C source file

Is there any way to call a C++ function from a C source file , without using extern "C" prior to the function declaration in the C++ file e.g :

//C++ source file

extern "C" void func_name();

void func_name()
{
.... 
}

Upvotes: 2

Views: 1415

Answers (3)

Stephan Lechner
Stephan Lechner

Reputation: 35154

You could write a separate translation unit, let's say mycppunit.cpp containing your void func_name() implementation without any extern "C" declarations. Compile this translation unit into a binary using a C++ compiler, yielding, for example, a mycppunit.o binary; then, use a command line tool like nm to find out how the function name has been mangled: For example:

nm mycppunit.o | grep func_name

would give something like

000000010006a920 T __Z9func_namev

Then you may assume that there will be a function void _Z9func_namev() available, and you can write in a translation unit, e.g. `my_c_program.c, the following:

void _Z9func_namev();

int main() {
    _Z9func_namev();
}

Compiling this with a C compiler and linking it together with the mycppunit.o will give the desired result.

Hope it is what you are looking for.

Upvotes: 1

zwol
zwol

Reputation: 140540

I'm not aware of any combination of C and C++ compilers that provide an officially supported way to do this. You're supposed to use extern "C" in the C++-side header files.

However, perhaps you have to anyway; I can think of several reasons other than homework, such as when you've got a third-party C++ library with an interface that could be invoked from C but the developers neglected to put extern "C" in the headers, and you can't recompile it.

There is usually an unofficial way to do it: you have to find out the mangled name of the C++ function, and any hidden parameters that it has (this is almost always treated as a hidden first parameter, and there may be others). You then write a declaration on the C side using the mangled name and the full parameter list.

Here is a very simple example that will work with GCC on most operating systems and CPUs:

/* file1.cpp */
#include <cstdio>
void foo()
{
    puts("hello from foo");
}

/* file2.c */
#include <stdio.h>
extern void _Z3foov(void);
int main(void)
{
    puts("hello from main");
    _Z3foov();
    return 0;
}

Because this is homework I am not going to give you a more complicated example, but I am going to point you at the so-called "Itanium C++ ABI", which specifies how the mangling and the hidden parameters work with GCC and Clang on most operating systems and CPUs. (Be aware that MSVC uses a completely different, undocumented, scheme. I have heard rumors that Clang can optionally use MSVC's scheme now but I'm not sure I believe it, considering how gargantuan a reverse-engineering job it would have been. ;-)

(In case you're wondering, mangled names are how function and operator overloading are implemented in the linker. If my file1.cpp had defined both void foo(void) and void foo(int), that would have produced an object file exporting the mangled names _Z3foov and _Z3fooi.)

Upvotes: 2

Puppy
Puppy

Reputation: 146910

The only way to not use extern "C" directly is to manually determine the mangled name and call that from C; which is essentially just doing extern "C" but manually. There's no point or purpose or alternative method with any merit whatsoever.

Upvotes: 2

Related Questions