且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

在C ++中,它是安全/可移植的使用静态成员函数指针为C API回调吗?

更新时间:2022-11-23 19:48:45

根据C ++标准是不安全的。如此SO发布中所述:


在C ++中实现的AC回调函数必须是externC。它可能似乎在类中作为静态函数工作,因为类静态函数通常使用与C函数相同的调用约定。但是,这是一个等待发生的错误(见下面的注释),所以请不要 - 通过externC包装。


根据 Martin York 在该答案中提出的意见,存在真实问题,试图



使用C ABI回调 externC






编辑:从标准中添加一些支持引号(强调我的):



3.5 程序和链接:


在所有类型调整之后(其间typedef(7.1.3) strong>引用给定对象或函数的所有声明指定的类型应该是相同的,除了数组对象的声明可以指定由于存在或不存在主数组边界而不同的数组类型(8.3.4 )。违反此类关于类型身份的规则不需要诊断。 [3.5 / 10]



[注意:可以使用链接规范(7.5)实现与非C ++声明的链接。 ] [3.5 / 11]



...具有不同语言链接的两个函数类型是不同类型,即使它们是相同的。 [7.5 / 1]


所以如果回调的代码使用C语言绑定的回调, C ++程序)也必须如此。


In C++, is it safe/portable to use static member function pointer for C API callbacks? Is the ABI of a static member function the same as a C function?

It is not safe per the C++ standard. As stated in this SO posting:

A C callback function implemented in C++ must be extern "C". It may seem to work as a static function in a class because class-static functions often use the same calling convention as a C function. However, doing that is a bug waiting to happen (see comments below), so please don't - go through an extern "C" wrapper instead.

And according to comments made by Martin York in that answer there are real-world problems trying to do so on some platforms.

Make your C ABI callbacks extern "C".


Edit: Adding some supporting quotes from the standard (emphasis mine):

3.5 "Program and linkage":

After all adjustments of types (during which typedefs (7.1.3) are replaced by their definitions), the types specified by all declarations referring to a given object or function shall be identical, except that declarations for an array object can specify array types that differ by the presence or absence of a major array bound (8.3.4). A violation of this rule on type identity does not require a diagnostic. [3.5/10]

[Note: linkage to non-C++ declarations can be achieved using a linkage-specification (7.5). ] [3.5/11]

And

7.5 "Linkage specifications":

... Two function types with different language linkages are distinct types even if they are otherwise identical. [7.5/1]

So if the code making the callback is using C language bindings for the callback, then the callback target (in the C++ program) must as well.