zoukankan      html  css  js  c++  java
  • C#中使用DLL文件

    首先,我们需要在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[20];
        char dsfid[4];
        char afi[4];
        unsigned int blockNum;
        unsigned int bytesPerBlock;
        char info[1024];
    };

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

    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)释放内存。

     

  • 相关阅读:
    Sql 行转换列(列转换行), JavaScript解决思路
    c# 异步线程
    C# 读取数据库存储过程返回值 笔记
    利用UtilityLibrary.dll WeifenLuo.WinFormsUI.Docking.dll控件创建工具栏效果
    关于C#Winform线程调用窗体的使用方法以及窗体的单一显示
    通过调用API函数实现的无边框窗体的拖拽,比判断坐标更快捷
    ubuntu下安装redis
    ubuntu下安装beanstalkd
    preg_match_all 执行一个全局正则表达式匹配
    mongodb的安装和进入
  • 原文地址:https://www.cnblogs.com/shihui142857/p/3418287.html
Copyright © 2011-2022 走看看