当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《在C++中,为CAPI回调使用静态成员函数指针是安全/可移植的吗?》经验,为你挑选了3个好方法。

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



1> Michael Burr..:

根据C++标准,这是不安全的.正如指出该SO发帖:

在C++中实现的AC回调函数必须是extern"C".它似乎在类中作为静态函数工作,因为类静态函数通常使用与C函数相同的调用约定.但是,这样做是一个等待发生的错误(请参阅下面的评论),所以请不要 - 通过外部"C"包装来代替.

根据Martin York在该答案中所做的评论,在某些平台上尝试这样做存在实际问题.

进行C ABI回调extern "C".


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

3.5"计划和联系":

在对类型进行所有调整之后(在其中typedefs(7.1.3)被其定义替换),引用给定对象或函数的所有声明指定的类型应该是相同的,除了数组对象的声明可以指定数组类型是否存在主阵列界限(8.3.4).违反此规则的类型标识不需要诊断.[3.5/10]

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

7.5"连杆规格":

......具有不同语言联系的两种函数类型是不同的类型,即使它们在其他方面是相同的.[7.5/1]

因此,如果进行回调的代码使用C语言绑定进行回调,那么回调目标(在C++程序中)也必须如此.



2> 小智..:

在搜索并在攻击其他问题的几次休息之后,我找到了一个清晰简洁的答案(无论如何,为了标准):

通过表达式调用函数,该表达式的函数类型具有与被调用函数定义的函数类型的语言链接不同的语言链接,这是未定义的.[5.2.2/1]

我仍然认为它是在最基本的层面问题的使用从C++标准文本定义与C编译器编译C库的行为,究竟该如何互操作性中介的工作原理是很实现特定的; 然而,这是我认为最接近标准可以(目前)希望定义这种互动.

特别是,这是未定义的行为(并且不使用C库,因此不会出现问题):

void call(void (*pf)()) { pf(); } // pf() is the UB
extern "C" void f();
int main() { call(f); }
// though I'm unsure if a diagnostic is required for call(f)

Comeau确实给出了诊断call(f)(尽管即使不需要诊断也能做到这一点).

这不是未定义的行为,并显示了如何在函数指针类型中包含语言链接(通过typedef):

extern "C" typedef void F();
void call(F* pf) { pf(); }
extern "C" void f();
int main() { call(f); }

或者可以写成:

extern "C" {
typedef void F();
void f();
}
void call(F* pf) { pf(); }
int main() { call(f); }



3> 小智..:

对于我所知道的所有Windows C++编译器,答案是肯定的,但语言标准中没有任何内容可以保证这一点.但是,我不会让你停止,这是使用C++实现回调的一种非常常见的方法 - 你可能会发现你需要将静态函数声明为WINAPI.这是从我自己的旧线程库中获取的:

class Thread {
   ...
   static DWORD WINAPI ThreadFunction( void * args );
};

这是te Windows线程API的回调使用.


我并没有真正看到这一点.我的意思是,如果函数是一个静态成员*无论如何*,为什么不只是通过首先通过一个非成员函数来安全地进行操作?
它破坏了什么编译器.在我上一份工作中,我编译了ACE/TAO以及25个编译器/ OS /硬件配置的公司代码.在每个配置上内置8个(调试/发布 - 单多线程 - 共享/静态库)风格.在那200个版本中,我发现3中的问题(我有三个可重现的问题,我可以调试)它可能会影响其他人,但我花了很长时间才找出问题并修复.确切的编译器/版本逃脱了我(它是5年前),但我认为它是一个较旧的Sun编译器和较旧的AIX编译器,我可能是错的.它们是旧版本的编译器
推荐阅读
Gbom2402851125
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有