您的位置:首页 > 其它

平台调用P-INVOKE(三)--(封送结构体)

2014-05-13 15:39 288 查看
对于结构体二维数组,看似简单,其实很复杂。很多人往往不知从何下手,在托管和非托管代码之间总是不能正确传递值。先用一个例子:

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;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: