未能封送类型,因为嵌入数组实例的长度与布局中声明的长度不匹配
出错场景
在调试海康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的有判断。