从非托管dll中的QThread回调到托管c ++主线程

时间:2012-08-15 13:30:36

标签: c++ multithreading qt callback

我想从一个在本地dll中创建的线程回调到我的托管包装器,我已成功创建了我的线程,并通过Qt.s框架信号和插槽进行了调用。

如何从单独的线程回调到非托管和托管dll之间的主线程?非托管是在QT c ++和托管的VS c ++中完成的。

非托管dll: main.cpp中

typedef void (__stdcall * processCallback)(char*, int, int);
Thread* thread;
EXTEXPORT_VOID initdll(processCallback callback)
{
    /* Init MainThread - Runs eventloop */
    thread = new Thread(callback);
    thread ->start();
}

thread.h - 运行方法,我在这里进行回调,但回调在我的新线程中继续,而不是在我的托管dll中创建它的主线程。为什么呢?

void run() {
    callback("Testing callback", 0, 0);
    exec();
}

我需要这个回调来到我的主线程而不是我现在正在运行的线程。

托管dll

/* From unmanaged to managed c++ */
[UnmanagedFunctionPointerAttribute(CallingConvention::StdCall)] 
public delegate void UnmanagedCallbackDelegate(char*, int, int);

typedef void (__stdcall * typeCallback)(char*, int, int); //Same def as in Unm. dll
public ref class cDLLThreadWrapper
{
    [DllImport("cDLL.dll", CallingConvention=CallingConvention::StdCall)] 
    static void initdll(typeCallback);

public:
    typeCallback callbackNative;
    UnmanagedCallbackDelegate^ m_CallbackDelegate;

    cDLLThreadWrapper()
    {

    }
    void init()
    {
        m_CallbackDelegate = gcnew UnmanagedCallbackDelegate(this, &cDLLThreadWrapper::UnhandledCallback);
        IntPtr ptr = Marshal::GetFunctionPointerForDelegate(m_CallbackDelegate);
        callbackNative = static_cast<typeCallback>(ptr.ToPointer());

        initdll(callbackNative);
    }
            void UnhandledCallback(char* data, int x, int y)
    {
        String^ callStr = gcnew String(data);
                    //AppDomain.GetCurrentThreadId())
        //I get here but the thread is wrong, it should be the main thread
                    //which called the initdll function from this wrapper.
    }
}

正如我所说的回调有效但由于某种原因我在错误的线程中得到它,不应该回调来自thread1 - &gt;主线?

这是一个非常简化的示例,但具体问题是为什么我的回调不会从我新创建的线程转到主线程,而是保留在新创建的线程中。我错在哪里?任何帮助表示赞赏!

1 个答案:

答案 0 :(得分:1)

您正在直接通话中执行回叫,令您感到惊讶的是什么?如果您在Qt中执行callback(...),它将在您的新线程中执行并继续。它相当于声明与Qt::DirectConnection类型的信号槽连接。当调用者线程和目标线程不同时,Qt很聪明并为你做幕后Qt::QueuedConnection。但为了使其自动工作,源必须声明为signal,目标必须声明为slot,目标必须是QThread,具有Qt特定的事件循环运行。您在托管C ++中运行了“某个”事件循环,但Qt不知道如何以及在那里发布什么。绝对不是QObject元数据,您的.NET C ++将无法理解它。 Qt魔法仅在Qt内部起作用。您必须了解如何将特定事件发布到.NET C ++并教您的Qt代码来执行此操作。我不是.NET专家,但以下内容看起来很有用

How to map Qt Signal to Event in Managed C++ (C++/CLI)