为什么C11不支持在静态成员函数上声明extern“C”?

只要我有一个包含声明为void g(void(* callback)())的函数的C库;以下代码优雅但非法:
struct A
{
    // error C2159: more than one storage class specified (VC++ Nov 2012 CTP)
    static extern "C" void callback()
    {}
};

g(A::callback);

为什么C11不支持这个?

解决方法

这是一个特别令人困惑的话题.我们来攻击§7.5“链接规范”[dcl.link].

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的一个较不实施的功能,因为术语的混乱混乱和从微妙到学术的概念差异.

相关文章

本程序的编译和运行环境如下(如果有运行方面的问题欢迎在评...
水了一学期的院选修,万万没想到期末考试还有比较硬核的编程...
补充一下,先前文章末尾给出的下载链接的完整代码含有部分C&...
思路如标题所说采用模N取余法,难点是这个除法过程如何实现。...
本篇博客有更新!!!更新后效果图如下: 文章末尾的完整代码...
刚开始学习模块化程序设计时,估计大家都被形参和实参搞迷糊...