我有一个工作示例,它使用信号和插槽在Qt共享库(dll)和Qt应用程序之间进行通信。我的问题是,它是首选方式还是有更好的方法来处理qt共享库。以下是详细信息:
我开发的应用程序具有监听网络上的设备和更新GUI的功能。共享库处理侦听网络上的设备,Qt应用程序模块处理GUI部分。
我有一个宏,它使用Q_DECL_EXPORT / Q_DECL_IMPORT来导出共享库和应用程序使用的公共类。该公共类派生自QObject并定义Qt信号和时隙。这个公共类是作为共享库(dll)的一部分构建的。
Qt应用程序在编译时加载了共享库,并为公共类创建了一个实例,并使用该实例在Qt应用程序和Qt共享库模块之间设置信号和插槽,如下所示:
在Qt应用程序初始化期间:
// Create shared libray API class instance to access dll module features.
mp_sharedlib_api = new shareLibAPIClass( this );
以后在Qt应用程序中:
// Connect signal/slot between shared library and Qt application
connect(
mp_sharedlib_api , SIGNAL( SignalUpdateGUIStatus( QString ) ),
this, SLOT( SlotUpdateGUIStatus( QString ) )
);
这是开发使用共享库的Qt项目的正确方法吗?共享库的API文档包含什么? API文档是否列出了共享库发送/处理的信号和插槽?
提前致谢。
答案 0 :(得分:4)
您不应该想到通过信号和插槽连接的两个库,而是一组类/类实例,一组与后端相关的类和一组与UI相关的类。 UI类使用后端类(但从不相反)。这两组类在不同的库中是部署的实现细节,并且与C ++级别的应用程序设计大多无关。即使所有代码在单个应用程序中链接在一起,设计概念也是相同的。
使用单个信号signalUpdateGUIStatus(QString)
的单个“公共类”很可能是错误的方法。将接口限制为单个类甚至信号是没有意义的,因为它是一个单独的库。小接口很好 - 但除非你的后端代码只发送一种非常特殊的更新,“signalUpdateUIStatus(QString whatChangedEncodedAsString)”将通过单个类/信号做太多。
signalUpdateGUIStatus还意味着后端库知道有一个UI。它不应该。它只是提供有关网络上设备的信息 - 是否有显示信息的UI或某些机器人通过电子邮件(或其他)发送通知都不是它的业务。
你可以拥有一个带有导出类的共享库,如LightSensorListener,TemperatureSensorListener等(或者只是DeviceListener,依赖),当值发生变化时可能是QObjects发出信号,但也有任何其他Q_PROPERTY,方法等。这些类将在应用程序中实例化,然后连接到UI代码。
想想你在应用程序中如何使用Qt。您的库将是另一个库,其类用于从网络获取数据。就像您使用QString,QWidget,QLineEdit等创建UI并与UI交互一样,您可以使用库的类来与网络连接:
假设我们的库“foo”有一个类TemperatureSensor:
//file TemperatureSensor.h
/**
* A temperature sensor on the network.
* yaddayaddayadda
*/
class FOO_EXPORT TemperatureSensor {
Q_OBJECT
Q_PROPERTY(QString address READ address WRITE setAddress NOTIFY addressChanged)
Q_PROPERTY(bool available READ available NOTIFY availableChanged)
Q_PROPERTY(qreal temperature READ temperature NOTIFY temperatureChanged)
public:
/**
* Creates a temperature sensor
*
* @param parent parent QObject
*/
explicit TemperatureSensor(QObject* parent=0);
/**
* Returns whether the device is currently available and delivering data
*/
bool available() const;
/**
* Returns the temperature reported by the sensor (In Celsius)
*/
qreal temperature() const;
/**
* Makes the device explode. Use with caution!
* Don't give this to little developers/children.
*/
void blowUp();
//address(), setAddress() etc...
Q_SIGNALS:
/**
* The availability of the sensor changed
*
* @param available whether the sensor is now available
*/
void availableChanged(bool available);
void temperatureChanged(qreal);
void addressChanged(const QString&);
};
然后在应用程序中,您只需创建实例并将其与UI连接起来:
TemperatureSensor sensor;
sensor.setAddress("/tempsensors/1234");
TemperaturWidget widget;
widget.show();
//connect signals from sensor, or pass the whole sensor instance, etc.
对于文档,应记录库的所有公共类(即导出的所有内容)。信号/插槽通常与其他“常规”方法一样记录。