低冗长的 C 泛型继承

C generic inheritance with low verbosity

拥有:

struct packet_sample_t {
   int common_id;
   int some;
   char data[];
   float foo;
}

具有以下功能:

void dispatch_packet(void *packet);

我的目标是解析数据包 ID,然后调用其处理程序,但我无法从 void * 检索结构变量 common_id

我想用高级语言创建类似 interface 的东西,假设我所有的数据包结构都应该有变量 common_id.
所以我正在寻找可以像下面这样工作的东西:

struct packet_base {
   int common_id;
}

void dispatch_packet(void *packet) {
   int common_id = ( (packet_base *)packet )->common_id;
   switch(common_id) {...}
}

void test() {
   packet_sample_t packet = {.common_id = 10, ...};
   dispatch_packet((void *) &packet); //this function should retrieve `common_id`

   packet_other_t other = {.common_id = 1};
   dispatch_packet((void *) &other); // again with another packet
}

我对 C 语言不是很熟悉,我真的不知道我该怎么做。但简单来说,我希望能够将一个数据包投射到它的packet_base,它们共享一个公共变量。

编辑:示例中有更多详细信息

您可以使用union将不同类型的数据聚合到一个结构中

struct packet1_t
{
   // Packet1 specific data
   ......
}

struct packet2_t
{
   // Packet2 specific data
   ......
}

struct packet_t
{
    int common_id;
    union
    {
        struct packet1_t packet1;
        struct packet2_t packet2;
        ......
    }
} packet;

现在,您可以根据 ID 从联合中选择正确的类型:

int do_something_with_packet(packet_t packet)
{
    switch (packet.common_id)
    {
        case 1:
            do_something_with_packet1(packet.packet1);
            break;
        case 2:
            do_something_with_packet2(packet.packet2);
            break;
        ..................
    }
    ....
}

你的技术是有效的。有 a number of ways to do struct inheritance in C, and this is one of them. 21st Century C might be a good read for you as well as Object-Oriented Programming with ANSI C.

您在声明和使用您的结构和类型时遇到了问题。让我们看看这个。

struct packet_base {
   int common_id;
};

它的类型是 struct packet_base。如果要声明指向此类型的指针,则需要编写 struct packet_base *packet。如果你想转换这种类型的变量,它是 (struct packet_base *)thing.

这很烦人,因此您通常使用 typedef 为结构声明一个类型别名。语法是 typedef <type> <alias>

typedef struct {
   int common_id;
} packet_base_t;

这表示类型 struct { int common_id; }packet_base_t 的别名。现在您可以使用 packet_base_t 作为类型。 packet_base_t *packet 声明一个指针并 (packet_base_t *)thing 转换。

修复后,再加上一些小错误,它就可以工作了。请参阅 What is the difference between char array vs char pointer in C? 了解 char *datachar data[]

typedef struct {
   int common_id;
   int some;
   char *data;
   float foo;
} packet_sample_t;

typedef struct {
   int common_id;
} packet_base_t;

void dispatch_packet(void *arg) {
    // It's simpler to cast to a new variable once then to muck
    // up the code with casts.
    packet_base_t *packet = (packet_base_t *)arg;

    int common_id = packet->common_id;
    printf("id: %d\n", common_id);
}