加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

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

发布时间:2020-12-16 05:26:39 所属栏目:百科 来源:网络整理
导读:只要我有一个包含声明为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不支持这个
只要我有一个包含声明为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的一个较不实施的功能,因为术语的混乱混乱和从微妙到学术的概念差异.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读