2009-04-09 8 views
2

他のプロセスが(UNIXソケットを使って)関数を呼び出せるようにするこのプログラムがあります。メッセージプロトコルは非常に単純で、関数名、関数シグニチャー、およびパラメーターを保持するバッファー(char *)です。CスタブのないRPC

プログラム内のモジュールが関数にアクセスできるようにしたい場合、名前と署名をライブラリに登録します。私が直面している問題は、要求が入った後に物理的に関数を呼び出すことです.RPCとJavaのRMIライクなライブラリを見てきましたが、これらはライブラリを呼び出すためにスタブを生成する必要があります。私が取り組んでいるシステムは非常に動的であり、私は変更できない他の人々のコードともやりとりする必要があります。

だから、基本的に、この関数は次のようになります。

int somefunc(int someparam, double another) 
{ 
    return 1234; 
} 

今私は、ライブラリに登録:

//   func ptr name  signature 
REG_FUNCTION(somefunc, "somefunc", "i:id"); 

のリクエストが来たとき、私は私が欲しい一度有効な、いくつかのエラーチェックを行います関数を呼び出す。だから私は変数を持っています:

void * funcptr = (the requested function); 
char * sig = (the function signature); 
char * params = (a buffer of function parameters); 
//note that the params buffer can hold data types of arbitrary lengths 

私はどのようにCでパラメータで関数を呼び出すことができますか?

ありがとうございます!

+0

あなたは何のための署名が必要ですか?クライアントは関数を呼び出すか、somefuncを含むライブラリに要求を渡しますか?いくつかの明確化は助けになるでしょう! – dirkgently

答えて

2

これは、一般的にはCのみを使用して完全に解決できるとは思われません。たとえば、ターゲット関数で使用される呼び出し規約はわかりません。あなたがコンパイラーを「欺く」ことになるか、少なくともそれを推測する必要があるというリスクがあります。コンパイラがレジスタに渡された引数を使用して登録された関数を構築することを決定した場合、おそらくいくつかの最適化設定(または別のコンパイラでビルドされた場合はどうでしょうか?

一般的にCで、与えられた引数のセットを持つ関数を呼び出すこと、そして引数の値をランダムなバイトのバッファからアンパックする必要があることを表現する方法はありません。

あなたはこのような恐ろしい何かを行うことができます:

enum { VOID_INT, VOID_INT_DOUBLE, VOID_DOUBLE_INT, ... } Signature; 

void do_call(const void *userfunction, const void *args, Signature sig) 
{ 
    switch(signature) 
    { 
    case VOID_INT: 
    { 
     int x = *(int *) args; 
     void (*f)(int) = userfunction; 
     f(x); 
     break; 
    } 
    case VOID_INT_DOUBLE: 
    ... 
    } 
} 

をしかし、それは、これは、スケーラビリティと同じ大陸に住んでいないことは明らかです。もちろん、このコードを自動生成することもできます。戻り値の型と引数の型の合理的なセットです。 void *への/からの関数ポインタのキャストのために、まだ寒さの中でちょっとしたことがあるかもしれませんが、それは受け入れられるかもしれません。しかし、あなたはまだあなたに、あらかじめ生成されたコードを持っていない署名をあなたに渡す危険性を常に抱えています。

0

チェックアウトlibffi。このライブラリは、実行時に指定されたパラメータのセットで関数を呼び出すことを可能にします。

関連する問題