C#中使用DLL文件

首先,咱们须要在C++程序中导出DLL文件。我使用的是Visual Studio开发,把项目"属性"中的“配置类型”改成"动态库dll",而后添加以下导出代码:ide

extern "C" __declspec(dllexport) void AS3911FindTag(Tag tags[], int &tagNum, int slot);//find tags
extern "C" __declspec(dllexport) bool GetTagInformation(Tag& tag);//get tag information
extern "C" __declspec(dllexport) int usbDeviceAttached(int waitTime);//initialize usb connect

而后运行程序,能够找到生成的DLL文件。在C#项目中使用,把DLL文件和生成的exe文件放在一块儿便可,而后C#中添加头部引用:函数

using System.Runtime.InteropServices;

类中声明:工具

[DllImport("AS3911Test.dll", CallingConvention = CallingConvention.Cdecl)] public static extern void AS3911FindTag(IntPtr tags, ref int tagNum, int slot); [DllImport("AS3911Test.dll", CallingConvention = CallingConvention.Cdecl)] public static extern bool GetTagInformation(ref Tag tag);
[DllImport(
"AS3911Test.dll", CallingConvention = CallingConvention.Cdecl)] public static extern int usbDeviceAttached(int waitTime);

声明后,能够直接使用这些方法了。不过要注意一点,C#和C++的交互,最麻烦的是数据类型的转换。我这里在参数中使用了Tag这个结构体,在C++中以下:ui

struct Tag { char id[20]; char dsfid[4]; char afi[4]; unsigned int blockNum; unsigned int bytesPerBlock; char info[1024]; };

在C#中对应的声明以下:spa

public struct Tag { /// char[]
[System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst = 20)] public string id; /// char[]
[System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst = 4)] public string dsfid; /// char[]
[System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst = 4)] public string afi; /// unsigned int
public uint blockNum; /// unsigned int
public uint bytesPerBlock; /// char[]
[System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst = 1024)] public string info; }

注意C#中参数部分的ref,至关于C++中指针。涉及到数据类型对应转换时,能够借助CLRInsideOut这个工具。下面以AS3911FindTag(IntPtr tags, ref int tagNum, int slot)这个函数为例,看看如何使用。指针

static void FindTag() { ComInit(); usbDeviceAttached(500); ISO15693Init(); int num = 0; int size = Marshal.SizeOf(typeof(Tag)) * Max_Tag_Num; IntPtr pBuff = Marshal.AllocHGlobal(size); Tag[] mytag = new Tag[Max_Tag_Num]; AS3911FindTag(pBuff, ref num, 16); for (int i = 0; i < num; i++) { IntPtr p = new IntPtr(pBuff.ToInt64() + Marshal.SizeOf(typeof(Tag)) * i); mytag[i] = (Tag)Marshal.PtrToStructure(p, typeof(Tag)); Console.WriteLine(mytag[i].id); } Marshal.FreeHGlobal(pBuff); ISO15693DeInit(); usbDeviceDeAttached(); ComDeInit(); }

直接看到AS3911FindTag(pBuff, ref num, 16)这段代码,这里的pBuff是C#中的引用,而后用Marshal.AllocHGlobal(size)分配了一块内存,传入函数的是一块内存的引用。第二个参数比较简单,表示经过该函数给num赋值。AS3911FindTag这个函数运行完后,pBuff所指向的内存块会被赋值,咱们下面就试着取出数据。咱们使用告终构体Tag并声明了大小,因此能够从这里着手解决问题。看到for循环中第二行代码,这里的p表示从何处读取数据,最后作类型转换可。Marshal.PtrToStructure这个函数能够将数据从非托管内存块封送到新分配的指定类型的托管对象,这里从DLL中的非托管内存封送到当前C#托管内存。最后,用Marshal.FreeHGlobal(pBuff)释放内存。code

相关文章
相关标签/搜索