2013-05-13 20 views
8

私のケースはかなりシンプルです。私のC++プログラムはUnixシグナルを処理したいと思っています。そうするために、glibcはsignal.hの中で関数ポインタを第2引数として受け取ることを期待するsigactionという関数を提供しています。関数ポインタが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); 
} 

私の質問は:extern "C"リンケージ指定子は必要なのか?

ボーナスの質問:シグナルはstaticと表示されますか?

+0

一部のコンパイラは、 'extern" C "'を削除するとコンパイルすることを単に拒否します。これは、sigactionの第2引数が間違った型を持つためです。多くのコンパイラでは、関数型のリンケージ部分を考慮していないバグです。 –

答えて

4

extern Cは、名前のマングリングを避けるために、バイナリからシンボルをエクスポートするか、別のバイナリ(通常はどちらの場合も共有ライブラリ)からシンボルをインポートする場合にのみ必要です。

ここではそうではありません。uponSignalをさまざまなバイナリにリンクしていないので、extern Cは必要ありません。あなたがしているのは、同じ翻訳単位の(明らかに)部分であるか、少なくとも同じバイナリの部分なので、すでにuponSignalのアドレスを知っている関数から関数のアドレスをsigactionに渡すだけです。

ボーナスの質問:uponSignalstaticと宣言されていますか?

確かに必要な場合。 uponSignalとにかく外部リンケージは必要ありません。

+1

実際、私は名前のマングリングよりも**の呼び出し規約**を心配していました。 – qdii

+2

あなたはしないでください。 ;)呼び出し規約は実装固有のものですが(つまり、標準の範囲外です)、関数シグネチャの呼び出し規約を一部にしないコンパイラを見たことがないので、コンパイラは警告を出しますこれまでのところ不一致です(とにかくほとんど起こりません)。 – syam

6

私の質問は:extern "C"リンケージ指定子は必要ですか?

最大限の移植性のために、 C++標準では、extern "C"と宣言された関数によるCとの相互運用性のみが保証されています。

実際には、 (glibcで使用されるGNU ABIを含む)最も感知できるABIは、CとC++の非メンバ(および静的メンバ)関数に対して同じ呼び出し規約を使用するため、extern "C"は言語間で関数名を共有するためにのみ必要です。

ボーナスの質問:uponSignalは静的と宣言されますか?

はい。外部リンケージは、他の翻訳単位の名前で関数にアクセスする場合にのみ必要です。関数ポインタを介して関数を呼び出す必要はありません。

+0

"C++標準では、extern" C "と宣言された関数によるCとの相互運用性のみが保証されていますか? – qdii

+1

@qdii:そうではありません。明示的に保証がないと言うものは何もなく、保証を提供するものは何もありません。 7。5/1は、 "異なる言語リンケージを持つ2つの関数型は、それ以外の点で同じであっても異なる型である"と指定し、 "特定の言語リンケージが特定の呼び出し規約などと関連している可能性がある" –

関連する問題