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

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++中如下:

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

在C#中对应的声明如下:

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

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

static void FindTag()
{
ComInit();
usbDeviceAttached();
ISO15693Init(); int num = ;
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, ); for (int i = ; 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)释放内存。

最新文章

  1. 3. SVM分类器求解(1)——Lagrange duality
  2. PHP curl 函数
  3. 开启Win7系统管理员Administrator账户
  4. Tomcat 内存溢出对应解决方式
  5. C#基础知识系列三(类和结构体、String和StringBuilder、equals和==)
  6. 转:Google全程面试题目(未完成)
  7. linux之开发板与宿主机通信--ftp使用
  8. GNU :6.47 Function Names as Strings
  9. C#中属性简写原理
  10. JQuery Kendo UI使用技巧总结
  11. [转] react-native 之布局篇
  12. TableView数据源方法的执行顺序
  13. [转]IOS 学习笔记(8) 滚动视图(UIScrollView)的使用方法
  14. Quick Cocos2dx Action相关
  15. 使用WinDbg内核调试
  16. TypeScript 上手教程
  17. as 报错
  18. webservice的两种调用方式
  19. MongoDB——待整理
  20. TaxonKit - A cross-platform and Efficient NCBI Taxonomy Toolkit

热门文章

  1. 支付宝Unity
  2. solr教程,值得刚接触搜索开发人员一看
  3. c++调用matlab生成的Dll动态连接库
  4. poj 2100 Graveyard Design
  5. *[topcoder]GUMIAndSongsDiv1
  6. MapReduce编程系列 — 2:计算平均分
  7. python学习笔记七--数据操作符的优先级
  8. 【HDOJ】2388 Playground Hideout
  9. Complete The Pattern #2
  10. HTML5学习(四)---Canvas绘图