PDA

View Full Version : QMetaObject::InvokeMethod returns true but method is never invoked



sisco
20th June 2014, 10:22
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;
QApplication MyApp(argc, NULL);
w = new Wrapper();
return MyApp.exec();
}

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");

if (QMetaObject::invokeMethod(w, "connectDialog",
Q_ARG(HWND, hParent))
)
qDebug() << "Invocation successful";

return errorState;
}
When this function runs, invokeMethod() returns true but the method never runs!
here is the method i am trying to invoke:

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;
}
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... :confused:
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

sisco
20th June 2014, 23:25
This problem can now be marked as fixed....

It seems to be a problem with visual studio as the code works fine in QtCreator and realese builds from VS2013 but not when debugging. I will open a different thread for that problem next week.