有没有办法从C源文件中调用C ++函数,而不使用C ++文件中函数声明之前的extern“C”,例如:
//C++ source file
extern "C" void func_name();
void func_name()
{
....
}
答案 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.cpp
和void 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
链接在一起将得到所需的结果。
希望这就是你要找的东西。