C# C++ 互操作回调

标签 c# c++ callback interop

我最近一直在研究 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) 循环。然而,程序只是退出。我无法完全理解这种行为,我的一部分认为这是预期的,但我的一部分希望它会继续在 main 中。

我所期待的...

  1. 调用 GetData() 函数
  2. GetData函数调用回调
  3. 回调函数返回GetData
  4. GetData 返回 main()

然而这并不完全正确。

谁能解释一下发生了什么。

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

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

Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.

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);
}

最佳答案

您必须使用

将托管回调转换为 native 函数指针(C# 中的 IntPtr)
IntPtr Marshal.GetFunctionPointerForDelegate(Delegate d)

方法。

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

成功

SetCallback(Marshal.GetFunctionPointerForDelegate(lTD));

并重新声明 SetCallback 为

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

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

相关文章:

c# - 简单而精细的for循环不起作用

c# - Awesomium 安装和支持问题

c++ - 使用哪种设计模式存储由第一个函数创建的指针,该指针将在以后使用?

PHP array_filter,如何在回调中获取key?

c# - 使用 C# 验证小费计算器中的数据

c# - 从文件中获取文本 C#

c++ - 在虚函数中使用子类类型参数

c++ - 使用类来维护几个常量变量是个好主意吗

android - Firebase API 和 Android 的 Activity 生命周期

php - JavaScript 正则表达式 : PHP like Callback Variable