未能封送类型,因为嵌入数组实例的长度与布局中声明的长度不匹配

出错场景

在调试海康SDK时,将struct类型的实例压入内存时,提示了改错误信息,具体代码如下:

CHCNetSDK.NET_DVR_ALARM_DEVICE_USER alarmDeviceUser = new CHCNetSDK.NET_DVR_ALARM_DEVICE_USER();
alarmDeviceUser.sPassword = Encoding.UTF8.GetBytes("a77777777");
//输入指针
IntPtr ptrInput = Marshal.AllocHGlobal(Marshal.SizeOf(alarmDeviceUser));
// 这一句话报错
Marshal.StructureToPtr(alarmDeviceUser, ptrInput, false);

错误截图如下:

错误说明

单从字面上去理解,就是长度不一样,说白了就是alarmDeviceUser和ptrInput在内存的长度不一致,导致放入内存的时候放不进去。

排除原因

一开始怎么都不知道啥原因,因为Marshal.SizeOf(alarmDeviceUser)拿到的肯定是alarmDeviceUser的长度,其他代码在海康威视中都有例子,这里面只有一句话是自己的,就是alarmDeviceUser.sPassword = Encoding.UTF8.GetBytes("a77777777")。那这句有什么问题吗。

错误说明

通过排查可以得出来alarmDeviceUser.sPassword默认的值是16,而如果使用这个赋值以后,他的长度变为了9。什么意思呢,就是单论alarmDeviceUser实例的时候,sPassword长度是9;Marshal.SizeOf(alarmDeviceUser)计算长度时,sPassword默认是16。这样子就导致了长度不同。

为了便于定位问题,我们将NET_DVR_ALARM_DEVICE_USER修改为只有sPassword,运行后可以看到nSize和sPassword大小的不同

修复问题

如何修改呢,只需要将 alarmDeviceUser.sPassword = Encoding.UTF8.GetBytes("a77777777");修改为Encoding.UTF8.GetBytes("a77777777").CopyTo(alarmDeviceUser.sPassword, 0);即可。

不过如果该byte数组为null,则不会出现这个问题,应该是在StructureToPtr时,针对null的有判断。

posted @ 2023-05-24 16:46  摧残一生  阅读(384)  评论(0编辑  收藏  举报