[英]Conditional substitution of union member in C
我有
typedef union
{
void (*fp1p)(void);
void (*fp2p)(uint32_t);
void (*fp3p)(uint32_t, uint32_t);
void (*fp4p)(uint32_t, uint32_t, uint32_t);
uint32_t (*fp5p)(uint32_t);
uint32_t (*fp6p)(uint32_t, uint32_t);
uint32_t (*fp7p)(uint32_t, uint32_t, uint32_t);
} fp;
struct command
{
char *name; //command name
uint32_t minargs;
uint32_t maxargs;
int minval;
int maxval;
fp read_func_pointer;
fp write_func_pointer;
};
struct command commands[] =
{
[0] = { "reg1001", 0,0,0,0, .read_func_pointer.fp6p = TDC1000_SPIByteReadReg, .write_func_pointer.fp4p = TDC1000_SPIByteWriteReg },
//
//
};
接着
if(condition)
{
uint32_t ret_val = commands[0].read_func_pointer.fp6p(…);
}
else
{
commands[0]. write_func_pointer.fp6p(…);
}
如何使其通用而不是.fp6p?
我不知道這是否是您的選擇,但是如何將代表函數指針類型的枚舉添加到您的結構中呢?
在conditon語句中,您可以打開枚舉,然后調用正確的函數指針。
我認為您可以為工會使用匿名成員:
struct command
{
char *name; //command name
...
union
{
....
void (*fp4p)(uint32_t, uint32_t, uint32_t);
uint32_t (*fp6p)(uint32_t, uint32_t);
};
...
};
對於write_func成員,必須將fp6p
等名稱fp6pw
為fp6pw。 然后直接調用commands[0].fp6p(...)
。 不確定,但初始化必須是您想要的“泛型”。
我想澄清一下。 假設我們有幾個命令
struct command commands[] = {
[0] = { "reg1001", 0,0,0,0, .read_func_pointer.fp6p = TDC1000_SPIByteReadReg, .write_func_pointer.fp4p = TDC1000_SPIByteWriteReg },
[1] = = { "reg7201", 0,0,0,0, .read_func_pointer.fp3p = TDC7200_SPIByteReadReg, .write_func_pointer.fp5p = TDC7200_SPIByteWriteReg },
};
我有一個通用功能來選擇傳入命令
For (i=0; I < sizeof(commands); i++)
{
if (strcmp(commands[i].name,args[0])==0)
{
commands[i]. read_func_pointer.<- Here – how can I know what pointer to place?
}
}
在便攜式標准C99或C11中,無法實現僅在運行時調用簽名功能。 簽名應該在編譯時就已經知道(您可以擴展代碼,從概念上講,可以通過帶有標記的函數指針聯合 ,即保留用於描述簽名的標簽)。 之所以這樣,是因為調用約定可以(並且確實)隨函數簽名而變化(ABI將使用不同的寄存器來傳遞不同種類或類型的參數或結果)。
或者,考慮使用libffi ; 它包含了一些魔法(匯編代碼,依賴於的ABI ),這將調用一個任意函數指針其簽名是由一些元數據描述 。
如果您以POSIX為目標,則可以使用一些dlopen和dlsym技巧(您可能還考慮在Qt5或POCO或Glib等框架中支持插件)。 您可能會(在運行時)在generated-code-001.c
中generated-code-001.c
一些適當的(膠水)C代碼,通過派生一些編譯器命令進行編譯(例如, gcc -Wall -O -fPIC generated-code-001.c -shared -o generated-code-001.so
),然后dlopen
./generated-code-001.so
共享對象(在Linux上;在MacOSX上,編譯命令和文件擴展名不同),然后使用dlsym
獲取函數指針。 我在MELT中廣泛使用了這些技巧
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.