2

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()
{
.... 
}
5
  • 6
    Hint: What do you think extern "C" is for? Commented Oct 20, 2017 at 20:44
  • I know it works with extern "C", but my task is to try to make it without extern "C" Commented Oct 20, 2017 at 20:48
  • Why? The only way I can think of doing that is to call the mangled name from C. And I don't think you want to do that. Commented Oct 20, 2017 at 20:49
  • 1
    Why don't you want to use extern "C"? That's what it's for. Commented Oct 20, 2017 at 20:51
  • This is something like homework from the university where i study, and it is explicitly said, to find if there is a way to do it without extern "C" in the declaration . (sorry for bad english) Commented Oct 20, 2017 at 20:55

3 Answers 3

2

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.

Sign up to request clarification or add additional context in comments.

3 Comments

I can think of at least three legitimate reasons to want to do this. Also, "manually determining the mangled name" is not "just doing extern 'C' manually"; it is the opposite.
Perhaps it is a homework assignment to learn how the C++ compiler decorates names.
Yes , its exactly a homework to learn about decorations in C++ .
2

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

1 Comment

Apart from name mangling, it is also necessary to account for any difference in calling conventions and of layout of types, particularly struct or class types, that are passed as arguments or returned by the function. The REASON that the standard encourages name mangling is that there is more to calling a C++ function than just matching function names, even if the conventional linker only requires names to match.
1

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.

1 Comment

Thank you for the answer, i did it but im using Visual Studio and the mangled name is ?func_name@@YAXXZ , but i cant write symbols like ? and @ in the code. What should i do ?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.