创建 class 的多个实现,一个用于发送 Qt 信号,一个用于直接使用硬件
create multiple implementations of a class, one to send Qt signals and one to work with hardware directly
我正在为 stm32 上的嵌入式应用程序 运行ning 开发可视化调试器。
因此,调试器将 运行 在 PC 上重用与主应用程序相同的代码,除了触发硬件反应的低级函数,并将改为为 GUI (QT) 发送信号。
我正在寻找一种模式或一些干净的东西,它可以让我在代码中没有大 #ifdef 的情况下做到这一点。
举个例子:
我有 gpio.h 和 gpio.c 文件与 stm32 低级东西一起玩(它们是由 stmCube 半生成的,所以我不能完全改变它们)。
(C code)
void GPIO_set_realy_state(int relay, bool state)
{
HAL_GPIO_WritePin(port,relay,state?GPIO_PIN_SETGPIO_PIN_RESET);
}
我在它们上面有一个 c++ 包装器 (GpioWrapper),只要应用程序需要更改 IO 的状态就会调用它
GpioWrapper::setRealyState(int relay, bool state)
{
GPIO_set_realy_state(relay,state);
}
在 PC 应用程序中,我想要该包装器的另一种实现或类似的东西,而不是上面的调用,以发送信号而不是调用低级函数使 GUI 更改图标。
GpioWrapper::setRealyState(int relay, bool state)
{
emit RelayTriggered(relay,state);
}
我面临的问题是要发送信号,我的 class 需要从 QObject 继承,在 GpioWrapper.h 中不能是这种情况,因为那部分对 Qt World 毫无头绪在嵌入式应用程序中使用时,我想尽可能避免在我的包装器中使用#ifdef #else。
解决该问题的更简洁方法是什么?
如果您想避免使用 QObject,您可以通过使用 function callback 实现您的 uwn SIGNAL/SLOT 架构,在 C++(11) 中,使用 lambda 函数。
它是实现某些事件的呼叫者通知的替代方法。
标准算法库的许多函数都使用回调。
您可以使您的 GpioWrapper class 抽象并将其放入头文件,并有两个 CPP 文件,其中包含针对 STM 和 QT 情况的实现,以将每个文件包含到相应的项目中
文件GpioWrapper.h:
class GpioWrapper{
public:
static GpioWrapper* Create();
//...
virtual void setRealyState(int relay, bool state) = 0;
//...
};
文件GpioWrapperSTM.cpp(成为STM项目的一部分):
class GpioWrapperSTM: public GpioWrapper{
public:
//...
void setRealyState(int relay, bool state) override
{
GPIO_set_realy_state(relay,state);
}
//...
};
GpioWrapper* GpioWrapper::Create(){
return new GpioWrapperSTM();
}
文件GpioWrapperQT.cpp(成为QT项目的一部分):
class GpioWrapperQT: public QObject, public GpioWrapper{
public:
//...
void setRealyState(int relay, bool state) override
{
emit RelayTriggered(relay,state);
}
//...
};
GpioWrapper* GpioWrapper::Create(){
return new GpioWrapperQT();
}
您应用中某处的示例用法:
std::shared_ptr<GpioWrapper> wrapper = GpioWrapper::Create();
wrapper->setRealyState(10, 20);
注意:实际上不必使用 std::shared_ptr<> 甚至不必通过 new 进行动态分配(这里只是为了说明这个想法)。可以只声明静态 GpioWrapper* Instance() 方法,该方法 returns 指向静态分配的实例等(但要注意所谓的 Meyers 单例 - 对于某些旧编译器,它不是线程安全的)。
我正在为 stm32 上的嵌入式应用程序 运行ning 开发可视化调试器。 因此,调试器将 运行 在 PC 上重用与主应用程序相同的代码,除了触发硬件反应的低级函数,并将改为为 GUI (QT) 发送信号。
我正在寻找一种模式或一些干净的东西,它可以让我在代码中没有大 #ifdef 的情况下做到这一点。
举个例子:
我有 gpio.h 和 gpio.c 文件与 stm32 低级东西一起玩(它们是由 stmCube 半生成的,所以我不能完全改变它们)。
(C code)
void GPIO_set_realy_state(int relay, bool state)
{
HAL_GPIO_WritePin(port,relay,state?GPIO_PIN_SETGPIO_PIN_RESET);
}
我在它们上面有一个 c++ 包装器 (GpioWrapper),只要应用程序需要更改 IO 的状态就会调用它
GpioWrapper::setRealyState(int relay, bool state)
{
GPIO_set_realy_state(relay,state);
}
在 PC 应用程序中,我想要该包装器的另一种实现或类似的东西,而不是上面的调用,以发送信号而不是调用低级函数使 GUI 更改图标。
GpioWrapper::setRealyState(int relay, bool state)
{
emit RelayTriggered(relay,state);
}
我面临的问题是要发送信号,我的 class 需要从 QObject 继承,在 GpioWrapper.h 中不能是这种情况,因为那部分对 Qt World 毫无头绪在嵌入式应用程序中使用时,我想尽可能避免在我的包装器中使用#ifdef #else。
解决该问题的更简洁方法是什么?
如果您想避免使用 QObject,您可以通过使用 function callback 实现您的 uwn SIGNAL/SLOT 架构,在 C++(11) 中,使用 lambda 函数。
它是实现某些事件的呼叫者通知的替代方法。
标准算法库的许多函数都使用回调。
您可以使您的 GpioWrapper class 抽象并将其放入头文件,并有两个 CPP 文件,其中包含针对 STM 和 QT 情况的实现,以将每个文件包含到相应的项目中
文件GpioWrapper.h:
class GpioWrapper{
public:
static GpioWrapper* Create();
//...
virtual void setRealyState(int relay, bool state) = 0;
//...
};
文件GpioWrapperSTM.cpp(成为STM项目的一部分):
class GpioWrapperSTM: public GpioWrapper{
public:
//...
void setRealyState(int relay, bool state) override
{
GPIO_set_realy_state(relay,state);
}
//...
};
GpioWrapper* GpioWrapper::Create(){
return new GpioWrapperSTM();
}
文件GpioWrapperQT.cpp(成为QT项目的一部分):
class GpioWrapperQT: public QObject, public GpioWrapper{
public:
//...
void setRealyState(int relay, bool state) override
{
emit RelayTriggered(relay,state);
}
//...
};
GpioWrapper* GpioWrapper::Create(){
return new GpioWrapperQT();
}
您应用中某处的示例用法:
std::shared_ptr<GpioWrapper> wrapper = GpioWrapper::Create();
wrapper->setRealyState(10, 20);
注意:实际上不必使用 std::shared_ptr<> 甚至不必通过 new 进行动态分配(这里只是为了说明这个想法)。可以只声明静态 GpioWrapper* Instance() 方法,该方法 returns 指向静态分配的实例等(但要注意所谓的 Meyers 单例 - 对于某些旧编译器,它不是线程安全的)。