struct A { // error C2159: more than one storage class specified (VC++ Nov 2012 CTP) static extern "C" void callback() {} }; g(A::callback);
为什么C11不支持这个?
解决方法
1) All function types,function names with external linkage,and variable names with external linkage have a language linkage.
请注意,语言联动的属性适用于两种完全不同类型的实体:类型和名称.
一个函数在其类型中具有通常不可见的信息位,它标识符合哪个ABI:C调用约定,Pascal,Fortran,都可能被指定为以不同的方式使用堆栈,因此通过指针调用它们需要知道隐形语言标签.
来自另一种语言的变量或函数的名称可以通过C语法来访问,也可以从引用C语句的其他语言来访问.但并不是每一种语言都可以与C的命名方案和OO模型相匹配.因此,该方案中的接口不包括类.
因为这些东西是单独管理的,所以可以在其类型(调用约定)及其名称(链接符号)中具有不同链接的东西.
4) Linkage specifications nest. When linkage specifications nest,the innermost one determines the language
linkage. A linkage specification does not establish a scope. A linkage-specification shall occur only in namespace scope (3.3). In a linkage-specification,the specified language linkage applies to the function types of all function declarators,and variable names with external linkage declared within the linkage-specification. A C language linkage is ignored in determining the language linkage of the names of class members and the function type of class member functions.
外部“C”{}影响除成员函数之外的所有函数声明,包括指针和引用.由于函数只能在命名空间或成员中定义,所以只能在命名空间范围内定义C函数.
这个标准给出了一个例子:
extern "C" typedef void FUNC_c(); class C { // the name of the function mf1 and the member // function’s type have C++ language linkage; the // parameter has type pointer to C function void mf1(FUNC_c*); // the name of the function mf2 and the member // function’s type have C++ language linkage FUNC_c mf2; // the name of the data member q has C++ language // linkage and the data member’s type is pointer to // C function static FUNC_c* q; };
你可以使用typedef来模拟你想要的行为.从§7.5/ 4的另一个例子,
extern "C" typedef void FUNC(); // the name f2 has C++ language linkage and the // function’s type has C language linkage FUNC f2;
将这些例子与你的结合在一起,你可以拥有
extern "C" typedef void callback_t(); callback_t A_callback; // declare function with C++ name and C type struct A { static callback_t &callback; // not a member function }; // in source file: // definition matches semantics of declaration,although not Syntax void A_callback() { ... } // define static member reference callback_t &A::callback = A_callback; g(A::callback); // call Syntax is emulated
在实践中,很少有所作为. C和C在大多数平台上使用兼容的调用约定(请参阅Jonathan Wakely在此页面上的异常注释),只要不尝试传递或返回非POD C类类型即可.这是C的一个较不实施的功能,因为术语的混乱混乱和从微妙到学术的概念差异.