6

Mac OS X で実行時にライブラリ関数に動的にリンクする必要があります。Apple の例に従って、関数ポインタを宣言し、dlsym() の結果を割り当てます。次の例は、プレーン C (.c) ファイルとして正常にコンパイルされます。しかし、これは C++ ファイルで必要であり、この例を C++ ファイル (.cpp) としてコンパイルすると、clang コンパイラが教えてくれます。

型 'void ( )(char *)' の変数を型 'void 'の右辺値で初期化することはできません

プレーンな「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

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 に答える