每个结构体调用只使用一次的函数指针

4

我有一个包含多个函数指针的结构体。通用接口在头文件中定义。

头文件

typedef struct
{
    void (*Start)(void);
    void (*ByteWrite)(uint8_t *pBuffer);        // Modifies I2C buffer
    uint8_t (*ByteRead)(uint8_t *pBuffer);
    void (*ArrayWrite)(uint8_t *pBuffer);
    uint8_t (*ArrayRead)(uint8_t *pBuffer);
    bool (*Busy)(void);
} sI2C_t;


extern const sI2C_t I2C0;
extern const sI2C_t I2C1;
extern const sI2C_t I2C2;

然后在C文件中,每个函数指针都实现以满足结构接口。

C文件

static void I2C0_Start(void) { ... }
static void I2C0_ByteWrite(*uint8_t) { ... }
static uint8_t I2C0_ByteRead(*uint8_t) { ... }
static void I2C0_ArrayWrite(*uint8_t) { ... }
static uint8_t I2C_ArrayRead(*uint8_t) { ... }
static bool I2C_Busy(void) { ... }

const sI2C I2C0 =
{
    I2C0_Start,
    I2C0_ByteWrite,
    I2C0_ByteRead,
    I2C0_ArrayWrite,
    I2C0_ArrayRead,
    I2C0_Busy
};

// Code-block repeated for I2C1, I2C2, etc. (REDUNDANT!)

这使得访问特定于I2C接口的函数相对容易:
bool status;

I2C0.Start();
status = I2C1.Busy();
...

虽然 I2C0、I2C1 和 I2C2 等函数指针基本相同,但我必须为每个新的结构接口单独编写出它们。既然这是冗余的,那么有没有办法只实现这些函数指针一次呢?


这可能是宏是合理解决方案的情况之一。话虽如此,如果您将I2C0I2C1等作为变量名,那么使用数组可能会是更好的整体方法? - Oliver Charlesworth
像这样 extern const sI2C_t I2C[MAX_NUM];?每个函数仍然必须为其定义,对吗?您能举个例子说明我如何使用宏吗? - Biff
1
X-Macros 来拯救! - luser droog
X-Macros能让我区分I2C0/1/2吗?在函数指针中,我需要预先考虑这一点。 - Biff
*uint8_t?你确定可以在参数列表中解引用一个类型名吗? - autistic
2个回答

1
标准解决方案是将结构体指针作为函数的第一个参数传递。即,不要使用以下方式:
I2C0.Start();

你写:

你写:

I2C0.Start(&I2C0);

您可以向该结构添加一些额外的字段以标识它是哪个(例如,如果每个I2C总线都有固定的硬件地址,则可以在结构的额外字段中具有硬件地址)。
这是相当于C++类的正常C方法。

我曾考虑过将其作为指针传递,但我认为因为我区分 I2C0/1/2(例如 I2C0.Start()I2C1.Start()),所以可以隐含地指示它是哪一个。 - Biff

0
你可以编写一个构造函数。例如:
typedef struct{
     int    a;
     char   b;
}example;

void constructor (example *pointer_to_struct, int a_value, char b_value){
    pointer_to_struct->a = a_value;
    pointer_to_struct->b = b_value;   /*remember: if you have strings don't have any 
                                     assignments, since a string (like any other array) is a pointer to 
                                     its first element*/
}


int main (void){

    example ex_struct;
    constructor(&ex_struct, 10, 'C');

    return 0;
}

编辑:您还可以编写一个函数,为所选类型的每个结构执行相同的赋值操作。例如:

void constructor(structure *p){
     p->a = 10;
     p->b = 'C';
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接