【问题标题】:C linkage for function pointer passed to C library传递给 C 库的函数指针的 C 链接
【发布时间】:2013-05-07 10:07:38
【问题描述】:

我的情况很简单:我希望我的 C++ 程序能够处理 Unix 信号。为此,glibc 在 signal.h 中提供了一个名为 sigaction 的函数,该函数期望接收一个函数指针作为其第二个参数。

extern "C"
{
void uponSignal(int);
}

void uponSignal(int)
{
    // set some flag to quit the program
}

static
void installSignalHandler()
{
    // initialize the signal handler
    static struct sigaction sighandler;
    memset( &sighandler, 0, sizeof(struct sigaction) );
    sighandler.sa_handler = uponSignal;

    // install it
    sigaction( SIGINT, &sighandler, nullptr );
}

我的问题是:extern "C" 链接说明符是否必要?

额外问题:可以将 onSignal 声明为static吗?

【问题讨论】:

  • 如果你删除extern "C",一些编译器会直接拒绝编译它,因为 sigaction 的第二个参数类型错误。许多编译器的一个错误是他们不考虑函数类型的链接部分。

标签: c++ c signals glibc linkage


【解决方案1】:

extern C 仅在您从二进制文件中导出符号或从另一个二进制文件(通常在这两种情况下都是共享库)中导入符号时才需要,以避免名称混淆。

情况并非如此,您没有在各种二进制文件之间链接uponSignal,因此您不需要extern C。你所做的只是将你的函数地址从一个已经知道uponSignal地址的函数传递给sigaction,因为它们(显然)是同一个翻译单元的一部分,或者至少是同一个二进制文件。

额外问题:uponSignal 可以声明为static吗?

如果你愿意,当然可以。 uponSignal 反正不需要外部链接。

【讨论】:

  • 实际上,我更担心调用约定而不是名称修改。
  • 你不应该。 ;) 尽管调用约定是特定于实现的(即超出标准范围),但我从未见过没有将调用约定作为函数签名的一部分的编译器,因此编译器会在存在时警告您ever 是不匹配的(无论如何很少发生)。
【解决方案2】:

我的问题是:extern "C" 链接说明符是否必要?

为了最大的便携性,是的; C++ 标准仅通过声明为 extern "C" 的函数保证与 C 的互操作性。

实际上,没有;大多数明智的 ABI(包括 glibc 使用的 GNU ABI)将对 C 和 C++ 非成员(和静态成员)函数使用相同的调用约定,因此只需要 extern "C" 在语言之间共享函数名。

额外问题:uponSignal 可以声明为静态吗?

是的。外部链接只需要从其他翻译单元通过名称访问功能;不需要通过函数指针调用函数。

【讨论】:

  • 您能否引用一句“C++ 标准仅通过声明为 extern "C" 的函数保证与 C 的互操作性”?
  • @qdii: 不是真的;没有什么明确说没有保证,只是没有提供保证。 7.5/1 指定“具有不同语言链接的两个函数类型是不同的类型,即使它们在其他方面相同”,并且有一个注释指出“特定语言链接可能与 [...] 特定调用约定等相关联。”
猜你喜欢
  • 2013-09-17
  • 1970-01-01
  • 2020-12-10
  • 2013-04-28
  • 2011-04-17
  • 1970-01-01
  • 1970-01-01
  • 2019-03-12
相关资源
最近更新 更多