【问题标题】:extern "C" for member static callback functionextern "C" 用于成员静态回调函数
【发布时间】:2017-09-21 06:31:49
【问题描述】:

我想为用 Haskell (GHC) 编写的代码提供回调函数。它使用类似 GCC C 编译器的函数类型来导出/导入功能,并在运行时与我的代码进行互操作。

我必须提供一个回调函数,它实际上接受this 指向该类的指针并调用它的方法:

struct C
{
    int f(int i) { ; }
    static int f_callback(void * self, int i)
    {
        static_cast< C * >(self)->f(i);
    }
};

逻辑上f_callbackC 类的一部分,所以我把它放到了相应的命名空间范围内。

但我担心我应该使用extern "C" 语言规范(调用约定在这里很重要,而不是名称修改)?可以在普通命名空间中声明和定义extern "C" 函数,对于在不同命名空间中定义相同名称的extern "C" 函数有一些特殊规则,但there is 没有类范围的命名空间和简单命名空间的区别一个。

是否可以将static extern "C" 函数定义到类范围内?

【问题讨论】:

  • 不,这是不可能的 IIRC。但是您不必担心 C 和 C++ 使用不同的 ABI 或堆栈框架。
  • @user0042 会比static __cdecl 更安全吗?
  • 这是一个不可移植的注释,但是你可以使用它。
  • 你可以在外面写一个包装器来调用这个静态函数并用extern "C"标记它
  • @AjayBrahmakshatriya 通常 C 回调函数应标记为 noexcept 或手动捕获异常并将其转换为适合调用代码的错误报告形式。

标签: c++ c callback language-lawyer extern


【解决方案1】:

外部回调设计为未链接到特定类。

根据代码的内部结构,将其设为静态类成员可能很好,但它歪曲了现实。

因此,我建议将其设为独立的外部“C”函数。这避免了误解并突出了假设(例如,self 被假定为 C,但实际上可能是其他东西)。如果 f() 是公开的,那么这一切都会非常干净。如果它是私有的,您需要将您的回调设为朋友,并且这种紧密耦合将再次突出显示。

包装替代方案只会添加一个多余的中间人来达到相同的结果。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-04-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-16
    相关资源
    最近更新 更多