平台调用P-INVOKE高级篇(一)--(封送含有二维数组的结构体)
来源:互联网 发布:admaster数据分析岗 编辑:程序博客网 时间:2024/05/17 03:06
对于结构体二维数组,看似简单,其实很复杂。很多人往往不知从何下手,在托管和非托管代码之间总是不能正确传递值。先用一个例子:
struct Lable1 {
BYTELabFilterChan0[4][256];
BYTELabFilterChan1[4][256];
}
这是曾经有人这样在C#进行定义的:
第一个:
[StructLayout(LayoutKind.Sequential)]
public class Label1 {
public byte[,]LabFilterChan0 = new byte[4, 256];
public byte[,]LabFilterChan1 = new byte[4, 256];
}
第二个:
public struct Label1{
byte[,]LabFilterChan0 = newbyte[4,256];
byte[,]LabFilterChan1 = new byte[4,256];
}
第三个:
public struct Label1{
byte[4,256]LabFilterChan0 ;
byte[4,256]LabFilterChan1 ;
}
咋一看,好像没什么问题!大家可以仔细看看,其实都有问题:
对于非托管和托管的结构体对应,关键就是两点:
1、两边的结构体大小要一致。
2、字节顺序要一致!
3、字符集。
其实第二点主要针对嵌套联合体来说的,没有嵌套联合体,一般按顺序字节方式即可:[StructLayout(LayoutKind.Sequential)]。对应嵌套联合体的结构体,将在下一篇进行讲解。 字符集比较好理解,就是Ansi和Unicode两种,即1个和2个字节。由于这个结构体没有包含字符串成员变量,所以,我们这里重点关注第一点!
对于简单类型的成员变量,如byte、short、int、float等,很容易跟C#的类型对应,MSDN专门有这个对应表,我这里不再重述。
回到这个例子,上面的三种转换错在哪里:
第一个:语法正确,内存空间8,而C++是1024!
第二个、第三个:C#语法就不允许,大家可以测试,看看报的什么语法错误,加深印象!
那么,正确做法是怎样呢?
第一种:拆分,也是最简单办法:
[StructLayout(LayoutKind.Sequential)]
public structByteStru {
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
public byte[]a;
};
[StructLayout(LayoutKind.Sequential)]
public structLabel1 {
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
publicByteStru[] LabFilterChan0 ;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public ByteStru[] LabFilterChan1 ;
};
第二种:合并,这个比较复杂:
[StructLayout(LayoutKind.Sequential)]
public structLabel1 {
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1024)]
publicbyte[] LabFilterChan0 ;
[MarshalAs(UnmanagedType.ByValArray,SizeConst = 1024)]
publicbyte[] LabFilterChan1 ;
};
这种办法,就把原来的二维数组,全部转为一个byte的一维数组,需要在使用做比较复杂处理:
public static byte[] MashalSimpleTwoArrayToBytes<T>(T[][] arr) {
introw = arr.GetLength(0);
intcol = arr.GetLength(1);
inttypeSize=Marshal.SizeOf(typeof(T));
inttotalLength=row*col*typeSize;
//开辟一个Byte 数组
byte[]allBuffuer = newbyte[totalLength];
intstartIndex = 0;
//然后依次把arr的数据拷贝到allBuffuer
for(int i = 0; i < row; i++)
{
arr[i].CopyTo(allBuffuer, startIndex);
startIndex+= typeSize * col;
}
returnallBuffuer;
}
- 平台调用P-INVOKE高级篇(一)--(封送含有二维数组的结构体)
- 平台调用P-INVOKE高级篇(一)--(封送含有二维数组的结构体)
- 平台调用P-INVOKE高级篇(一)--(封送含有二维数组的结构体)
- C#调用C++ 平台调用P/Invoke 结构体--含有内置数据类型的一维、二维数组、字符串指针【六】
- 平台调用P-INVOKE(三)--(封送结构体)
- 平台调用P-INVOKE(三)--(封送结构体)
- 平台调用P-INVOKE(三)--(封送结构体)
- 平台调用P-INVOKE(二)--(封送字符串)
- 平台调用P-INVOKE(二)--(封送字符串)
- 平台调用P-INVOKE(二)--(封送字符串)
- 平台调用P-INVOKE(一)--(基础篇)
- 平台调用P-INVOKE(一)--(基础篇)
- 平台调用P-INVOKE(一)--(基础篇)
- .net 互操作之p/invoke- 数据封送(嵌套结构体,类,数组)(5)
- C#调用C++ 平台调用P/Invoke 结构体--输入输出参数、返回值、返出值、结构体数组作为参数【五】
- P/Invoke的参数封送
- P/Invoke (平台调用)
- P/Invoke平台调用
- spring的配置文件中bean的注入方式
- Tomcat Manager配置
- Maven实战之antrun插件
- <context-param>的作用
- IPHONE JSON 一个例子
- 平台调用P-INVOKE高级篇(一)--(封送含有二维数组的结构体)
- 云计算要重视IT变化和经验积累
- XAMPP的安装常见问题
- 数据库的连接数
- Linux sed命令
- Cannot refer to a non-final variable anim inside an inner class defined in a different method
- 操作SQL数据库常用语句
- ORACLE判断 BLOB类型长度
- C#编写的windows计算器-源代码