もう 1 つの方法は、すべての関数を保持する構造体を宣言してから、関数を静的に定義することです。そうすれば、グローバルな名前構造体の名前の競合について心配するだけで済みます.
// foo.h
#ifndef FOO_H
#define FOO_H
typedef struct {
int (* const bar)(int, char *);
void (* const baz)(void);
} namespace_struct;
extern namespace_struct const foo;
#endif // FOO_H
// foo.c
#include "foo.h"
static int my_bar(int a, char * s) { /* ... */ }
static void my_baz(void) { /* ... */ }
namespace_struct const foo = { my_bar, my_baz }
// main.c
#include <stdio.h>
#include "foo.h"
int main(void) {
foo.baz();
printf("%d", foo.bar(3, "hello"));
return 0;
}
上記の例では、 my_bar
そして my_baz
foo
経由でのみ、main.c から直接呼び出すことはできません .
同じ署名を持つ関数を宣言する名前空間がたくさんある場合は、そのセットの名前空間構造体を標準化し、実行時に使用する名前空間を選択できます。
// goo.h
#ifndef GOO_H
#define GOO_H
#include "foo.h"
extern namespace_struct const goo;
#endif // GOO_H
// goo.c
#include "goo.h"
static int my_bar(int a, char * s) { /* ... */ }
static void my_baz(void) { /* ... */ }
namespace_struct const goo = { my_bar, my_baz };
// other_main.c
#include <stdio.h>
#include "foo.h"
#include "goo.h"
int main(int argc, char** argv) {
namespace_struct const * const xoo = (argc > 1 ? foo : goo);
xoo->baz();
printf("%d", xoo->bar(3, "hello"));
return 0;
}
my_bar
の複数の定義 と my_baz
これらは静的に定義されているため競合しませんが、基になる関数には適切な名前空間構造体を介してアクセスできます。
名前空間プレフィックスを使用する場合、通常、#define NAMESPACE_SHORT_NAMES
で有効化できる短縮名のマクロを追加します ヘッダーを含める前。ヘッダー foobar.h は次のようになります:
// inclusion guard
#ifndef FOOBAR_H_
#define FOOBAR_H_
// long names
void foobar_some_func(int);
void foobar_other_func();
// short names
#ifdef FOOBAR_SHORT_NAMES
#define some_func(...) foobar_some_func(__VA_ARGS__)
#define other_func(...) foobar_other_func(__VA_ARGS__)
#endif
#endif
インクルード ファイルで短い名前を使用したい場合は、そうします
#define FOOBAR_SHORT_NAMES
#include "foobar.h"
これは、Vinko Vrsalovic (コメント内) によって説明されている名前空間マクロを使用するよりも、クリーンで便利なソリューションだと思います。
## 演算子を使用できます:
#define FUN_NAME(namespace,name) namespace ## name
関数を次のように宣言します:
void FUN_NAME(MyNamespace,HelloWorld)()
かなりぎこちなく見えますが。