Question

I'm using objcopy to convert a text file into an object file for linking with my DLL using MinGW and MinGW-64. With MinGW, everything works fine, but with MinGW-64 I get errors of the form "undefined reference to `binary_src_glsl_RGBtoHSV_glsl_end'". The original file is called RGBtoHSV.glsl and is in the folder binary\src\glsl. In the output from objcopy the variable name is _binary_src_glsl_RGBtoHSV_glsl_end. My code to access the variables for that file is as follows:

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);

If I change the variable names so that they have an undercore in front, e.g.:

extern "C" const char _binary_src_glsl_RGBtoHSV_glsl_start;

Then that symbol is found in MinGW-64, but not in MinGW (32 bits). I did try the --remove-remove-leading-char option to objcopy but that had no effect. As far as I can see, my options are to either add an underscore to the variable names generated by objcopy by using "--prefix-symbol _" when building for MinGW 32 bits, in which case the above variable name will work in 32 and 64 bits.

Is there another solution to this problem? Ideally I'd like something along the lines of

extern "C" fix_underscore_problem const char binary_src_glsl_RGBtoHSV_glsl_start;

Where fix_underscore_problem is a magic command to fix the leading underscore problem.

Update (2012-07-01): Using the advice given in Adding leading underscores to assembly symbols with GCC on Win32? I changed by header file to use

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

This seems to fix the problem, but now I wonder how portable this is. Is there an equivalent syntax available in MSVC or a C++ standard way of doing this?

Était-ce utile?

La solution

Well, I've solved the problem, sort of, by defining a macro that creates a variable with the leading underscore, if needed. Then it creates a function that returns a pointer to the variable. The function name will always be the name passed to the macro, so the rest of my code can just use that function name instead. The macro is:

#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

I'd appreciate any suggestions for improving this solution. Especially anything I can add to the branch that deals with compilers other than GCC and MSVC, since I have no experience with them.

As a side note, I also tried using ld to make the object file containing my text, but that suffered from the same problem that no matter what option I used, I couldn't remove the leading underscore.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top