主題はスワッピング機能について尋ねますが、実際には何が機能するかをエミュレートしたいと考えてswizzle
います。これは、同じ関数名を呼び出して別のことをさせたいということを意味します。
ポインターのみのソリューションでは、その動作は得られません。それが重要でない場合は、提供されている関数ポインターのみのソリューションのいずれかを採用する必要があります。それが重要な場合は、抽象化のレイヤーを導入する必要があります。抽象化では、内部で関数ポインターを使用できます (ただし、他の解決策があります)。
このインターフェースのユーザーへの API は次のようになります。
/* API to initialize */
void abstract_func_init ();
/* API to manipulate abstract functions */
typedef int abstract_func_type ();
abstract_func_type * abstract_func_get (abstract_func_type *key);
int abstract_func_set (abstract_func_type *key, abstract_func_type *behavior);
/* the abstract functions */
extern int foo ();
extern int bar ();
このようなインターフェースの実装は次のようになります。
static void insert (abstract_func_type *key, abstract_func_type **behavior)
{ /* associate key to behavior */ }
static abstract_func_type ** lookup (abstract_func_type *key)
{ /* return behavior from key */ }
abstract_func_type * abstract_func_get (abstract_func_type *k) {
abstract_func_type **f = lookup(k);
if (f) return *f;
return 0;
}
int abstract_func_set (abstract_func_type *k, abstract_func_type *p) {
abstract_func_type **f = lookup(k);
if (f) {
*f = p;
return 0;
}
return -ENOENT;
}
#define DEFINE_ABSTRACT_FUNC(func) \
static int static_##func (); \
static abstract_func_type *func##_ptr = static_##func; \
int func () { return func##_ptr(); } \
static int static_##func ()
DEFINE_ABSTRACT_FUNC(foo) { return puts("foo"); }
DEFINE_ABSTRACT_FUNC(bar) { return puts("bar"); }
void abstract_func_init () {
insert(foo, &foo_ptr);
insert(bar, &bar_ptr);
}
次に、swap()
投稿で最初に提示したものは、次のように実装できます。
void swap (abstract_func_type *a, abstract_func_type *b) {
abstract_func_type *ap = abstract_func_get(a);
abstract_func_type *bp = abstract_func_get(b);
abstract_func_set(a, bp);
abstract_func_set(b, ap);
}
を呼び出すプログラムは次のswap()
とおりです。
puts("before swap");
foo();
bar();
swap(foo, bar);
puts("after swap");
foo();
bar();
そして、その出力は次のようになります。
before swap
foo
bar
after swap
bar
foo
ルックアップ テーブルへの抽象関数の追加を自動化するには、ビルド システムに、行を出力するスクリプトを呼び出す追加のステップを導入し、grep
そのような行ごとDEFINE_ABSTRACT_FUNC
に を呼び出す関数を含む新しいソース ファイルを生成することができます。insert()
.
モックアップの完全なバージョンは、ここにあります。