1

多くのスクリプト言語には、次のようなプログラミング方法があります。

まず、funcという名前の関数があります。

void func()
{
}

次に、クライアントがこの関数を呼び出すときにいくつかの情報をログに記録したいのですが、関数を変更したくないので、次のようなことができます。

void (*pfunc)(void) = func;
void func()
{
    log("Someone call fund");
    pfunc();
}

その後、fundを呼び出す人は誰でも、私の「オーバーライド」関数を呼び出すことになります。これは、多くのスクリプト言語で問題ありません。C言語でも同じことができますか?そしてそれをどのようにコーディングするのですか?

このメソッドを使用して、サードパーティライブラリでいくつかの作業を実行したいので、コンパイルプロセスだけでなく、リンクプロセスに影響を与える何かを実行する必要があります。

4

3 に答える 3

7

単純なケースでは、マクロを使用してコーディングします

#define func()                \
do {                          \
    log("Someone called func"); \
    func();                   \
} while(0)

マクロの展開内では、マクロは再帰的に展開されません。

より複雑なケースでは、関数とマクロを実装します。「.h」ファイルに次のように配置します。

void func_annotated(void);
#ifdef DEBUG
# define func() func_annotated()
// or if the function takes parameters
// # define func(...) func_annotated(__VA_ARGS__)
#endif

「.c」ファイルに実装を配置します

void func_annotated(void)
{
    log("Someone called func");
    (func)();
}

ここで余分な()周囲funcは、これが常に実際の関数を使用することを保証します。

于 2012-08-03T14:16:06.040 に答える
1

たぶんあなたは図書館のインターポーザーを探しています。ファイルに独自の関数を定義し、syscallの代わりにその関数を使用して呼び出しをログに記録するプログラムを呼び出すことができます。

たとえば、:によって作成されたいくつかのシステムコールを挿入しlsます。

$ LD_PRELOAD=/your/own/functions/file.so ls -l

ログに記録したい関数を呼び出しているプログラムコードを変更できない場合(おそらくそれが利用できないため)に適しています。

于 2012-08-03T14:35:31.373 に答える
0

この場合、関数ポインタを使用する必要はありません。funcログに記録したいものすべてのパラメーターを関数に取得させることができます。また、オーバーライドについても同じですが、関数ポインターである必要はありません(オーバーライド関数を後で変更する予定がない限り)。また、この場合、関数ポインターが関数を指しているため、無限ループが作成されfuncます。funcまた、関数を宣言する前に、関数ポインタとして使用できるかどうかさえわかりません。

私はこのようなことを試みます、これは整数を記録します、しかしあなたはあなたが望むものを何でも記録するためにそれを使うことができます。

void func(int value)
{
    printf("%d\n", value);
    anotherFunc(value);
}

ここで、anotherFunc()はまったく別の関数です。前に述べたように、それによって呼び出される関数を変更したい場合はanotherFunc()、関数ポインターを使用するのが理にかなっています。そうでない場合は、関数ポインターは必要ありません。

于 2012-08-03T14:21:04.807 に答える