extern "C" xác định cách biểu tượng trong tệp đối tượng được tạo nên được đặt tên. Nếu một hàm được khai báo không có "C" bên ngoài, tên biểu tượng trong tệp đối tượng sẽ sử dụng tên mang tên C++. Đây là một ví dụ.
test.c Với như vậy:
void foo() { }
Biên soạn và niêm yết các biểu tượng trong các tập tin đối tượng cho:
$ g++ -c test.C
$ nm test.o
0000000000000000 T _Z3foov
U __gxx_personality_v0
Hàm foo là thực sự gọi là "_Z3foov". Chuỗi này chứa thông tin kiểu cho kiểu trả về và các tham số, trong số những thứ khác. Nếu bạn thay vì viết test.c như thế này:
extern "C" {
void foo() { }
}
Sau đó biên dịch và nhìn vào biểu tượng:
$ g++ -c test.C
$ nm test.o
U __gxx_personality_v0
0000000000000000 T foo
Bạn nhận được C liên kết. Tên của hàm "foo" trong tệp đối tượng chỉ là "foo" và nó không có tất cả các thông tin kiểu ưa thích đến từ tên mangling.
Bạn thường bao gồm tiêu đề bên trong "C" {} bên ngoài nếu mã đi kèm với nó được biên dịch bằng trình biên dịch C nhưng bạn đang cố gọi nó từ C++. Khi bạn làm điều này, bạn đang nói với trình biên dịch rằng tất cả các khai báo trong tiêu đề sẽ sử dụng liên kết C. Khi bạn liên kết mã của mình, các tệp .o của bạn sẽ chứa tham chiếu đến "foo" chứ không phải "_Z3fooblah", hy vọng sẽ khớp với bất kỳ nội dung gì trong thư viện mà bạn liên kết.
Hầu hết các thư viện hiện đại sẽ đặt nhân viên bảo vệ xung quanh các tiêu đề như vậy để biểu tượng được khai báo với liên kết phù hợp. ví dụ. trong nhiều tiêu đề chuẩn bạn sẽ tìm thấy:
#ifdef __cplusplus
extern "C" {
#endif
... declarations ...
#ifdef __cplusplus
}
#endif
Điều này đảm bảo rằng khi mã C++ bao gồm tiêu đề, ký hiệu trong tệp đối tượng của bạn khớp với thư viện C. Bạn chỉ nên đặt bên ngoài "C" {} xung quanh tiêu đề C của bạn nếu nó cũ và không có các vệ sĩ này.
Tôi nhầm lẫn ý bạn trong tiêu đề câu hỏi của bạn ... bạn có thể xây dựng không? –
Tôi không chắc chắn về cách đặt nó. Bạn đã đọc vượt quá tiêu đề? – Landon