2012-02-16 17 views
5

(Esto es gcc 3.3.1 (larga historia -. Culpa NIST) de Cygwin)referencia indefinida cuando se enlaza dinámicamente con gcc en cygwin

he recopilado algunos archivos de origen con gcc -c -fPIC ... para obtener archivos .o.

luego hice:

$ gcc -shared -o foo.dll foo.o bar.o 

Pero cuando voy a usarlo:

$ gcc -o usefoo.exe usefoo.o -L. -lfoo 
    usefoo.o:usefoo.cpp:(.text+0x2e0): undefined reference to `_get_template_size' 
    collect2: ld returned 1 exit status 

Sin embargo, si utilizando los mismos archivos .o que en lugar de hacer:

$ ar rcs libfoo-static.a foo.o bar.o 

El enlace en contra de eso es exitoso:

$ gcc -o foo.exe foo.o -L. -lfoo-static 

Lo que me resulta extraño es que, como puede ver a continuación, la referencia en cuestión está presente tanto en .a como en .dll. Entonces, ¿por qué el error al enlazar con el .dll?

de referencia se encuentra en la biblioteca compartida:

$ nm foo.dll|grep get_template 
1001b262 T _get_template_size 

Y también en la biblioteca estática:

$ nm libfoo-static.a |grep get_template 
00000352 T _get_template_size 

Y aquí está la referencia al símbolo generado en el archivo que quiere usar el función:

$ nm usefoo.o 
00000000 b .bss 
00000000 d .data 
00000000 t .text 
0000012c T __Z12ErrorMessagei 
     U ___main 
     U __alloca 
     U _atoi 
     U _get_template_size 
0000026c T _main 
     U _printf 

actualizado para solucionar la respuesta de Marco

Curiosamente/molesto, cuando trato de hacer un ejemplo de prueba mínimo de esto no puedo hacer que suceda (a pesar de que sucede cada vez con la cosa real):

func1.h:

#ifndef FUNC1_H 
#define FUNC1_H 

int func1(int i); 

#endif 

func1.c:

#include "func1.h" 

int func1(int i) { 
    return 2*i; 
} 

usefunc.c:

#include <stdio.h> 
#include "func1.h" 

int main() { 
    printf("%d\n", func1(10)); 
} 

continuación:

$ rm *.o *.dll *.a 

$ gcc -fPIC -I. -c func1.c usefunc.c 

$ gcc -shared -o func.dll func1.o 

$ gcc -L. -o usefunc.exe usefunc.o -lfunc 

$ ./usefunc.exe 
20 

Respuesta

6

he encontrado la respuesta (en el que resuelve mi problema link) en una página web Cygwin: http://cygwin.com/cygwin-ug-net/dll.html

Lo que terminé tener que hacer era crear la biblioteca compartida y hacer el enlace final como esto:

$ gcc -shared -o cygfoo.dll \ 
     -Wl,--out-implib=libfoo.dll.a \ 
     -Wl,--export-all-symbols \ 
     -Wl,--enable-auto-import \ 
     -Wl,--whole-archive *.o \ 
     -Wl,--no-whole-archive 

$ gcc -L. -o usefoo.exe usefoo.o -lfoo 

Pero todavía me gustaría saber por qué no tuve que hacer esto para mi prueba simple.

2

no estoy del todo seguro, pero que yo sepa Windows tiene espacios de nombres por módulo (como EXE o DLL). Cuando está enlazando estáticamente está poniendo todo en un .exe, así un módulo, un espacio de nombres.

Al vincular dinámicamente, crea dos módulos (1 exe, 1 dll) y ambos tienen sus espacios de nombres.

Debe exportar el símbolo de la DLL para que esto funcione en iirc (lea en importlibs, p.en el excelente Linkers and Loaders

+0

¡Interesante! Dos cosas a tener en cuenta: (1) Con el código real en cuestión, si agrego llamadas a otras cosas en la biblioteca compartida, también aparecen como indefinidas debajo de un enlace dinámico, por lo que no es solo esa función específica. Esto apoya tu respuesta. Sin embargo ... (2) Cuando trato de hacer una prueba simple de esto, ¡la prueba simple funciona bien bajo un enlace dinámico! (Ver la actualización de mi pregunta). – QuantumMechanic

+0

No tengo idea. Puede haber funcionalidad de ayuda en el compilador aquí y allá, no conozco bien los distintos puertos de Windows. Btw PIC en Windows?!? –

Cuestiones relacionadas