I am having problems trying to invoke a method from an object running in another thread.
I have a simple gui application that needs to be wrapped into a DLL for use with other software.
I am using visual studio 2013 with the qt plugin for developement of the DLL.
i use the DLLMain function to start the messageloop for the gui app with the following code:
static HANDLE hThread;
BOOL APIENTRY DllMain(HINSTANCE hInstance, DWORD fdwReason, LPVOID lpReserved)
{
UNREFERENCED_PARAMETER(lpReserved);
switch (fdwReason)
{
case DLL_PROCESS_DETACH:
qDebug
() <<
"DLL is being unloaded" <<
QThread::currentThreadId();
break;
case DLL_PROCESS_ATTACH:
{
qDebug
() <<
"DLL is being loaded" <<
QThread::currentThreadId();
hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)main, (LPVOID)hInstance, 0, NULL);
if (hThread != NULL)
break;
else
return FALSE;
}
case DLL_THREAD_ATTACH:
qDebug
() <<
"Process creating thread" <<
QThread::currentThreadId();
break;
case DLL_THREAD_DETACH:
qDebug
() <<
"Process thread exiting" <<
QThread::currentThread();
break;
}
return TRUE;
}
int main(int argc, char *argv[])
{
qDebug
() <<
QThread::currentThreadId();
argc = 0;
w = new Wrapper();
return MyApp.exec();
}
static HANDLE hThread;
BOOL APIENTRY DllMain(HINSTANCE hInstance, DWORD fdwReason, LPVOID lpReserved)
{
UNREFERENCED_PARAMETER(lpReserved);
switch (fdwReason)
{
case DLL_PROCESS_DETACH:
qDebug() << "DLL is being unloaded" << QThread::currentThreadId();
break;
case DLL_PROCESS_ATTACH:
{
qDebug() << "DLL is being loaded" << QThread::currentThreadId();
hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)main, (LPVOID)hInstance, 0, NULL);
if (hThread != NULL)
break;
else
return FALSE;
}
case DLL_THREAD_ATTACH:
qDebug() << "Process creating thread" << QThread::currentThreadId();
break;
case DLL_THREAD_DETACH:
qDebug() << "Process thread exiting" << QThread::currentThread();
break;
}
return TRUE;
}
int main(int argc, char *argv[])
{
qDebug() << QThread::currentThreadId();
argc = 0;
QApplication MyApp(argc, NULL);
w = new Wrapper();
return MyApp.exec();
}
To copy to clipboard, switch view to plain text mode
First of all, while debugging this does not give me any warning about the QApplication not being created in the main thread. While when using the same code in Qt creator does give warning (they are both using the same compiler from vs2013).
the following function is used to invoke a method:
unsigned __stdcall voxy_init(HWND hParent)
{
qDebug() << "";
qDebug() << "voxy_init";
qDebug
() <<
QThread::currentThreadId();
unsigned errorState = 0;
qRegisterMetaType<HWND>("HWND");
Q_ARG(HWND, hParent))
)
qDebug() << "Invocation successful";
return errorState;
}
unsigned __stdcall voxy_init(HWND hParent)
{
qDebug() << "";
qDebug() << "voxy_init";
qDebug() << QThread::currentThreadId();
unsigned errorState = 0;
qRegisterMetaType<HWND>("HWND");
if (QMetaObject::invokeMethod(w, "connectDialog",
Q_ARG(HWND, hParent))
)
qDebug() << "Invocation successful";
return errorState;
}
To copy to clipboard, switch view to plain text mode
When this function runs, invokeMethod() returns true but the method never runs!
here is the method i am trying to invoke:
{
Q_OBJECT
public:
Wrapper();
private slots:
void connectDialog(HWND);
void debugDialog();
};
void Wrapper::connectDialog(HWND parent)
{
qDebug() << "ConnectionDialog";
qDebug
() <<
QThread::currentThreadId();
ConnectWindow c;
c.setWindowFlags(Qt::WindowStaysOnTopHint);
::SetParent((HWND)c.winId(), parent);
c.setGeometry(400,400,400,400);
c.setWindowFlags(Qt::WindowStaysOnTopHint);
c.setWindowModality(Qt::ApplicationModal);
int res = c.exec();
qDebug() << "user accepted selection";
// Connect to the selection made by the user
} else{
return;
}
return;
}
class Wrapper : public QObject
{
Q_OBJECT
public:
Wrapper();
private slots:
void connectDialog(HWND);
void debugDialog();
};
void Wrapper::connectDialog(HWND parent)
{
qDebug() << "ConnectionDialog";
qDebug() << QThread::currentThreadId();
ConnectWindow c;
c.setWindowFlags(Qt::WindowStaysOnTopHint);
::SetParent((HWND)c.winId(), parent);
c.setGeometry(400,400,400,400);
c.setWindowFlags(Qt::WindowStaysOnTopHint);
c.setWindowModality(Qt::ApplicationModal);
int res = c.exec();
if (res == QDialog::Accepted){
qDebug() << "user accepted selection";
// Connect to the selection made by the user
} else{
return;
}
return;
}
To copy to clipboard, switch view to plain text mode
Any hints on what could be my problem?
EDIT: I found out that when building the DLL using QtCreator with the msvc compiler, it does work but only once. this makes it even more confusing...
EDIT 2: After more debugging this i found out that after the invoked method (Wrapper::connectDialog) returns the thread that it lives on (QApplication thread) exits with the following output in the debug window: The thread 0xf28 has exited with code 0 (0x0).
EDIT 3: More debugging fixed my problem with the invocation only working once. The application was exiting after closing the last open window. Still having the problem of the invoke not happening in vs2013...
Thanks,
Sisco
Bookmarks