[英]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.