3

MinGW と MinGW-64 を使用して DLL とリンクするために、objcopy を使用してテキスト ファイルをオブジェクト ファイルに変換しています。MinGW ではすべて正常に動作しますが、MinGW-64 では「`binary_src_glsl_RGBtoHSV_glsl_end' への未定義の参照」という形式のエラーが発生します。元のファイルは RGBtoHSV.glsl という名前で、binary\src\glsl フォルダーにあります。objcopy からの出力では、変数名は _binary_src_glsl_RGBtoHSV_glsl_end です。そのファイルの変数にアクセスするための私のコードは次のとおりです。

extern "C" const char binary_src_glsl_RGBtoHSV_glsl_start;
extern "C" const char binary_src_glsl_RGBtoHSV_glsl_end;
const std::string RGBtoHSV = std::string(&binary_src_glsl_RGBtoHSV_glsl_start, &binary_src_glsl_RGBtoHSV_glsl_end-&binary_src_glsl_RGBtoHSV_glsl_start);

変数名を変更して、前にアンダーコアを付けると、次のようになります。

extern "C" const char _binary_src_glsl_RGBtoHSV_glsl_start;

次に、そのシンボルは MinGW-64 で見つかりますが、MinGW (32 ビット) では見つかりません。--remove-remove-leading-char オプションを objcopy に試してみましたが、効果はありませんでした。私が見る限り、私のオプションは、MinGW 32 ビット用にビルドするときに「--prefix-symbol _」を使用して objcopy によって生成された変数名にアンダースコアを追加することです。この場合、上記の変数名は 32 ビットで機能します。そして64ビット。

この問題の別の解決策はありますか? 理想的には、次のようなものが欲しいです

extern "C" fix_underscore_problem const char binary_src_glsl_RGBtoHSV_glsl_start;

ここで、fix_underscore_problem は先頭のアンダースコアの問題を修正する魔法のコマンドです。

更新 (2012-07-01): Win32 で GCC を使用して先頭のアンダースコアをアセンブリ シンボルに追加するに記載されているアドバイスを使用しますか? 使用するヘッダーファイルで変更しました

extern "C" const char binary_src_glsl_RGBtoHSV_glsl_start asm("_binary_src_glsl_RGBtoHSV_glsl_start");

これで問題は解決したようですが、今ではこれがどれほど移植性があるのだろうかと思います。MSVC またはこれを行う C++ 標準の方法で利用できる同等の構文はありますか?

4

1 に答える 1

1

必要に応じて先頭にアンダースコアを付けて変数を作成するマクロを定義することで、問題を解決しました。次に、変数へのポインタを返す関数を作成します。関数名は常にマクロに渡される名前になるため、コードの残りの部分では代わりにその関数名を使用できます。マクロは次のとおりです。

#define GPUFW_STR(x) #x

#if defined(__GNUC__) | defined(__MINGW32__) | defined(__MINGW64__)
    //GCC and MinGW allow one to use the asm keyword to give a variable a
    //specific label, overriding the label used at compile time.
    #define GPUFW_BINARY_BLOB_EXTERN(T,x) extern "C" const T x asm(GPUFW_STR(_ ## x)); static const T* at_ ## x = &x;
#else
    #if defined(_MSC_VER)
        #if defined(_WIN32)
            //Visual C++ does not seem to have a method to specify a different
            //label for a variable at link time, but in 32-bit Windows
            //extern "C" variables have a leading underscore anyway.
            #define GPUFW_BINARY_BLOB_EXTERN(T,x) extern "C" const T x; static const T* at_ ## x = &x;
        #else
            //64-bit Visual C++ does not prepend an underscore to extern "C"
            //variable names, causing many problems here.  Hence define the
            //external variable as _x.
            #define GPUFW_BINARY_BLOB_EXTERN(T,x) extern "C" const T _##x; static const T* at_ ## x = &_ ## x;
        #endif
    #else
        //Unknown compiler.
        #warning Your compiler was not recognised by GPUFW.  Binary blob inclusion may produce linker errors.
        #if defined(_WIN64)
            //On 64-bit Windows most compilers seem to stick to the Visual C++
            //naming conventions.
            #define GPUFW_BINARY_BLOB_EXTERN(T,x) extern "C" const T _##x; static const T* at_ ## x = &_ ## x;
        #else
            //If all else fails, hope that the compiler uses a leading underscore.
            #define GPUFW_BINARY_BLOB_EXTERN(T,x) extern "C" const T x; static const T* at_ ## x = &x;
        #endif
    #endif
#endif

このソリューションを改善するための提案をいただければ幸いです。特に、GCC と MSVC 以外のコンパイラを扱うブランチに追加できるものはすべて、経験がないためです。

補足として、ld を使用してテキストを含むオブジェクト ファイルを作成しようとしましたが、使用したオプションに関係なく、先頭のアンダースコアを削除できないという同じ問題が発生しました。

于 2012-07-03T18:09:07.800 に答える