我需要在运行时在Mac OS X中动态链接到库函数。在Apple's example之后,我声明一个函数指针并为其指定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) ;
}
答案 0 :(得分:7)
dlsym
返回void*
。在POSIX中(但不是标准C,正如James所指出的那样)存在从void*
到指向函数类型的隐式转换,因此对myFunc
的赋值才有效。在C ++中没有隐式转换(因为它不是类型安全的),所以你需要通过添加一个强制转换来告诉编译器你真正的意思:
void (*myFunc)(char*) = (void(*)(char*))dlsym(lib_handle, "myFunc");
(或者你可以看中reinterpret_cast
)。
答案 1 :(得分: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() ) );
}
(当然还有更多错误检查)。