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

时间:2017-10-20 20:43:06

标签: c++ c

有没有办法从C源文件中调用C ++函数,而不使用C ++文件中函数声明之前的extern“C”,例如:

//C++ source file

extern "C" void func_name();

void func_name()
{
.... 
}

3 个答案:

答案 0 :(得分:2)

不使用extern" C"直接是手动确定受损名称并从C调用;这基本上只是做extern" C"但手动。任何优点都没有任何意义或目的或替代方法。

答案 1 :(得分:2)

我不知道C和C ++编译器的任何组合提供了官方支持的方法来执行此操作。你应该使用extern" C"在C ++端头文件。

但是,也许你还是要这样;我可以想到除了家庭作业之外的几个原因,例如当你有一个第三方C ++库,其界面可以从C调用但是开发人员忽略了放置extern&# 34; C"在标题中,您无法重新编译它。

通常是非正式的方法:你必须找出C ++函数的受损名称,以及它所拥有的任何隐藏参数({{ 1}}几乎总是被视为隐藏的第一个参数,可能还有其他参数)。然后使用损坏的名称和完整的参数列表在C端写一个声明。

这是一个非常简单的示例,可以在大多数操作系统和CPU上使用GCC:

this

因为这是作业,所以我不打算给你一个更复杂的例子,但我会指出你所谓的" Itanium C++ ABI",它指明了如何修剪隐藏的参数适用于大多数操作系统和CPU上的GCC和Clang。 (请注意,MSVC使用完全不同的,未记录的方案。我听说有传言说Clang现在可以选择使用MSVC的方案但是我不确定我是否相信它,考虑到这将是一项巨大的逆向工程工作。 - )

(如果您想知道,错误的名称是链接器中如何实现函数和运算符重载。如果我的/* 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; } 同时定义了file1.cppvoid foo(void),那么会产生一个导出受损名称void foo(int)_Z3foov的对象文件。)

答案 2 :(得分:1)

你可以写一个单独的翻译单元,让我们说mycppunit.cpp包含你的void func_name()实现,而不需要extern "C"个声明。使用C ++编译器将此转换单元编译为二进制文件,例如,产生mycppunit.o二进制文件;然后,使用像nm这样的命令行工具来查找函数名称是如何被修改的:例如:

nm mycppunit.o | grep func_name

会给出像

这样的东西
000000010006a920 T __Z9func_namev

然后你可以假设有一个功能void _Z9func_namev()可用,你可以写一个翻译单元,例如`my_c_program.c,以下内容:

void _Z9func_namev();

int main() {
    _Z9func_namev();
}

使用C编译器进行编译并将其与mycppunit.o链接在一起将得到所需的结果。

希望这就是你要找的东西。