我正在尝试创建一个DLL,它是我们USB设备的API。该库应该也适用于非Qt应用程序。我已经将所有的Qt内容和私有类都PIMPL化了,因此下面的代码是公共类下的一层。我正在使用QSerialPort和大量的SIGNAL/SLOT,因此需要QCoreApplications事件循环。ReaderSerial是Qt内容开始的地方,它还实例化了另一个类,在其中QSerialPort在不同的QThread中运行。
目前我的问题是整个系统在错误“QTimer can only be used with threads started with QThread”上崩溃了。
我猜测我的基于Qt的类,如ReaderSerial,并没有“看到”QCoreApp事件循环或类似的东西。因此,我的问题是如何向我的DLL提供QCoreApplication事件循环,以便我创建的所有基于Qt的类都能正常工作,并且我可以从我的DLL中调用方法。
非常感谢您的回答。
reader_p.h
class ReaderPrivate
{
public:
ReaderPrivate();
~ReaderPrivate();
void static qCoreAppExec();
ReaderSerial *readerSerial;
void connectReader(std::string comPort);
void disconnectReader();
};
reader.cpp
// Private Qt application
namespace QAppPriv
{
static int argc = 1;
static char * argv[] = {"API.app", NULL};
static QCoreApplication * pApp = NULL;
};
ReaderPrivate::ReaderPrivate()
{
std::thread qCoreAppThread(qCoreAppExec);
qCoreAppThread.detach();
readerSerial = new ReaderSerial;
}
ReaderPrivate::~ReaderPrivate()
{
delete readerSerial;
}
void ReaderPrivate::qCoreAppExec()
{
if (QCoreApplication::instance() == NULL)
{
QAppPriv::pApp = new QCoreApplication(QAppPriv::argc, QAppPriv::argv);
QAppPriv::pApp->exec();
if (QAppPriv::pApp)
delete QAppPriv::pApp;
}
}
void ReaderPrivate::connectReader(std::string comPort)
{
readerSerial->openDevice(comPort);
}
void ReaderPrivate::disconnectReader()
{
readerSerial->closeDevice();
}
根据@Kuba Ober的回答,我创建了一个共享库。花费了一些时间来理解发生了什么以及如何使其工作,但它仍然没有做到应该做的事情。因此,我现在正在寻求建议如何使这段代码工作。
apic.h
#include "Windows.h"
extern "C"
{
__declspec(dllexport) void WINAPI kyleHello();
}
apic.cpp
#include "apic.h"
#include "appthread.h"
void WINAPI kyleHello()
{
worker->hello();
}
BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID)
{
static AppThread *thread;
switch (reason)
{
case DLL_PROCESS_ATTACH:
thread = new AppThread;
thread->start();
break;
case DLL_PROCESS_DETACH:
delete thread;
break;
default:
break;
}
return TRUE;
};
appthread.h
#include <QThread>
#include <QCoreApplication>
#include <QPointer>
#include "worker.h"
static QPointer<Worker> worker;
class AppThread : public QThread
{
public:
AppThread();
~AppThread();
// No need for the Q_OBJECT
QPointer<QCoreApplication> m_app;
void run() Q_DECL_OVERRIDE
{
std::cout << "\n AppThread::run";
int argc;
char *argv;
QCoreApplication app(argc, &argv);
m_app = &app;
std::cout << "\nAppThread::run before Worker";
Worker worker_;
worker = &worker_;
std::cout << "\nAppThread::run before app.exec";
app.exec();
}
//using QThread::wait(); // This wouldn't work here.
};
appthread.cpp
#include "appthread.h"
AppThread::AppThread()
{
std::cout << "\n AppThread::ctor";
}
AppThread::~AppThread()
{
std::cout << "\n AppThread::dtor \n";
m_app->quit();
wait();
}
worker.h
#include <QObject>
#include <QDebug>
#include <iostream>
class Worker : public QObject
{
Q_OBJECT
Q_INVOKABLE void helloImpl()
{
std::cout << "I'm alive.";
//qDebug() << "I'm alive.";
}
public:
Worker();
void hello();
};
worker.cpp
#include "worker.h"
Worker::Worker()
{
std::cout << "\nWorker::ctor";
hello();
}
void Worker::hello()
{
std::cout << "\nWorker::hello()";
// This is thread-safe, the method is invoked from the event loop
QMetaObject::invokeMethod(this, "helloImpl", Qt::QueuedConnection);
}
通常情况下,这样的输出是:
AppThread::ctor
Worker::hello()
AppThread::dtor
有时候:
AppThread::ctor
Worker::hello()
AppThread::run
AppThread::dtor
有时候:
AppThread::ctor
Worker::hello()
AppThread::dtor
QMutex: destroying locked mutex
GitHub代码库:https://github.com/KyleHectic/apic.git