摘要:在C#与C++的互操作中,委托(delegate)和函数指针的传递是一个复杂但非常强大的功能。这可以实现从C++回调C#方法,或者在C#中调用C++函数指针的能力。无论是跨语言调用回调函数,还是在多线程、异步任务中使用委托,了解两者的传递机制都是非常重要的。本
在C#与C++的互操作中,委托(delegate)和函数指针的传递是一个复杂但非常强大的功能。这可以实现从C++回调C#方法,或者在C#中调用C++函数指针的能力。无论是跨语言调用回调函数,还是在多线程、异步任务中使用委托,了解两者的传递机制都是非常重要的。本篇文将详细讨论C++中的函数指针和C#中的委托如何跨语言传递,并通过示例代码展示其实现。
在C++中,函数指针是一种可以指向函数的指针,它可以存储函数的地址,并在需要时调用相应的函数。函数指针的定义如下:
// 定义返回类型为int,参数为两个int的函数指针int (*FuncPtr)(int, int);C#中的委托类似于C++中的函数指针,但具有更高的抽象层次。委托是对方法的引用,可以将它们传递给其他方法或作为回调使用。委托的定义如下:
// 定义一个返回类型为int,参数为两个int的委托public delegate int Operation(int x, int y);在C#中,委托可以被转换为函数指针并传递给C++,让C++调用C#中的回调方法。这种互操作可以通过DllImport和Marshal.GetfunctionPointerForDelegate实现。
• C#端:定义委托并将其传递给C++。• C++端:接受函数指针并调用它。在C++中,定义一个接受函数指针的函数:
// C++代码 (MyNativeLib.cpp)extern "C" typedef int (*callback)(int, int);extern "C" __declspec(dllexport) void RegisterCallback(Callback cb){int result = cb(10, 20); // 调用传递的函数指针printf("Callback result: %d\n", result);}在C#中,定义一个委托并将其转换为函数指针传递给C++:
using System;using System.Runtime.InteropServices;class Program{// 定义与C++函数指针匹配的委托public delegate int Callback(int x, int y);// 导入C++函数[DllImport("MyNativeLib.dll")]public static extern void RegisterCallback(IntPtr callback);// 回调函数,符合委托签名public static int MyCallback(int x, int y){Console.WriteLine($"C# Callback called with values: {x}, {y}");return x + y;}static void Main{// 创建委托实例Callback cb = new Callback(MyCallback);// 将委托转换为函数指针IntPtr cbPtr = Marshal.GetFunctionPointerForDelegate(cb);// 注册回调RegisterCallback(cbPtr);// 避免GC回收委托GC.KeepAlive(cb);}}执行结果
C# Callback called with values: 10, 20Callback result: 30• 防止GC回收:在C#中,委托被当作托管对象,如果没有明确的引用,GC(垃圾回收器)可能会回收该对象,从而导致C++调用时访问非法内存。为此,必须通过GC.KeepAlive确保委托不被回收。• 函数签名匹配:C#中的委托签名必须与C++函数指针的签名完全一致,包括参数类型和返回类型,否则会出现运行时错误。C++中的函数指针也可以传递给C#,在C#中转换为委托并调用。这通常用于C++库提供回调函数,而C#端需要处理这些回调。
• C++端:提供函数指针。• C#端:将函数指针转换为委托并调用。在C++中,定义一个返回函数指针的函数:
// C++代码 (MyNativeLib.cpp)extern "C" int Add(int x, int y){return x + y;}extern "C" __declspec(dllexport) int (*GetFunctionPointer)(int, int){return &Add; // 返回Add函数的指针}在C#中,接收C++返回的函数指针并将其转换为委托:
using System;using System.Runtime.InteropServices;class Program{// 定义与C++函数指针匹配的委托public delegate int FunctionPointer(int x, int y);// 导入C++函数[DllImport("MyNativeLib.dll")]public static extern IntPtr GetFunctionPointer;static void Main{// 获取函数指针IntPtr ptr = GetFunctionPointer;// 将函数指针转换为委托FunctionPointer func = (FunctionPointer)Marshal.GetDelegateForFunctionPointer(ptr, typeof(FunctionPointer));// 调用函数int result = func(5, 7);Console.WriteLine($"Result from C++ function: {result}");}}执行结果
在C#与C++的互操作中,委托和函数指针的传递为跨语言调用提供了强大的灵活性。通过委托,C#可以将方法传递给C++进行回调,C++也可以将函数指针传递给C#,并在C#中调用。这种机制在回调、事件处理、异步任务等场景中非常实用。
如果本文对你有帮助,我将非常荣幸。
如果你对本文有其他的看法,欢迎留言交流。
如果你喜欢我的文章,谢谢三连,点赞,关注,转发吧!!!
来源:小黄科技每日一讲