0

我想从在本机 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.
    }
}

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

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

4

1 回答 1

1

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

如何在托管 C++ (C++/CLI) 中将 Qt 信号映射到事件

于 2012-08-15T14:46:31.917 回答