2012-02-16 35 views
5

(Đây là gcc 3.3.1 (dài câu chuyện -. Đổ lỗi NIST) trên Cygwin)tham khảo Không xác định khi động liên kết với gcc trong Cygwin

tôi đã biên soạn một số file nguồn với gcc -c -fPIC ... để có được .o files.

Sau đó, tôi đã làm:

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

Nhưng khi tôi đi để sử dụng nó:

$ 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 

Tuy nhiên, nếu sử dụng cùng một file .o tôi thay vì làm:

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

Liên kết chống lại thành công đó:

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

Điều kỳ lạ đối với tôi là bạn có thể thấy bên dưới, tham chiếu được đề cập có trong cả tệp .a và .dll. Vậy tại sao lỗi khi liên kết với .dll?

tham khảo được tìm thấy trong thư viện chia sẻ:

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

Và nó cũng có trong thư viện tĩnh:

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

Và đây là tài liệu tham khảo để các biểu tượng được tạo ra trong file mà muốn sử dụng chức năng:

$ 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 

cập nhật để giải quyết Marco của câu trả lời

Điều thú vị/annoyingly, khi tôi cố gắng để làm một ví dụ kiểm tra tối thiểu này, tôi không thể làm cho nó xảy ra (mặc dù nó xảy ra mỗi khi có thật):

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

Sau đó:

$ 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 

Trả lời

6

Tôi tìm thấy câu trả lời (ở chỗ nó giải quyết vấn đề liên kết của tôi) trên một trang web Cygwin: http://cygwin.com/cygwin-ug-net/dll.html

Những gì tôi đã kết thúc phải làm là tạo ra các thư viện chia sẻ và thực hiện liên kết cuối cùng như này:

$ 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 

Nhưng tôi vẫn muốn biết tại sao tôi không phải làm điều này cho bài kiểm tra đơn giản của mình.

2

Tôi không hoàn toàn chắc chắn, nhưng afaik Windows có không gian tên cho mỗi mô-đun (như exe hoặc .dll). Khi liên kết tĩnh bạn đang đặt tất cả mọi thứ trong một .exe, do đó một mô-đun, một không gian tên.

Khi liên kết động, bạn tạo hai mô-đun (1 exe, 1 dll) và cả hai đều có không gian tên của chúng.

Bạn cần xuất biểu tượng từ DLL để làm việc này iirc (đọc lên trên importlibs, ví dụ:trong tuyệt vời Linkers and Loaders

+0

Thú vị! Hai điều cần lưu ý: (1) Với mã thực tế được đề cập, nếu tôi thêm cuộc gọi vào những thứ khác trong thư viện được chia sẻ, chúng cũng hiển thị dưới dạng không xác định trong liên kết động - vì vậy không chỉ có chức năng cụ thể đó. Điều này hỗ trợ câu trả lời của bạn. Tuy nhiên ... (2) Khi tôi cố gắng thực hiện một bài kiểm tra đơn giản này, bài kiểm tra đơn giản hoạt động tốt dưới một liên kết động! (Xem cập nhật cho câu hỏi của tôi). – QuantumMechanic

+0

Không có ý tưởng. Có thể có chức năng trợ giúp trong trình biên dịch ở đây và ở đó, tôi không biết các cổng windows khác nhau. Btw PIC trên Windows?!? –

Các vấn đề liên quan