简体   繁体   English

从C源文件调用C ++源文件中定义的全局函数

[英]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 eg : 有什么方法可以从C源文件调用C ++函数,而无需在C ++文件中的函数声明之前使用extern“ C”,例如:

//C++ source file

extern "C" void func_name();

void func_name()
{
.... 
}

The only way to not use extern "C" directly is to manually determine the mangled name and call that from C; 不直接使用extern“ C”的唯一方法是手动确定错误的名称并从C调用该名称。 which is essentially just doing extern "C" but manually. 这实际上只是在做外部“ C”,而是手动进行。 There's no point or purpose or alternative method with any merit whatsoever. 没有任何优点的目的,目的或替代方法。

I'm not aware of any combination of C and C++ compilers that provide an officially supported way to do this. 我不知道提供正式支持的方法的C和C ++编译器的任何组合。 You're supposed to use extern "C" in the C++-side header files. 您应该在C ++端头文件中使用extern“ C”。

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. 我可以想到除家庭作业以外的其他几个原因,例如,当您拥有一个第三方C ++库,该库具有可以从C调用的接口,但是开发人员忽略了在标头中放置extern“ C”时,您可以重新编译它。

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). 通常一个非官方的方式做到这一点:你必须找出C ++函数的重整名称 ,以及它所拥有的任何隐藏的参数( this几乎总是被视为隐藏的第一个参数,并有可能成为其他人)。 You then write a declaration on the C side using the mangled name and the full parameter list. 然后,使用变形的名称和完整的参数列表在C侧编写一个声明。

Here is a very simple example that will work with GCC on most operating systems and CPUs: 这是一个非常简单的示例,可以在大多数操作系统和CPU上与GCC一起使用:

/* 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. 因为这是家庭作业,所以我不会给您一个更复杂的示例,但是我将向您指出所谓的“ Itanium C ++ ABI ”,它指定了如何在大多数情况下使用GCC和Clang修改和隐藏参数操作系统和CPU。 (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. ;-) (请注意,MSVC使用了完全不同的 ,未记录的方案。我听说有传言说Clang现在可以选择使用MSVC的方案,但是考虑到逆向工程的工作量,我不确定我是否会相信。 - )

(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 .) (以防万一,链接器中如何实现函数名和运算符重载。如果我的file1.cpp定义了void foo(void)void foo(int) ,那将产生一个目标文件导出混乱的名称_Z3foov_Z3fooi 。)

You could write a separate translation unit, let's say mycppunit.cpp containing your void func_name() implementation without any extern "C" declarations. 您可以编写一个单独的转换单元,假设mycppunit.cpp包含您的void func_name()实现,而没有任何extern "C"声明。 Compile this translation unit into a binary using a C++ compiler, yielding, for example, a mycppunit.o binary; 使用C ++编译器将此翻译单元编译为二进制文件,例如,生成mycppunit.o二进制文件; then, use a command line tool like nm to find out how the function name has been mangled: For example: 然后,使用诸如nm的命令行工具来查找函数名称的处理方式:例如:

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, eg `my_c_program.c, the following: 然后,您可以假定将有一个可用的void _Z9func_namev()函数,并且您可以在以下翻译单元(例如`my_c_program.c)中进行编写:

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. 使用C编译器对此进行编译,并将其与mycppunit.o链接在一起将产生所需的结果。

Hope it is what you are looking for. 希望它是您想要的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM