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

C++ 从非托管dll中的QThread回调到托管c++;主线,c++,multithreading,qt,callback,C++,Multithreading,Qt,Callback,我想从本机dll中创建的线程回调到托管包装器,我已经成功创建了线程,并通过Qt.s框架信号和插槽进行了调用 如何在非托管和托管dll之间从单独的线程回调到主线程?非托管是在Qt++中完成的,VS C++ C++的管理程序。 非托管dll: main.cpp h-run方法,我在这里进行回调,但是回调在我的新线程中继续,而不是在托管dll中创建回调的主线程。为什么? void run() { callback("Testing callback", 0, 0); exec(); }

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

如何在非托管和托管dll之间从单独的线程回调到主线程?非托管是在Qt++中完成的,VS C++ C++的管理程序。 非托管dll: main.cpp

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.
    }
}
<代码> >从非托管到托管C++ * [非托管FunctionPointerAttribute(调用约定::StdCall)] 公共委托void UnmanagedCallbackDelegate(char*,int,int); typedef void(u stdcall*typeCallback)(char*,int,int)//与Unm中的def相同。动态链接库 公共引用类cDLLThreadWrapper { [DllImport(“cDLL.dll”,CallingConvention=CallingConvention::StdCall)] 静态void initdll(typeCallback); 公众: 类型回调callbackNative; UnmanagedCallbackDelegate ^m_CallbackDelegate; cDLLThreadWrapper() { } void init() { m_CallbackDelegate=gcnew UnmanagedCallbackDelegate(this,&cDLLThreadWrapper::UnhandledCallback); IntPtr ptr=Marshal::GetFunctionPointerForDelegate(m_CallbackDelegate); callbackNative=static_cast(ptr.ToPointer()); initdll(callbackNative); } 无效未处理回调(字符*数据,整数x,整数y) { 字符串^callStr=gcnew字符串(数据); //AppDomain.GetCurrentThreadId()) //我到了这里,但线程是错误的,它应该是主线程 //从这个包装器调用initdll函数。 } } 正如我所说的,回调是有效的,但是由于某种原因,我把它放在了错误的线程中,回调不应该来自thread1->Main-thread吗


这是一个非常简单的示例,但具体的问题是为什么我的回调没有从新创建的线程转到主线程,而是停留在新创建的线程中。我哪里想错了?感谢您的帮助

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


听起来像是在混合回调和事件循环的概念-
thread1
正在调用函数,因此代码在
thread1
中执行。Qt线程有-你的主线程有类似的东西吗?您希望向循环发布事件,而不是简单地使用回调函数。我注意到我没有提到这一点,我在.net表单应用程序中引用了我的包装器dll,应用程序事件循环是我在这方面的“主线程”。我知道如何在两个QT线程之间使用信号和时隙,但问题是当我需要通过我的C++包装器从非托管线程DLL中获得到.NETFrm应用程序。我怎样才能从我的qt dll将一个事件发布到我的.net事件循环中,这是我真正的问题?是的,我注意到了,当然,感谢链接,看起来很有希望。我注意到,我也可以通过调用.NETForms应用程序中的委托以另一种方式来实现,但我明白你的意思。
/* 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.
    }
}