2013-09-28 90 views
13

Tôi đã thử liên kết một thư viện tĩnh (được biên dịch với gcc) với một chương trình C++ và tôi nhận 'tham chiếu không xác định'. Tôi đã sử dụng gcc và g ++ phiên bản 4.6.3 trên máy chủ ubuntu 12.04. Ví dụ, đây là file thư viện đơn giản cho phương pháp thừa:Liên kết C thư viện tĩnh đã biên dịch với Chương trình C++

mylib.h

#ifndef __MYLIB_H_ 
#define __MYLIB_H_ 

int factorial(int n); 

#endif 

mylib.c

#include "mylib.h" 

int factorial(int n) 
{ 
    return ((n>=1)?(n*factorial(n-1)):1); 
} 

Tôi tạo ra đối tượng cho mylib.c này sử dụng gcc:

gcc -o mylib.o -c mylib.c 

Again thư viện tĩnh được tạo ra từ các tập tin đối tượng sử dụng tiện ích AR:

ar -cvq libfact.a mylib.o 

Tôi đã thử nghiệm thư viện này với một chương trình C (test.c) và chương trình C++ (test.cpp)

Cả C và chương trình C++ có cơ thể giống nhau:

#include "mylib.h" 
int main() 
{ 
    int fact = factorial(5); 
    return 0; 
} 

Giả sử thư viện libfact.a tĩnh có sẵn trong/home directory/kiểm tra, tôi biên soạn chương trình C của tôi mà không bất kỳ vấn đề:

gcc test.c -L/home/test -lfact 

Tuy nhiên trong khi ++ chương trình thử nghiệm C, nó ném một lỗi liên kết:

g++ test.cpp -L/home/test -lfact 

test.cpp:(.text+0x2f): undefined reference to `factorial(int)' 
collect2: ld returned 1 exit status 

Tôi thậm chí đã cố gắng thêm lệnh extern trong test.cpp:

extern int factorial(int n) //added just before the main() function 

Vẫn còn những lỗi tương tự.

  • Ai đó có thể cho tôi biết tôi sai ở đây không?
  • Có bất kỳ điều gì tôi đã bỏ lỡ khi tạo thư viện tĩnh không?
  • Tôi có phải thêm bất kỳ thứ gì vào số test.cpp để làm cho nó hoạt động không?
+1

Khi tôi nhìn thấy các câu hỏi SO không có câu trả lời, cùng với câu trả lời được 7 bình chọn, tôi hoàn toàn hiểu được tính cách ngu xuẩn của con người. Làm thế nào câu trả lời có thể có liên quan nếu câu hỏi không? Nào! –

Trả lời

19

Vấn đề là bạn chưa nói với chương trình C++ rằng giai thừa được viết bằng C. Bạn cần thay đổi tệp tiêu đề test.h của mình. Như thế này

#ifndef __MYLIB_H_ 
#define __MYLIB_H_ 

#ifdef __cplusplus 
extern "C" { 
#endif 

int factorial(int n); 

#ifdef __cplusplus 
} 
#endif 

#endif 

Bây giờ tệp tiêu đề của bạn sẽ hoạt động cho cả chương trình C và C++. Xem here để biết chi tiết.

Tên BTW có chứa dấu gạch dưới kép được dành riêng cho trình biên dịch (vì vậy tên bắt đầu bằng dấu gạch dưới và chữ hoa) nên #ifndef __MYLIB_H_ là nói đúng pháp luật. Tôi sẽ đổi thành #ifndef MYLIB_H #define MYLIB_H

+2

Có nó hoạt động như sự quyến rũ với điều này. Cảm ơn các liên kết. Cảm ơn bạn đã thêm thông tin về dấu gạch dưới kép. – Prabu

+0

giải thích tuyệt vời. +1 – Crt

1

Trong khi câu trả lời được chấp nhận là hoàn toàn chính xác, tôi nghĩ tôi chỉ cần thêm một quan sát. Một số trình chỉnh sửa gặp sự cố với cú đúp mở/đóng và sẽ thụt lề toàn bộ phạm vi extern "C" trong tiêu đề.Nếu mylib.h là một tiêu đề then chốt cho một thư viện, bạn có thể xem xét:

#if defined (__cplusplus) 
#define _MYLIB_INIT_DECL extern "C" { 
#define _MYLIB_FINI_DECL } 
#else 
#define _MYLIB_INIT_DECL 
#define _MYLIB_FINI_DECL 
#endif 

Tất cả các tiêu đề khác trong mylib thư viện, ví dụ, mylib_aux.h, có thể có dạng:

#ifndef _MYLIB_AUX_H 
#define _MYLIB_AUX_H 

#include <mylib.h> 

_MYLIB_INIT_DECL 

... header content ... 

_MYLIB_FINI_DECL 

#endif /* _MYLIB_AUX_H */ 

Rõ ràng, tên tôi 'Sử dụng là tùy ý, nhưng đối với nhiều tiêu đề thư viện, cách tiếp cận này có ích cho tôi.

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