我最近一直在修改C#到C++互操作,特别是设置从C++ DLL调用的回调函数。

namespace TomCSharpDLLImport
{
    class Program
    {
        public delegate void TomDelegate(int a, int b);

        [DllImport("TomDllNative.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern void GetData();

        [DllImport("TomDllNative.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern void SetCallback(TomDelegate aCallback);

        static void Main(string[] args)
        {
            TomDelegate lTD = new TomDelegate(Program.TomCallback);

            SetCallback(lTD); //Sets up the callback

            int thread = Thread.CurrentThread.ManagedThreadId;

            GetData(); //This calls the callback in unmanaged code

            while (true) ;
        }

        //Callback function which is called from the unmanaged code
        public static void TomCallback(int a, int b)
        {
            Console.WriteLine("A: {0} B: {1}", a, b);
            int thread = Thread.CurrentThread.ManagedThreadId;
        }
    }
}

我的问题是,当程序控件进入TomCallback函数时,我期望它会再击中Main中的while(true)循环。但是,该程序只是退出。我无法完全理解这种行为,部分人认为这是预期的,但部分人会希望这种情况会持续下去。

我期待的是...
  • GetData()函数称为
  • GetData函数调用回调
  • 回调函数返回到GetData
  • GetData返回到main()

  • 但是,这不太正确。

    有人会很友好地解释发生了什么。

    为了节省空间,我没有发布非托管代码,但是如果需要,我很乐意发布

    编辑:
    我打开了非托管调试(完全忘了这样做),现在我看到了崩溃。



    native 代码,因为这是崩溃的地方
    #include "stdafx.h"
    typedef void (*callback_function)(int, int);
    
    extern "C" __declspec(dllexport) void SetCallback(callback_function aCallback);
    extern "C" __declspec(dllexport) void GetData();
    
    callback_function gCBF;
    
    __declspec(dllexport) void SetCallback(callback_function aCallback)
    {
        gCBF = aCallback;
    }
    
    __declspec(dllexport) void GetData()
    {
        gCBF(1, 2);
    }
    

    最佳答案

    您必须使用

    IntPtr Marshal.GetFunctionPointerForDelegate(Delegate d)
    

    方法。

    您将SetCallback()与System.Delegate用作参数使用是错误的。

    做了
    SetCallback(Marshal.GetFunctionPointerForDelegate(lTD));
    

    并重新声明SetCallback为
    /// StdCall is crucial here
    [DllImport("TomDllNative.dll", CallingConvention = CallingConvention.StdCall)]
    public static extern void SetCallback(IntPtr aCallback);
    

    关于C#C++ Interop回调,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/10841081/

    10-10 18:34
    查看更多