2013-03-12 90 views
1

我想動態地調用C函數(例如,形成stdlib,數學...)。這意味着我的C程序只知道指向隨機函數(例如printf)及其簽名(編碼爲char數組:char *,...)的指針。C - 不帶函數指針的動態函數調用

我的目標是reflectCall功能是獲取一個指向函數(&printf),簽名(在char[]莫名其妙編碼),參數爲long[]long是不實際的數據類型,一個長值能也代表一個double值,指針,...)。因此

我反映函數的簽名是這樣的:

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

功能應該做的功能*funcPointer的實際調用,最後返回其結果。

因此,我可以不是創建一個指針指針;例如像這樣:

int (*functionPtr)(int,int); 

任何人都可以給我一個提示如何解決這個問題或建議任何參考實現嗎?

+0

目前基本上沒有辦法在一個獨立於平臺的方式來做到這一點。 – 2013-03-12 22:25:40

+0

對不起,你不能將可變參數傳遞給可變參數函數。 C只是不支持必要的反思。 – nneonneo 2013-03-12 22:25:48

回答

4

C不提供設施來做到這一點。您必須在平臺特定的ASM中編寫函數的主體。

+0

可能感興趣:[libffi](http://sourceware.org/libffi/)。 – duskwuff 2013-03-12 22:28:34

+0

我可以用C++做這種反射嗎? (我還想調用C函數) – matg 2013-03-12 22:28:48

+0

@matg:Nope .... – 2013-03-12 22:29:04

2

正如其他地方所解釋的,沒有辦法真正動態地做到這一點。但是,如果您希望使用指針構建函數表,並使用某種字符串或索引來描述您想要執行的操作,那麼以便攜方式這當然是可能的。這對於各種解析和其他「基於命令的運行代碼等」的解決方案來說並不罕見。

但它確實需要你使用某種類型的函數指針[或者在某個點或另一個點將你的void *轉換爲一個]。在C中沒有其他(甚至幾乎)便攜式的函數調用方式。

5

這是可能做到這一點在純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. 用於包裹功能創建的表結構:由名稱

    STableItem table[] = { 
        {"printf", &WrapPrintf}, 
        {"foo", &WrapFoo}, 
        {NULL, NULL} 
    }; 
    
  4. 創建界面從表中調用任何功能(搜索功能:

    struct STableItem{ 
        const char *strName; 
        TWrapper pFunc; 
    }; 
    
  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); 
    

注:使用哈希函數更快名稱搜索

+0

您能否詳細介紹哈希函數,以便更快地進行名稱搜索?謝謝。 – Unheilig 2015-05-01 06:33:08