APIではなく、ライブラリ内でのみ関数を表示する

Nov 29 2020

私はいくつかのファイルに分散されているC99ライブラリを書いています。

// core.h
void my_private_fn();

void API_my_public_fn();
// core.c
#include "core.h"

void my_private_fn() {
    do_something();
}

void API_my_public_fn() {
    do_something_else();
}
// module_a.h
#include "core.h"

void API_useful_thing();
// module_a.c
#include "module_a.h"

void API_useful_thing() {
    my_private_fn();
}

API_ライブラリを使用するプログラムで接頭辞付きの関数のみを表示したいのですが、で使用するにmy_private_fncore.hで公開する必要もありmodule_a.cます。my_private_fnライブラリ内でのみ表示できるようにする方法はCにありますか?

回答

3 SergeBallesta Nov 29 2020 at 01:39

関数が定義されているコンパイルユニットでのみ表示される必要がある場合は、関数を宣言できますstatic。C言語には可能なスコープがほとんどないため、シンボルは3つのスコープしか持つことができません。

  • ブロックにローカル(ブロックは関数または関数内のブロックにすることができます)
  • 静的スコープ(関数外の静的宣言):シンボルは、宣言されているコンパイルユニットでのみ表示されます
  • グローバルスコープ(関数外の非静的宣言):シンボルはプログラム全体で表示されます。

せいぜい、公式に文書化されたAPIで宣言していないプライベートインクルードファイルで宣言を非表示にすることができます。そうすれば、従順なユーザーはそれを使用すべきではありません。ただし、ユーザーが宣言を独自のコードに入れて関数を使用するのを防ぐことはできません。

2 JohnKugelman Nov 29 2020 at 01:35

ライブラリ内でのみ使用され、エンドユーザーには配布されない内部ヘッダーファイルにそれらを配置しますcore_internal.h。たとえば、。

user3758232 Dec 31 2020 at 00:19

私が選択したSergeの回答に基づいて、コード構築をレイアウトするためのより適切な方法を見つけました。その最もメリットがあります。

重要なのは、「プライベート」関数を、ヘッダーファイルではなくCファイルにのみ含まれるヘッダーに配置することです。このようにして、「プライベート」シンボルは内部で使用できますが、外部の呼び出し元では使用できません。完全な例では:

core.h

void my_public_fn();

core_priv.h

void my_private_fn();

core.c

#include <stdio.h>

#include "core.h"
#include "core_priv.h"

void my_private_fn() {
    printf("Private function called.\n");
}

void my_public_fn() {
    printf("Public function called.\n");
}

module_a.h

#include "core.h"

void module_a_fn();

module_a.c

#include "core_priv.h"
#include "module_a.h"

void module_a_fn() {
    my_private_fn();
    my_public_fn();
}

また、必要に応じて、複数のモジュールを共通のライブラリヘッダーにグループ化することもできます。

library.h

#include "module_a.h"
// etc.

このように、ライブラリを使用するプログラムは、次のファイルのみを含める必要があります。

main.c

#include "library.h"

int main() {
    //my_private_fn(); // This triggers a compile warning.
    my_public_fn();    // I can still reach the "core" public function.
    module_a_fn();     // This calls the "private" function internally.

    return 0;
}

コンパイルとyieldのgcc -Wall *.c -o main.o実行./main.o

Public function called.
Private function called.
Public function called.