2013-05-13 31 views
8

Trường hợp của tôi khá đơn giản: Tôi muốn chương trình C++ của tôi xử lý các tín hiệu Unix. Để làm như vậy, glibc cung cấp một hàm trong signal.h gọi là sigaction, mà hy vọng sẽ nhận được một con trỏ hàm làm đối số thứ hai của nó.C liên kết cho con trỏ hàm được chuyển đến thư viện C

extern "C" 
{ 
void uponSignal(int); 
} 

void uponSignal(int) 
{ 
    // set some flag to quit the program 
} 

static 
void installSignalHandler() 
{ 
    // initialize the signal handler 
    static struct sigaction sighandler; 
    memset(&sighandler, 0, sizeof(struct sigaction)); 
    sighandler.sa_handler = uponSignal; 

    // install it 
    sigaction(SIGINT, &sighandler, nullptr); 
} 

Câu hỏi của tôi là: là extern "C" bộ định danh liên kết cần thiết?

Câu hỏi tiền thưởng: có thể sau khiSignal được khai báo static?

+0

Một số trình biên dịch sẽ đơn giản từ chối biên dịch nó nếu bạn loại bỏ 'extern" C "' bởi vì đối số thứ hai cho sigaction có kiểu sai. Nó là một lỗi trong nhiều trình biên dịch mà họ không xem xét phần liên kết của loại hàm. –

Trả lời

4

extern C chỉ cần thiết nếu bạn xuất ký hiệu từ mã nhị phân hoặc nhập chúng từ mã nhị phân khác (thường trong cả hai trường hợp, thư viện dùng chung), để tránh mang tên.

Đây không phải là trường hợp, bạn không liên kết uponSignal trên nhiều tệp nhị phân khác nhau để bạn không cần extern C. Tất cả những gì bạn đang làm là chuyển địa chỉ của hàm của bạn tới sigaction từ một hàm đã biết địa chỉ của uponSignal vì chúng (rõ ràng) là một phần của cùng một đơn vị dịch, hoặc ít nhất là cùng một nhị phân.

Câu hỏi thưởng: có thể uponSignal được khai báo static?

Chắc chắn nếu bạn muốn. uponSignal không cần liên kết bên ngoài.

+1

Thực ra, tôi lo lắng nhiều hơn về ** quy ước gọi ** hơn là mang tên. – qdii

+2

Bạn không nên. ;) Mặc dù các quy ước gọi là thực hiện cụ thể (ví dụ bên ngoài phạm vi của tiêu chuẩn), tôi chưa bao giờ thấy trình biên dịch đã không thực hiện phần quy ước gọi của chữ ký hàm để trình biên dịch cảnh báo bạn nếu có bao giờ là một không phù hợp (mà hiếm khi xảy ra anyway). – syam

6

Câu hỏi của tôi là: extern "C" Trình chỉ định liên kết cần thiết?

Để có tính di động tối đa, có; tiêu chuẩn C++ chỉ đảm bảo khả năng tương tác với C thông qua các hàm được khai báo extern "C".

Thực tế, không; ABI hợp lý nhất (bao gồm cả ABI GNU được sử dụng bởi glibc) sẽ sử dụng cùng một quy ước gọi cho các hàm C và C++ không phải thành viên (và thành viên tĩnh), do đó chỉ cần chia sẻ tên hàm giữa các ngôn ngữ là extern "C".

Câu hỏi bổ sung: có thể uponSignal được khai báo là tĩnh?

Có. Liên kết bên ngoài chỉ cần thiết để truy cập chức năng theo tên từ các đơn vị dịch thuật khác; nó không cần thiết để gọi hàm thông qua một con trỏ hàm.

+0

Bạn có báo giá để quay lại “Chuẩn C++ chỉ đảm bảo khả năng tương tác với C thông qua hàm được khai báo bên ngoài" C "? – qdii

+1

@qdii: Không thực sự; không có gì rõ ràng nói rằng không có bảo đảm, chỉ là không có gì cung cấp sự bảo đảm đó. 7.5/1 quy định rằng "Hai loại hàm có liên kết ngôn ngữ khác nhau là các kiểu riêng biệt ngay cả khi chúng giống nhau", và có một lưu ý chỉ ra rằng "một liên kết ngôn ngữ cụ thể có thể được liên kết với [...] một quy ước gọi cụ thể, v.v. . " –

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