在C#中挪用C(C++)类的DLL的时候,有时候C的接口函数包罗很多参数,而且有的时候这些参数有可能是个布局体,而且有可能是布局体指针,那么在C#到底该如何安适的挪用这样的DLL接口函数呢?本文将详细介绍如何挪用各类参数的要领。
一、挪用接口仅含普通变量int fnAdd(int num1,int num2);
那么在C#挪用这种函数最简单了,直接用函数原型即可,如下:
[DllImport("你的dll名称", EntryPoint = "fnAdd", CallingConvention = CallingConvention.Cdecl)] public static extern int fnAdd(int num1, int num2);
这样在C#的要领内可以安心的使用这个dll函数了。
二、挪用接口含普通变量的指针大家都知道C#为了安适起见,隐形的避开了指针(其实在C#完全可以使用指针的,只是为了安适),给与了引用的方法来代替指针,引用的好处就是可以和指针一样操纵参数原地点内的数据,并且这些数据在挪用函数返回时还存活,但是引用不成以想指针那样++或者--到此PC指针乱跑,引出的一系列问题,下面举例来操纵普通变量的指针,如下:
int fnAdd(int *p_n1,int *p_n2);
上文已经说了C#给与引用来取代指针,那么好了挪用接口可以这么写了:
[DllImport("你的dll名称", EntryPoint = "fnAdd", CallingConvention = CallingConvention.Cdecl)] public static extern int fnAdd(ref int num1,ref int num2);
对,就这样的简单,这样C#便可以挪用带指针的普通变量了。
三、来电稍微难度点的,挪用接口含布局体在C的头文件内包罗这样一个简单的布局体
struct mybuf { int num1; int num2; }
接口函数如下:
int fnAdd(struct mybuf mydata);
那么这样在C#该如何挪用这样的接口函数呢? 首先在C#我们要声明一个布局体,在C#布局体并没有被丢弃,只不过在使用布局体时需要注意一些细节,好比要挪用C的DLL那么最好在C#内界说的布局体前加上一些修饰符,如下:
[StructLayout(LayoutKind.Sequential)] public struct MyBuf { public int num1; public int num2; public MyBuf(int n1,int n2) { num1 = n1; num2 = n2; } } [DllImport("你的dll名称", EntryPoint = "fnAdd", CallingConvention = CallingConvention.Cdecl)] public static extern int fnAdd(MyBuf mydata);
大家可能会发明怎么这个布局体这么像个类啊,是的啊在C#中布局体确实是个特殊的类,也有结构函数,如上例子中的public MyBuf(int n1,int n2)这样的结构函数;
大家也可能看到界说布局体前我们使用StructLayout这样的布局体构造修饰符,这
个其实是很有用的,我们使用了LayoutKind.Sequential这个属性,这在dll的参数是指针的时候出格有用,因为你的C中的布局体内存是挨次构造的,因此我们在C#内也要给与挨次构造,这样通报指针的时候在C dll内就不会堕落了(也不必然)。
此外大家看到布局体的成员变量我们都用来public修饰符,当没有public只有int num1这样的语句的时候,C#默认成员变量是掩护的,那么你在C#中其他要领内界说这个布局体就不能随便的访谒改削其成员变量了(只能通过结构函数new的时候进行初始化),因此需要使用public来修饰一下成员变量。
四、继续来点难度,其实也没什么难度,就是dll接口参数包罗布局体指针nt fnAdd(struct mybuf *p_mydata),或者写成int fnAdd(void *p_mydata)
上面两个函数其实是一样的,因为C规定void类型的指针可以指向任何数据类型,只不过在c函数实体内强制为你的数据类型即可,好比:
struct mybuf*p = (structmybuf*)p_mydata;
那么在C#内该如何挪用该函数接口呢?很简单触类旁通ref嘛……
好了,代码如下: