6

我需要在 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) ;
}
4

2 回答 2

7

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

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

(或者你可以喜欢 a reinterpret_cast)。

于 2013-05-31T18:31:42.447 回答
0

因为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() ) );
}

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

于 2013-05-31T18:48:28.303 回答