繁体   English   中英

C中工会成员的条件替换

[英]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为目标,则可以使用一些dlopendlsym技巧(您可能还考虑在Qt5POCOGlib等框架中支持插件)。 您可能会(在运行时)在generated-code-001.cgenerated-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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM