簡體   English   中英

函數,名稱和參數的數組

[英]array of functions, names, and arguments

我正在嘗試使用輸入(來自文件)的功能-由他們命名。

例如-在我寫的文件中

     functionOne(1,2)

我成功地將函數名稱和他的參數分隔到不同的數組中-現在我有了:

    funcName[] = functioOne
    funcArg[0] = 1
    funcArg[1] = 2

但是,現在我卡住了-如何使用它? 我試圖制作一個指向函數的指針數組,但不知道如何使用它。 有什么建議嗎? 謝謝

C沒有內省 在運行時,無法從字符串獲取或調用函數。

雖然有解決方法。 例如,您可以創建一個包含函數名稱和函數指針的表。 然后,您可以搜索此表以找到要調用的函數。

也許像

void functionOne(int arg1, int arg2)
{
    ...
}

struct
{
    char *name;
    void (*function)(int, int);
} functions[] = {
    { "funcitonOne", &functionOne },
};

為了使它更通用,當您有許多函數采用不同數量的參數時,要難一些。 然后,您可以像傳遞普通的參數那樣,傳遞包含參數的數組:

void functionOne(int *arguments)
{
    // arguments[0] is the first arguments, etc.
    ...
}

相應地在結構中修改函數指針。

如果參數的類型也不同,則可以使用帶有類型標簽和值的並集的結構。

您無法在C語言中執行所需的操作。最接近的操作是,保留一個將指向各個函數的函數指針數組。 還要保留一個字符串數組,該字符串與其他數組的索引完全相同。 現在,只要獲得函數名稱,就可以對其進行解析,比較,並根據匹配的字符串的索引獲取適當的函數指針。

如何發送辯論文件-很好地做到這一點,我會說這件事-當您知道必須調用哪個函數時,就可以從文件本身中解析參數(您將知道此函數將花費2個辯論文本-因此您將獲得該行並將其解析為int ,並按預期將其double ,然后您將對其進行相應調用)。

通常, 您無法在便攜式 C11 (讀取n1570 )中做您想做的 事情 ,正如其他人所解釋的: 函數名是編譯時的事情 ,在執行時是未知的。 C編程語言沒有反射和/或內省 順便說一句,在優化編譯過程中,某個函數甚至可能“消失”(因此在運行時不“實際”存在,但是您的程序的行為就好像該函數存在一樣),因為它已被內聯或從可執行文件中刪除。 但是,C具有函數指針 (其類型描述了間接調用的函數的簽名)。 實際上,它們指向機器代碼


但是,如果您在運行例如Linux的x86-64計算機上編寫應用程序代碼,則有時可能使用一些“骯臟”的技巧來解決某些問題,這些技巧專門針對該操作系統指令集體系結構

  • 給定像"functionOne" (實際上是const char*類型)這樣的字符串 ,您可以獲得指向它的函數指針(例如functionOne ,只要它具有外部鏈接 )-通過動態鏈接工具-使用帶有NULL dlopen(3)路徑,然后是dlsym(3) 順便說一句,反向映射(從地址到名稱)可通過dladdr(3)獲得

  • 給定一個函數指針 (或者實際上是虛擬地址空間中指向某個可執行 代碼段內的任何有效地址),如果在編譯時已知該函數的簽名,則可以間接調用它(以該函數指針的類型給出) )。

  • 如果要使用僅在運行時才知道的具有任意簽名和任意參數的任意函數,則可以使用libffi 它知道您系統的ABI

  • 一個可能的技巧是發出一些包含C代碼的臨時文件/tmp/emittedcode.c (在運行時),將編譯過程派生到一個臨時插件中(例如gcc -Wall -O -shared -fPIC/tmp/emittedcode.c -o /tmp/emittedplugin.so ),並使用dlopen(3) 動態加載該臨時插件/tmp/emittedplugin.so 確保在程序終止時清理混亂(例如,刪除所有臨時文件,也許使用atexit(3) )。

  • 也許您想在運行時生成一些機器代碼; 然后再考慮一些JIT編譯庫,例如GCCJITLLVMlibjitasmjit

如果您的PC未運行Linux,則可能會為您的OS和計算機找到同等的東西。 閱讀操作系統:三篇簡單的文章,以全面了解有關OS的更多信息。 閱讀特定操作系統的文檔(對於Linux,請先閱讀ALP或有關Linux編程的新書,然后閱讀intro(2)syscalls(2)elf(5)和相關頁面)。


順便說一句,如果您只想從程序中調用函數(從某個輸入文件中的名稱),則可以在初始化時構建一些哈希表 (或map ,可能是一棵紅黑樹 ),將函數名與函數指針相關聯,如建議的那樣在這個其他的答案。

也許您想要具有某些eval原語的 homoiconic編程語言。 查看Common Lisp。 請注意SBCL ,它最多可以在REPL交互中編譯為動態生成的機器代碼。

也許您正在編寫一些解釋器 (通常比您想象的要困難和耗時,請閱讀《 龍書》 )。 考慮也許嵌入和使用現有的,例如GuileLua

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM