web-dev-qa-db-ja.com

名前の競合を回避するCプロジェクト

中規模のCライブラリプロジェクトの関数の命名規則に関する実用的なアドバイスを見つけるのに苦労しています。私のライブラリプロジェクトは、独自のヘッダーを持ついくつかのモジュールとサブモジュールに分かれており、OOスタイル(すべての関数は最初の引数として特定の構造体を受け取り、グローバルなどは取りません)に緩やかに従います)。何かのようなもの:

MyLib
  - Foo
    - foo.h
    - foo_internal.h
    - some_foo_action.c
    - another_foo_action.c
    - Baz
      - baz.h
      - some_baz_action.c
  - Bar
    - bar.h
    - bar_internal.h
    - some_bar_action.c

一般的に、関数は大きすぎて(たとえば)貼り付けられませんsome_foo_actionおよびanother_foo_action 1つのfoo.c実装ファイル。ほとんどの関数を静的にして、1日呼び出します。

ライブラリの構築時にユーザーのクライアントプログラムとの競合を回避するために、内部(「モジュールプライベート」)シンボルを取り除くことに対処できますが、問題は、ライブラリでシンボルに名前を付ける方法ですか?これまでのところ、私はやっています:

struct MyLibFoo;
void MyLibFooSomeAction(MyLibFoo *foo, ...);

struct MyLibBar;
void MyLibBarAnAction(MyLibBar *bar, ...);

// Submodule
struct MyLibFooBaz;
void MyLibFooBazAnotherAction(MyLibFooBaz *baz, ...);

しかし、私はおかしな長いシンボル名(例よりもはるかに長い)になってしまいます。名前の前に「偽の名前空間」を付けないと、モジュールの内部シンボル名がすべて衝突します。

注:私はキャメルケース/パスカルケースなどは気にせず、名前自体を気にします。

13
Dan Halliday

接頭辞(まあ、接辞)は本当に唯一のオプションです。あなたが見るいくつかのパターンは<library>_<name>(OpenGL、ObjCランタイムなど)、<module/class>_<name>(Linuxの一部など)、<library>_<module/class>_<name>(GTK +など)。あなたの計画は完全に合理的です。

長い名前は、予測可能であれば必ずしも悪いわけではありません。最終的にcrazy長い名前と、1つのソースファイル内の関連する関数を使用するには大きすぎる関数となるという事実は、さまざまな懸念を引き起こします。より具体的な例はありますか?

10
user2313838

Cライブラリの通常の規則は、ライブラリ名を外部で使用可能な名前のプレフィックスとして使用することです。

struct MyLibFoo;
void MyLibAFooAction(...);

ライブラリの複数のユニットで引き続きアクセスできる必要があるライブラリ内部名の場合、厳密な規則はありませんが、ライブラリ名のプレフィックスとそれが内部関数であることを示すものを使用します。例えば:

struct MyLibInternalFooBaz;
void MyLibInternalFooBazAction();

これにより、名前が非常に長くなり、入力が困難になる可能性があることに同意しますが、残念なことに、これはC++名前空間のようなメカニズムがないために支払う必要がある代償です。名前の長さを短くするために、いくつかの明確さを犠牲にして、名前に略語を使用することを選択できますが、長所と短所を慎重に比較検討する必要があります。

長い接頭辞を避けたい場合は、AppleがiOSおよびOS Xで行うことのように、ライブラリ名を短縮できます。

  • NSStringは、OSのNeXTSTEPルートからの文字列です
  • CALayerはコアアニメーションレイヤーです
3
mouviciel

関数ポインタが事前に入力されているグローバル構造変数についてはどうですか?

lib.h

_#pragma once

typedef struct
{
    void (*doFoo)(int x);
    const char *(*doBar)(void *p);
} YourApi;

extern const YourApi yourApi;
_

lib.c:

_#include "lib.h"

#include <stdio.h>

static void doFoo(int x)
{
    printf("Doing foo %d\n", x);
}

static const char *doBar(void *p)
{
    printf("Doing bar: %p\n", p);
    return "Hello";
}

const YourApi yourApi = {
    doFoo,
    doBar};
_

ハーネス:

_#include "lib.h"

int main()
{
    yourApi.doFoo(42);
    yourApi.doBar("asd");
}
_

Staticキーワードは、スコープを翻訳単位に制限するため、他のものと衝突しません。

次に、ユーザーは、_YourApi *ya = &yourApi_のようなポインターを使用し、次にya->doFoo(...)を使用して、短縮することができます。

また、テスト用にライブラリを模擬するための素晴らしい方法も提供します。

2
Calmarius