Incluido blob binario de objcopy en MinGW 32 y 64

Estoy usando objcopy para convertir un archivo de texto en un archivo de objeto para vincularlo con mi DLL usando MinGW y MinGW-64. Con MinGW, todo funciona bien, pero con MinGW-64 obtengo errores del tipo "referencia indefinida a `binary_src_glsl_RGBtoHSV_glsl_end'". El archivo original se llama RGBtoHSV.glsl y está en la carpeta binary\src\glsl. En la salida de objcopy, el nombre de la variable es _binary_src_glsl_RGBtoHSV_glsl_end. Mi código para acceder a las variables de ese archivo es el siguiente:

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

Si cambio los nombres de las variables para que tengan un guión bajo al frente, por ejemplo:

extern "C" const char _binary_src_glsl_RGBtoHSV_glsl_start;

Entonces ese símbolo se encuentra en MinGW-64, pero no en MinGW (32 bits). Probé la opción --remove-remove-leading-char para objcopy pero eso no tuvo ningún efecto. Por lo que puedo ver, mis opciones son agregar un guión bajo a los nombres de las variables generados por objcopy usando "--prefix-symbol _" al compilar para MinGW de 32 bits, en cuyo caso el nombre de la variable anterior funcionará en 32 y 64 bits.

¿Hay otra solución a este problema? Idealmente me gustaría algo a lo largo de las líneas de

extern "C" fix_underscore_problem const char binary_src_glsl_RGBtoHSV_glsl_start;

Donde fix_underscore_problem es un comando mágico para solucionar el problema del guión bajo principal.

Actualización (2012-07-01): Usando los consejos dados en ¿Agregar guiones bajos iniciales a los símbolos de ensamblaje con GCC en Win32? Cambié por archivo de encabezado para usar

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

Esto parece solucionar el problema, pero ahora me pregunto qué tan portátil es esto. ¿Hay una sintaxis equivalente disponible en MSVC o una forma estándar de C++ de hacer esto?

preguntado el 01 de julio de 12 a las 00:07

1 Respuestas

Bueno, he resuelto el problema, más o menos, definiendo una macro que crea una variable con el guión bajo inicial, si es necesario. Luego crea una función que devuelve un puntero a la variable. El nombre de la función siempre será el nombre pasado a la macro, por lo que el resto de mi código puede usar ese nombre de función en su lugar. La macro es:

#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

Agradecería cualquier sugerencia para mejorar esta solución. Especialmente cualquier cosa que pueda agregar a la rama que trata con compiladores que no sean GCC y MSVC, ya que no tengo experiencia con ellos.

Como nota al margen, también intenté usar ld para crear el archivo de objeto que contenía mi texto, pero sufría el mismo problema de que, independientemente de la opción que usara, no podía eliminar el guión bajo inicial.

Respondido 03 Jul 12, 19:07

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.