函数指针赋值在C中有效但不在C++中

Jer*_*ock 6 c++ function-pointers dynamic-linking

我需要在运行时在Mac OS X中动态链接到库函数.在Apple的示例之后,我声明了一个函数指针并为其指定了dlsym()的结果.以下示例成功编译为普通C(.c)文件.但我需要在C++文件中使用它,如果我将此示例编译为C++文件(.cpp),则clang编译器会告诉我

无法使用'void '类型的右值初始化'void()(char*)' 类型的变量

为什么它在简单的'C'中工作,我该如何解决这个问题?

#include <dlfcn.h>

void Test() {
    // Load the library which defines myFunc
    void* lib_handle = dlopen("myLib.dylib", RTLD_LOCAL|RTLD_LAZY);

    // The following line is an error if compiled as C++
    void (*myFunc)(char*) = dlsym(lib_handle, "myFunc");

    myFunc("Hello");

    dlclose(lib_handle) ;
}
Run Code Online (Sandbox Code Playgroud)

Pet*_*ker 7

dlsym回报void*.在POSIX中(但不是标准的C,正如James所指出的那样)存在从void*指向函数类型的隐式转换,因此赋值myFunc只是起作用.在C++中没有隐式转换(因为它不是类型安全的),所以你需要通过添加一个强制转换来告诉编译器你真正的意思:

void (*myFunc)(char*) = (void(*)(char*))dlsym(lib_handle, "myFunc");
Run Code Online (Sandbox Code Playgroud)

(或者你可以使用a reinterpret_cast).

  • 我所说的C标准的版本说,指向`void`的指针可以转换为指向任何_object_类型的指针(强调添加).函数不是对象类型,C从不允许在`void*`和指向函数的指针之间进行转换(显式或隐式).我不确定,但我认为需要诊断.(我不认为它是未定义的行为.)而且显式转换(甚至`reinterpret_cast`)也不应该工作.(大多数Unix编译器在这方面都不一致,但由于它是一个扩展,每个编译器都可以自由地做它喜欢的.) (2认同)