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

Function Pointer assignment works in C but not C++

本文关键字:但在 C++ 无效 有效 函数 赋值 指针      更新时间:2023-10-16

我需要在Mac OS X的运行时动态链接到库函数。以苹果为例,我声明了一个函数指针,并用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) ;
}

dlsym返回void*。在POSIX中(但不是标准的C,正如James所指出的(,有一个从void*到函数类型指针的隐式转换,所以对myFunc的赋值就是有效的。在C++中没有隐式转换(因为它不是类型安全的(,所以你需要通过添加一个强制转换来告诉编译器你真正是认真的:

void (*myFunc)(char*) = (void(*)(char*))dlsym(lib_handle, "myFunc");

(或者你可以用reinterpret_cast来获得乐趣(。

因为C编译器坏了。没有转换(显式或隐式(在void*和指向函数,既不在C中也不在C++中。

Posix为C添加了一个限制,并要求void*和指向函数的指针具有相同的大小和表示方式,因此即:

void (*myFunc)( char * );
*(void (**myFunc)( char* ))( &myFunc ) = dlsym(...);

将起作用。

在C++中,您可能希望使用以下内容:

class GetFunctionHelper;
GetFunctionHelper getFunction( void* dlHandle, std::string const& functionName );
class GetFunctionHelper
{
    void* fromSystem;
    freind GetFunctionHelper getFunction( void* , std::string const& );
    GetFunctionHelper( void* fromSystem ) : fromSystem( fromSystem ) {}
public:
    template <typename Ptr> operator Ptr() const
    {
        return *reinterpret_cast<Ptr const*>( &fromSystem );
    }
};
GetFunctionHelper
getFunction( void* dlHandle, std::string const& functionName )
{
    return GetFunctionHelper( dlsym( dlHandle, functionName.c_str() ) );
}

(当然还有更多的错误检查(。

相关文章: