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);
分类:
笔记
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 上周热点回顾(2.17-2.23)
· 如何使用 Uni-app 实现视频聊天(源码,支持安卓、iOS)
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章