定义为常量的数组成员
Array members defined as constants
我正在尝试实现一个框架,我需要在其中声明(在 .h 文件中)可用 "drivers"(结构变量)的列表,这些列表将在特定的 .c 模块中定义。由于该列表将来可能会增加,我希望将其全部放在 .h 文件中的一个位置,以使其易于扩展。
例如让我们有 "driver.h"
typedef struct driver {
int id;
char name[10];
int(*init)();
void (*deinit)();
int (*doTheJob)(int);
} driver_t;
#define DRIVERLIST driver1, driver2, driver3
#define DRIVERS extern driver_t DRIVERLIST;
DRIVERS
然后特定的驱动程序(driver1、driver2、driver3)将在专用模块中定义。例如driver1.c, driver2.c ..等等...
但是我想要一个模块,例如manager.c 我想在其中定义可用驱动程序数组,如 driver.h 中声明的那样,以便我能够迭代该数组并获取驱动程序以供框架的其他部分使用..
所以在 manager.c 我需要这样的东西:
driver_t drivers[MAX_DRIVERS] = {DRIVERS}
但是显然不是这样编译的..
主要思想是当我将来需要为其他驱动程序添加声明时只编辑 driver.h 然后只在专用模块中实现它,而无需编辑例如manager.c 或框架的其他部分..
你知道如何在 c 中实现这种机制吗?
在 C 中,您不能使用某些对象的副本来初始化数组(在 C++ 中可以,但这不是好的做法,因为它们是 副本 ,并且将与原始对象独立更改对象)。
drivers
数组应包含指向原始对象的指针。我建议
/* driver.h */
typedef struct driver {
int id;
char name[10];
int(*init)();
void (*deinit)();
int (*doTheJob)(int);
} driver_t;
#define MAX_DRIVERS 10
#define DRIVERLIST driver1, driver2, driver3
#define DRIVERS_INIT {&driver1, &driver2, &driver3}
#define DRIVERS extern driver_t DRIVERLIST;
DRIVERS
/* manager.c */
#include "driver.h"
/* ... */
driver_t * drivers[MAX_DRIVERS] = DRIVERS_INIT;
管理器代码将使用 drivers[i]->id
而不是 drivers[i].id
。
在 C 中执行此操作的正确方法是立即摆脱所有带有全局变量的 extern
-spaghetti。
相反,您可以将结构定义放在 driver.h
中,并在 driver.c
中通过 "constructor":
对其进行初始化
// driver.c
#include "driver.h"
#include "specific_driver_x.h"
void driver_init (driver_t* driver)
{
driver->init = specific_driver_init;
driver->doTheJob = specific_driver_job;
}
对于专业代码,这可以通过 here 解释的 "opaque type" 概念进一步改进,以实现私有封装(如果需要,还可以实现多态性)。在这种情况下,结构定义可以(部分)隐藏在 driver.c 中,并且构造函数还处理内存分配。
我想我找到了解决办法。我从 rtl_433 项目 https://github.com/merbanan/rtl_433/blob/master/include/rtl_433_devices.h 中获得灵感,他们在其中为设备声明定义了类似的东西。
所以它应该在头文件中:
/* driver.h */
#define DRIVERS \
DECL(driver1) \
DECL(driver2)
#define DECL(name) extern driver_t name;
DRIVERS
#undef DECL
然后在模块中:
/* driver.c */
driver_t* drivers[] = {
#define DECL(name) &name,
DRIVERS
#undef DECL
};
我正在尝试实现一个框架,我需要在其中声明(在 .h 文件中)可用 "drivers"(结构变量)的列表,这些列表将在特定的 .c 模块中定义。由于该列表将来可能会增加,我希望将其全部放在 .h 文件中的一个位置,以使其易于扩展。
例如让我们有 "driver.h"
typedef struct driver {
int id;
char name[10];
int(*init)();
void (*deinit)();
int (*doTheJob)(int);
} driver_t;
#define DRIVERLIST driver1, driver2, driver3
#define DRIVERS extern driver_t DRIVERLIST;
DRIVERS
然后特定的驱动程序(driver1、driver2、driver3)将在专用模块中定义。例如driver1.c, driver2.c ..等等...
但是我想要一个模块,例如manager.c 我想在其中定义可用驱动程序数组,如 driver.h 中声明的那样,以便我能够迭代该数组并获取驱动程序以供框架的其他部分使用..
所以在 manager.c 我需要这样的东西:
driver_t drivers[MAX_DRIVERS] = {DRIVERS}
但是显然不是这样编译的.. 主要思想是当我将来需要为其他驱动程序添加声明时只编辑 driver.h 然后只在专用模块中实现它,而无需编辑例如manager.c 或框架的其他部分.. 你知道如何在 c 中实现这种机制吗?
在 C 中,您不能使用某些对象的副本来初始化数组(在 C++ 中可以,但这不是好的做法,因为它们是 副本 ,并且将与原始对象独立更改对象)。
drivers
数组应包含指向原始对象的指针。我建议
/* driver.h */
typedef struct driver {
int id;
char name[10];
int(*init)();
void (*deinit)();
int (*doTheJob)(int);
} driver_t;
#define MAX_DRIVERS 10
#define DRIVERLIST driver1, driver2, driver3
#define DRIVERS_INIT {&driver1, &driver2, &driver3}
#define DRIVERS extern driver_t DRIVERLIST;
DRIVERS
/* manager.c */
#include "driver.h"
/* ... */
driver_t * drivers[MAX_DRIVERS] = DRIVERS_INIT;
管理器代码将使用 drivers[i]->id
而不是 drivers[i].id
。
在 C 中执行此操作的正确方法是立即摆脱所有带有全局变量的 extern
-spaghetti。
相反,您可以将结构定义放在 driver.h
中,并在 driver.c
中通过 "constructor":
// driver.c
#include "driver.h"
#include "specific_driver_x.h"
void driver_init (driver_t* driver)
{
driver->init = specific_driver_init;
driver->doTheJob = specific_driver_job;
}
对于专业代码,这可以通过 here 解释的 "opaque type" 概念进一步改进,以实现私有封装(如果需要,还可以实现多态性)。在这种情况下,结构定义可以(部分)隐藏在 driver.c 中,并且构造函数还处理内存分配。
我想我找到了解决办法。我从 rtl_433 项目 https://github.com/merbanan/rtl_433/blob/master/include/rtl_433_devices.h 中获得灵感,他们在其中为设备声明定义了类似的东西。
所以它应该在头文件中:
/* driver.h */
#define DRIVERS \
DECL(driver1) \
DECL(driver2)
#define DECL(name) extern driver_t name;
DRIVERS
#undef DECL
然后在模块中:
/* driver.c */
driver_t* drivers[] = {
#define DECL(name) &name,
DRIVERS
#undef DECL
};