3

我正在使用 objcopy 将文本文件转换为目标文件,以便使用 MinGW 和 MinGW-64 与我的 DLL 链接。使用 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 位)中找不到。我确实尝试了 objcopy 的 --remove-remove-leading-char 选项,但这没有效果。据我所见,我的选择是在为 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 回答