C#和c++之间相互传递函数指针
在C++和C#之中都有很多callback method,可以相互调用吗,怎么传递,是我表弟的问题.
1.定义c++ dll ,导出方法
// sort.cpp : 定义 DLL 应用程序的导出函数。
//
#include "stdafx.h" #include "sort.h" #include "stdlib.h" #include "iostream" // 这是导出函数的一个示例。 typedef int (__cdecl *compare )(const void *elem1, const void *elem2 ) ; void fnsort(int arr[],int size,compare fuccsharp) { std::cout<<"\r\narray length:"<<size<<"\r\n"; std::cout << "entry fnsort in cpp\r\n"; for(int index=0; index<size;index++){ std::cout << arr[index] << " "; } qsort(arr,size,sizeof(int),fuccsharp); std::cout<<"\r\n sort end\r\n"; for(int index=0; index<size;index++){ std::cout << arr[index] << " "; } return ; }
定义导出文件sort.def
LIBRARY BTREE
EXPORTS
fnsort
现在我们期待c#能呼叫fnsort,并实现funccsharp来实现排序算法,在c#中LoadLibrary,GetProcAddress,FreeLibrary当然是必不可少的.另外定义接口实现compare ,传入两个const void *,传出int
static int SortASC(IntPtr a, IntPtr b) { int va = System.Runtime.InteropServices.Marshal.ReadInt32(a); int vb = System.Runtime.InteropServices.Marshal.ReadInt32(b); return va - vb; } static int SortDESC(IntPtr a, IntPtr b) { int va = System.Runtime.InteropServices.Marshal.ReadInt32(a); int vb = System.Runtime.InteropServices.Marshal.ReadInt32(b); return vb - va; }
同时定义委托
[UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] public delegate int INTARRAYSORT(IntPtr a, IntPtr b);
现在我们认为我们实现了int (__cdecl *compare )(const void *elem1, const void *elem2 ) ;现在没事了,一切顺利了,Marshal.GetDelegateForFunctionPointer会将一个intptr转换为一个委托 ,new delegate(pfunc)可以将一个csharp func转换为一个函数指针传绘cpp,依上例,完整实现
using System; using System.Text; using System.Runtime.InteropServices; namespace callDLL { class Program { [DllImport("kernel32")] public static extern IntPtr LoadLibrary(string lpFileName); [DllImport("Kernel32")] public static extern bool FreeLibrary(IntPtr handle); [DllImport("Kernel32")] public static extern IntPtr GetProcAddress(IntPtr handle, String funcname); [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] public delegate int INTARRAYSORT(IntPtr a, IntPtr b); [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] public delegate void CPPSORT(int[] arr, int size, INTARRAYSORT callback); static int SortASC(IntPtr a, IntPtr b) { int va = System.Runtime.InteropServices.Marshal.ReadInt32(a); int vb = System.Runtime.InteropServices.Marshal.ReadInt32(b); return va - vb; } static int SortDESC(IntPtr a, IntPtr b) { int va = System.Runtime.InteropServices.Marshal.ReadInt32(a); int vb = System.Runtime.InteropServices.Marshal.ReadInt32(b); return vb - va; } static void Main(string[] args) { IntPtr dll = LoadLibrary("sort.dll"); IntPtr func=GetProcAddress(dll, "fnsort"); CPPSORT cppsort = (CPPSORT)Marshal.GetDelegateForFunctionPointer(func, typeof(CPPSORT)); int[] arr = new int[] { 1, 7, 4 }; //回叫函数可以使用委托实现 cppsort(arr,arr.Length,new INTARRAYSORT(SortASC)); cppsort(arr, arr.Length, new INTARRAYSORT(SortDESC)); FreeLibrary(dll); Console.WriteLine("\r\nend"); Console.Read(); } } }
输出如下
array length:3
entry fnsort in cpp
1 7 4
sort end
1 4 7
array length:3
entry fnsort in cpp
1 4 7
sort end
7 4 1
end