【问题标题】:Callback from QThread in unmanaged dll to managed c++ Main thread从非托管 dll 中的 QThread 回调到托管 C++ 主线程
【发布时间】:2012-08-15 13:30:36
【问题描述】:

我想从在本机 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 - run 方法,我在这里进行回调,但回调在我的新线程中继续,而不是在我的托管 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 -> 主线程吗?

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

【问题讨论】:

  • 听起来你在混合回调和事件循环的概念——thread1 正在调用函数,所以代码在thread1 中执行。 Qt 线程有event loops - 你的主线程有类似的东西吗?您想将事件发布到循环中,而不是简单地使用回调函数。
  • 我注意到我没有提到这一点,我在 .net 表单应用程序中引用了我的包装器 dll,应用程序事件循环是我在这件事上的“主线程”。我知道如何在两个 qt 线程之间使用信号和槽,但问题是当我需要通过我的 c++ 包装器从我的非托管线程 dll 到我的 .net 表单应用程序时。如何从我的 qt dll 向我的 .net 事件循环发布事件,这真的是我的问题吗?

标签: c++ multithreading qt callback


【解决方案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)

【讨论】:

  • 是的,我注意到了,当然,感谢您的链接,看起来很有希望。我注意到我也可以通过在我的 .net 表单应用程序中调用委托来以另一种方式做到这一点,但我明白你的意思。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-03-04
  • 2013-01-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-14
相关资源
最近更新 更多