静态成员函数和extern"C"链接函数之间有什么区别?例如,在C++中使用"makecontext"时,我需要传递一个指向函数的指针.谷歌建议使用extern"C"链接,因为"makecontext"是C.但我发现使用静态工作也是如此.我只是幸运还是......
class X { public: static void proxy(int i) {} } makecontext(..., (void (*)(void)) X::proxy, ...);
VS
extern "C" void proxy(int i) {} makecontext(..., (void (*)(void)) proxy, ...);
编辑:你能展示静态成员版本不起作用的编译器或架构(并且它不是编译器中的错误)吗?
是的,你只是幸运:) extern"C"是C语言的一种语言链接,每个C++编译器都必须支持,除了默认的extern"C++".编译器可能支持其他语言链接.例如,GCC支持extern"Java",它允许与java代码接口(虽然这非常麻烦).
extern"C"告诉编译器你的函数可以被C代码调用.这可以但不是必须包括适当的调用约定和适当的C语言名称修改(有时称为"装饰")等,具体取决于实现.如果你有一个静态成员函数,它的调用约定是你的C++编译器之一.它们通常与该平台的C编译器相同 - 所以我说你很幸运.如果你有一个C API并且你传递了一个函数指针,那么最好总是把一个放到用extern"C"声明的函数中
extern "C" void foo() { ... }
即使函数指针类型不包含链接规范,但看起来像
void(*)(void)
链接是类型的组成部分 - 如果没有typedef,你就无法直接表达它:
extern "C" typedef void(*extern_c_funptr_t)();
严格模式下的Comeau C++编译器将发出错误,例如,如果您尝试将上面的extern"C"函数的地址分配给a (void(*)())
,因为这是指向具有C++链接的函数的指针.
注意,这extern C
是C/C++互操作性的推荐方式.这是主人谈论它.添加到eduffy的答案:请注意,不推荐使用全局命名空间中的静态函数和变量.至少使用匿名命名空间.
回到extern C
:如果你不使用extern C,你必须知道确切的受损名称并使用它.这更令人痛苦.