関数ポインターの構造を使用して、さまざまなバックエンドのインターフェイスを実装します。シグニチャは大きく異なりますが、戻り値はほとんどすべてvoid、void *、またはintです。
struct my_interface {
void (*func_a)(int i);
void *(*func_b)(const char *bla);
...
int (*func_z)(char foo);
};
ただし、バックエンドがすべてのインターフェイス機能の機能をサポートしている必要はありません。したがって、2つの可能性があります。最初のオプションは、すべての呼び出しの前に、ポインターが等しくないNULLであるかどうかを確認することです。読みやすさとパフォーマンスへの影響を恐れているので、私はそれがあまり好きではありません(ただし、私はそれを測定していません)。もう1つのオプションは、ダミー関数を使用することです。まれに、インターフェイス関数が存在しない場合があります。
したがって、署名ごとにダミー関数が必要になります。異なる戻り値に対して1つだけ持つことができるのではないかと思います。そしてそれを与えられた署名にキャストします。
#include <stdio.h>
int nothing(void) {return 0;}
typedef int (*cb_t)(int);
int main(void)
{
cb_t func;
int i;
func = (cb_t) nothing;
i = func(1);
printf("%d\n", i);
return 0;
}
このコードをgccでテストしたところ、機能しました。しかし、それは正気ですか?または、スタックを破損したり、他の問題を引き起こしたりする可能性がありますか?
編集:すべての答えのおかげで、私はもう少し読んだ後、規約の呼び出しについて多くを学びました。そして今、内部で何が起こっているのかをよりよく理解することができます。