2012-02-16 20 views
5

(Jest gcc 3.3.1 (długa historia. - winni NIST) na Cygwin)Niezdefiniowany odniesienia podczas dynamicznego powiązania z gcc w Cygwin

mam skompilowane niektóre pliki źródłowe z gcc -c -fPIC ... dostać .o plików.

Potem zrobiłem:

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

Ale kiedy idę, aby go użyć:

$ 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 

Jednak jeśli stosując te same pliki .o ja zamiast robić:

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

Łącze do tego jest skuteczne:

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

Co jest dla mnie dziwne, to jak widać poniżej, odnośnik jest obecny zarówno w .a jak i .dll. Dlaczego więc błąd podczas łączenia z .dll?

referencyjny znajduje się w udostępnionej biblioteki:

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

I to także w statycznej biblioteki:

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

A tu odniesienie do symbolu generowanych w pliku, który chce wykorzystać funkcja:

$ 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 

Updated zająć odpowiedź Marco

ciekawe/irytująco, gdy próbuję złożyć minimalny przykład test tego, że nie może się zdarzyć (choć zdarza się za każdym razem z prawdziwych):

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

Następnie:

$ 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 

Odpowiedz

6

Znalazłem odpowiedź (w tym, że rozwiązuje mój problem łącze) na stronie internetowej Cygwin: http://cygwin.com/cygwin-ug-net/dll.html

Co skończyło się zrobić, to stworzyć bibliotekę współdzieloną i zrobić ostatnie ogniwo jak to:

$ 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 

Ale nadal chciałbym wiedzieć, dlaczego nie musiałem robić tego dla mojego prostego testu.

2

Nie jestem do końca pewien, ale AFAIK Windows ma nazw na moduł (jak exe lub dll). Podczas łączenia statycznego umieszczasz wszystko w jednym .exe, a więc w jednym module, w jednej przestrzeni nazw.

Podczas dynamicznego łączenia tworzy się dwa moduły (1 exe, 1 dll) i oba mają swoje przestrzenie nazw.

Musisz wyeksportować symbol z biblioteki DLL, aby działało iirc (odczyt na importlibs, np.w doskonałej Linkers and Loaders

+0

Interesujące! Dwie rzeczy do zapamiętania: (1) Z rzeczywistym kodem, o którym mowa, jeśli dodaję połączenia do innych rzeczy w udostępnianej bibliotece, również będą wyświetlane jako niezdefiniowane w dynamicznym łączu - więc nie jest to tylko ta konkretna funkcja. To wspiera twoją odpowiedź. Jednak ... (2) Kiedy próbuję zrobić prosty test tego, prosty test działa dobrze pod dynamicznym łączem! (Zobacz aktualizację na moje pytanie). – QuantumMechanic

+0

Brak pomysłu. Tam i tam może być funkcjonalność pomocnika w kompilatorze, nie znam dobrze różnych portów Windows. Btw PIC na Windows?!? –

Powiązane problemy