Включая двоичный двоичный объект из objcopy как в MinGW 32, так и в 64.

Я использую objcopy для преобразования текстового файла в объектный файл для связывания с моей DLL с помощью MinGW и MinGW-64. С 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, но это не дало никакого эффекта. Насколько я вижу, мои варианты состоят в том, чтобы либо добавить подчеркивание к именам переменных, сгенерированных objcopy, используя «--prefix-symbol _» при сборке для MinGW 32 бит, и в этом случае указанное выше имя переменной будет работать в 32 битах. и 64 бит.

Есть ли другое решение этой проблемы? В идеале я хотел бы что-то вроде

extern "C" fix_underscore_problem const char binary_src_glsl_RGBtoHSV_glsl_start;

Где fix_underscore_problem — это волшебная команда для исправления проблемы с подчеркиванием.

Обновление (01.07.2012): использование рекомендаций, приведенных в Добавить начальные символы подчеркивания к символам сборки с помощью GCC в Win32? Я изменил файл заголовка, чтобы использовать

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

Кажется, это решает проблему, но теперь мне интересно, насколько это портативно. Есть ли эквивалентный синтаксис, доступный в MSVC или стандартный способ C++?


person chippies    schedule 30.06.2012    source источник


Ответы (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 для создания объектного файла, содержащего мой текст, но он страдал от той же проблемы, что независимо от того, какую опцию я использовал, я не мог удалить начальное подчеркивание.

person chippies    schedule 03.07.2012