创建 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 单例 - 对于某些旧编译器,它不是线程安全的)。