関数が外部からアクセスされていることを明確にする方法は?


9

これはC固有の質問です。私は可能な限りすべてを翻訳単位の境界内に保ち、.hファイルを介していくつかの関数のみを公開することを試みています。つまり、staticファイルレベルのオブジェクトへのリンクを提供しています。

ここで、いくつかの関数を他のモジュールから呼び出す必要がありますが、直接呼び出す必要はありません。私のモジュール/ファイル/翻訳ユニットは他のモジュールにサブスクライブし、関数へのポインターを渡します。次に、特定のイベントが発生すると、いくつかの引数を指定してポインターが呼び出されます。

したがって、これらの関数があいまいな場所から呼び出されていることを非常に明確にする方法を知りたいと思います。

  • 彼らは、あるべきstaticextern(及び、それらを公開しますか.h)?
  • 関数の名前にいくつかのヒントを含める必要がありますか?
  • それとも、「Xから呼び出されました」というコメントで十分ですか?

1
それは素晴らしい質問です。私の解決策(私はまったく満足していません。そのため、コメントにそれを入れているだけです)は、複数のヘッダーファイルを作成し、わかりやすい名前を付け、それらに必要なスコープで関数をグループ化することです。ASTARライブラリのために私は私がAStar.h、AStar_private.h、AStar_packagePrivate.h、等...持って行った
シヴ山のドラゴン

回答:


2

コンパイル単位(ファイル)の観点からは、関数が外部から使用できるかどうかだけに注意する必要があります。それを使用可能にすることは、それが呼び出されることを意図していたことを意味し、それらの呼び出しが発生することを想定して操作する必要があります。関数自体に関する懸念は、そのエントリポイントから始まります。そもそも制御がそこに到達する方法は、それを実現するコードにのみ関係します。

CIが知っているすべての実装のリンケージはシンボリックであるため、関数を呼び出すものはすべてそのシンボルを参照する必要があります。

foo();  /* Direct */

some_function_pointer_t funcs[] = { &foo, &bar, &baz };  /* Indirect */

誤ってと宣言foo()した場合static、プログラムはリンクしません。非と宣言すると、static呼び出されない公開された関数があります。関数が使用されているかどうかに関する質問は、オブジェクトファイルのシンボルテーブルをダンプするか、ソース内で検索することで解決できます。


1

そのため、これらの関数が不明瞭な場所から呼び出されていることを非常に明確にする方法を探しています。

「あいまい」を定義します。
メソッドは明確に定義された「インターフェース」を通じて公開する必要があります。ShivanDragonがすでに示唆しているように、それらの「インターフェース」 .hファイルです。別のプログラムに「正しい」ヘッダーファイルを指定しないと、メソッドを呼び出すことができません。

それらは静的または外部である必要がありますか(そして.hでそれらを公開します)?

static 可能性がある限り、あなたが[様構造]任意のクラスを持っていないとして、インスタンスのデータが含まれていることもOK。実際にはまったく実装しない
externこと意味します。リンクプロセス中に、他の場所から実装が「取得」されます。

関数の名前にいくつかのヒントを含める必要がありますか?

それとも、「Xから呼び出されました」というコメントで十分ですか?

絶対違う。

このようなコメントは、どんなに意味のあるものであっても、書き終えた時点で古くなっています。


最初のポイントを説明すると、関数は次のように呼び出されます。コンポーネントに外部.hファイルが含まれています。そこから関数を呼び出し、モジュール自身の関数の1つへのポインタを渡します。その後、外部コードはそのポインタにあるものを何でも呼び出します。したがって、私の関数は、ヘッダーファイルをインクルードしていない誰かによって呼び出されています。
Vorac

1
2番目の点については、私の理解では、ファイルスコープで定義されたオブジェクトにexternは、デフォルトで外部リンクがあります。したがって、キーワードは冗長です`
Vorac 14

0

コールバック関数がモジュール内で定義されていて、ユーザーが自分のものを提供しない場合は、初期化フェーズでプレースホルダーを使用できると思います。プレースホルダーは通常、enum内部で適切なstatic関数に変換されるです。


0

私はまだそれらを作成しstatic(それらは誰にもリンクされて呼び出されることを意図していない)、それらの目的をその名前で外部関数に提供されるコールバックとしてマークします。

static 隠せるものはできるだけ隠そうとするからです。

a)、コメントが古くなっている、およびb)コールバックが提供された場所で、この関数がそのように使用されることが意図されていることが明らかになったため、それらの名前にそれらをマークします。命名規則に従わない関数のアドレスを取得しています。


0

スコープ修飾子は、「十分に近い」ドキュメントの形式としてではなく、主にコンパイラの情報として使用する必要があります。static特にを使用すると、現在のコンパイラで機能する場合でも、Cコンパイラは、コールバックとしても含めて、関数をモジュールの外から使用できなくすることができます。

もちろん、コードをコメントに追加する必要があります。コメントが混乱を招く可能性があることがわかるからです。異常または予期しないものには、適切なコメントが必要です。ただし、他の回答で述べたように、コメントは未読になったり、古くなったりする可能性があります。

したがって、残された唯一のオプションは、関数に名前を付けてコールバックであることを示すことです。ほとんどの例では、私が使用見てきた_callbackか、_cb接尾辞として、またはcb_接頭辞として。コードでコールバックが異常な場合は長い形式を使用し、一般的な場合は短い形式を使用します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.