假设我有两个设备驱动程序,我希望它们共享相同的界面,这样调用者就不知道它正在与哪个驱动程序进行通信。我如何在C中组织这个?我想过几个方法:
首先:为具有相同接口的两个驱动程序创建一对.c / .h文件,并在调用者中创建一个开关:
//main.c:
#ifdef USING_DRIVER_1
#include "driver_1.h"
#else
#include "driver_2.h"
#endif // USING_DRIVER_1
第二:使用单个标题并在驱动程序的源文件中创建一个文件长开关,如下所示:
//driver_1.c:
#ifdef USING_DRIVER_1
#include "driver.h"
bool func(uint32_t var)
{
foo(var);
}
#endif // USING_DRIVER_1
//driver_2.c:
#ifndef USING_DRIVER_1
#include "driver.h"
bool func(uint32_t var)
{
bar(var);
}
#endif // !USING_DRIVER_1
第三:这个与第二个很相似,但不是在文件本身中使用switch语句,而是在makefile或IDE中选择特定的驱动程序:
#makefile:
SRC = main.c
#SRC += driver_1.c
SRC += driver_2.c
我敢肯定其中一个优于其他人,可能还有一些我没想过。它在实践中是如何完成的?
编辑:
有关我的特定系统的详细信息:我的目标是ARM微控制器和我的开发人员。环境是一个IDE。设备驱动程序用于两个不同的修订版,并且永远不会同时使用,因此每个版本应该只包含一个版本。设备本身是通过AT命令运行的调制解调器。
答案 0 :(得分:2)
我建议使用指向函数的指针。例如:
struct driver_api {
bool (*pFunc)(uint32_t);
} DriverApi;
void initializeApi(struct driver_api *pApi);
// driver1.c:
void initializeApi(struct driver_api *pApi)
{
pApi->pFunc = bar;
}
// driver2.c:
void initializeApi(struct driver_api *pApi)
{
pApi->pFunc = foo;
}
您可能考虑的另一件事是从源文件中删除#ifndef USING_DRIVER_1
个检查。使用构建系统(例如make)并指定项目中应包含哪些源文件。然后,基于某些编译时选项(例如命令行参数)包括driver1.c
或driver2.c
,但不包括两者。
指针的“优点”是你可以编译两个API,然后在运行时决定(甚至在运行中改变它,无论出于何种原因)。
答案 1 :(得分:2)
这三种变体实际上都很有用。选择哪个取决于您实际需要的内容:
const struct
,它们提供接口(函数指针和可能的其他数据)。#if .. #elif #end
进行条件编译。如果两个驱动程序只有很小的差异,例如,这是有道理的。不同的SPI接口(SPI1与SPI2 ......)。那么这就是要走的路。通过构建工具的一些努力,您甚至可以将其用于案例1.(一个文件用于两个不同的驱动程序,但不是我的建议)。除了第一种方法之外的所有方法,两个驱动程序都必须为应用程序提供相同的接口。第一种方法实际上允许存在差异,但这实际上需要用户代码将它们区别对待并且可能不是您想要的。
对两个驱动程序使用单个头文件(例如:" spi_memory.h"" spi_flash.c" vs." spi_eeprom.c")确保应用程序确实没有看到实际的差异 - 当然,只要驱动程序行为相同。接口中的变量(例如extern size_t memory_size;
)或函数(更好的方法)可以捕捉到微小的差异。