C#调用c语言dll,并且传入byte数组或字符串,简单实例

前言

在C#中调用dll,可能会出现程序一开始可以运行,但过一会儿后出现内存错误——尝试读取或写入受保护的内存。这通常指示其他内存已损坏。
这是由于C#的托管内存机制,而C语言中是非托管内存。如果参数传入dll后,C#提前回收了内存或者移动了数据,将会出现错误。
解决方法是,在C#传入dll参数之前,将托管内存中的数据移动到非托管内存中,然后传入非托管内存的地址。(同理我们需要在dll中函数执行完后,手动释放非托管内存)、

静态路径调用dll

使用DllImport即可

const string zlg1939Dllpath = "C:\\projects\\自动测试\\zlgcanj1939\\Debug\\zlgcanj1939.dll";
[DllImport(zlg1939Dllpath, CallingConvention = CallingConvention.Cdecl)]
public static extern uint zlgcanInit(IntPtr dllDirectory, uint baurdrate);

[DllImport(zlg1939Dllpath, CallingConvention = CallingConvention.Cdecl)]
public static extern int zlgcanSendOneMessage(uint id, IntPtr data, byte datanum);

参数传入

核心思想是,使用Marshal类,开辟非托管的内存空间,然后向dll传入指针。
下面例举的C语言函数原型为:

int zlgcanInit(char* dllDirectory, uint32_t baurdrate, uint32_t device_index, uint32_t can_index);
int zlgcanSendOneMessage(uint32_t id, uint8_t* data, uint8_t datanum);

字符串

// 参数声明使用 IntPtr dllDirectory
// public static extern uint zlgcanInit(IntPtr dllDirectory, uint baurdrate);
// 参数传入使用 Marshal.StringToHGlobalAnsi(zlgwrapDllpath)
zlgcanInit(Marshal.StringToHGlobalAnsi(zlgwrapDllpath), 250000);

简单类型数组(例如byte数组)

// 参数声明使用 IntPtr data
// public static extern int zlgcanSendOneMessage(uint id, IntPtr data, byte datanum);
// 指向非托管内存的指针
IntPtr dataptr = Marshal.AllocHGlobal(8 * sizeof(byte));
// 托管内存中的数组
byte[] data = { 0, 0, 0, 4, 5, 0, 0, 0 };
// 内存复制
Marshal.Copy(data, 0, dataptr, 8);
// 调用
zlgcanSendOneMessage(0xcf00400, dataptr, 8);

释放内存

Marshal.FreeHGlobal(IntPtr);

来源链接:https://www.cnblogs.com/209jkjkjk/p/18619821

© 版权声明
THE END
支持一下吧
点赞15 分享
评论 抢沙发
头像
请文明发言!
提交
头像

昵称

取消
昵称表情代码快捷回复

    暂无评论内容