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

时间:2013-05-31 18:25:55

标签: c++ function-pointers dynamic-linking

我需要在运行时在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) ;
}

2 个答案:

答案 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() ) );
}

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