5

C関数(たとえば、stdlib、math ...)を動的に呼び出したいと思います。これは、私のCプログラムがランダム関数(例printf)へのポインターとその署名(char配列としてコード化:char *、...)しか知らないことを意味します。

&printf私の目標は、関数へのポインター( )、署名(何らかの方法でコード化されているchar[])、およびパラメーターをlong[]long実際のデータ型ではなく、1つの長い値がdouble値、ポインターを表すこともできる)として取得するreflectCall関数です。 ...)。

したがって、reflect関数のシグネチャは次のようになります。

long reflectCall(void *funcPointer, char[] types, long[] args)

関数は、関数の実際の呼び出しを実行し*funcPointer、最終的にその結果を返す必要があります。

その結果、ポインタポインタを作成できません。たとえば、このように:

int (*functionPtr)(int,int);

誰かがこの問題を解決する方法のヒントを教えてもらえますか、またはリファレンス実装を提案できますか?

4

4 に答える 4

7

純粋なCでそれを行うことは可能ですが、それほど単純でも迅速でもありません。

  1. 次のような、呼び出したいすべての関数のラッパー関数を作成します。

    int WrapPrintf(const char* types,long* args,long* results)
    {
        // Function specific code, in this case you can call printf for each parameter
        while(*types)
        {
            switch(*types){
            case 'i':
                printf("%d",(int)*args);
                break;
            case 'c':
                printf("%c",(char)*args);
                break;
            // .. and so on
            }
    
            ++types;
            ++args;
        }
        // Return number of filled results
        return 0;
    }
    
    int WrapFoo(const char* types,long* args,long* results)
    {
        // ..function specific code..
        return 0;
    }
    
  2. ラッパー関数へのポインター:

    typedef int (*TWrapper)(const char*,long*,long*);
    
  3. ラップされた関数のテーブル構造を作成します。

    struct STableItem{
        const char *strName;
        TWrapper pFunc;
    };
    
  4. テーブルを作成します。

    STableItem table[] = {
        {"printf", &WrapPrintf},
        {"foo", &WrapFoo},
        {NULL, NULL}
    };
    
  5. テーブルから任意の関数を呼び出すためのインターフェイスを作成します(関数を名前で検索して呼び出します)。

    int DynamicCall(const char *func_name,const char* types,long* args,long* results)
    {
        int k;
        for(k=0;table[k].strName != NULL;++k){
            if(strcmp(func_name,table[k].strName) == 0){
                return table[k].pFunc(types,args,results);
            }
        }
    
        return -1;
    }
    
  6. そして最後に電話をかけます:

    long args[] = {123,'b'};
    long results[8];            // not nice but just for an example
    
    int res_count = DynamicCall("printf","ic",(long*)args,(long*)results);
    

注:名前をすばやく検索するには、ハッシュ関数を使用してください

于 2013-03-15T07:54:31.380 に答える
4

Cはこれを行うための機能を提供していません。関数の本体はプラットフォーム固有のASMで記述する必要があります。

于 2013-03-12T22:26:39.453 に答える
3

それがあなたのニーズに合っているかどうかにかかわらず、libffiを見ることをお勧めします...

http://sourceware.org/libffi/
http://en.wikipedia.org/wiki/Libffi/

于 2013-03-13T01:25:27.963 に答える
2

他の場所で説明したように、これを真に動的に行う方法はありません。ただし、ポインターを使用して関数のテーブルを作成し、何らかの文字列またはインデックスを使用して目的を記述したい場合は、移植可能な方法で確かに可能です。これは、さまざまな解析やその他の「コマンドに基づいてコードを実行する」ためのソリューションとして、まったく珍しいことではありません。

ただし、何らかの関数ポインタを使用する必要があります[またはvoid *、ある時点で関数ポインタにキャストする]必要があります。C で関数を動的に呼び出す方法は他に (ほとんど) 移植性がありません。

于 2013-03-12T22:58:36.980 に答える