C# 结构体和数组转化问题

xianyunyehe2011 2012-01-29 12:15:02

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
//结构体转byte数组
public static byte[] StructToBytes(object structObj)
{
//得到结构体的大小
int size = Marshal.SizeOf(structObj);
//创建byte数组
byte[] bytes = new byte[size];
//分配结构体大小的内存空间
IntPtr structPtr = Marshal.AllocHGlobal(size);
//将结构体拷到分配好的内存空间
Marshal.StructureToPtr(structObj, structPtr, false);
//从内存空间拷到byte数组
Marshal.Copy(structPtr, bytes, 0, size);
//释放内存空间
Marshal.FreeHGlobal(structPtr);
//返回byte数组
return bytes;
}

//byte数组转结构体
public static object BytesToStruct(byte[] bytes, Type type)
{
//得到结构体的大小
int size = Marshal.SizeOf(type);
//byte数组长度小于结构体的大小
if (size > bytes.Length)
{
//返回空
return null;
}
//分配结构体大小的内存空间
IntPtr structPtr = Marshal.AllocHGlobal(size);
//将byte数组拷到分配好的内存空间
Marshal.Copy(bytes, 0, structPtr, size);
//将内存空间转换为目标结构体
object obj = Marshal.PtrToStructure(structPtr, type);
//释放内存空间
Marshal.FreeHGlobal(structPtr);
//返回结构体
return obj;
}
public Form1()
{
InitializeComponent();
}

[StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
struct TESTStruct
{
public byte length;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 6)]
public string number;
}
private void button1_Click(object sender, EventArgs e)
{
TESTStruct test = new TESTStruct();
test.number = "012345";
test.length = (byte)test.number.Length;
byte[] testBytes = StructToBytes(test);
TESTStruct objTest = new TESTStruct();
objTest = (TESTStruct)BytesToStruct(testBytes, typeof(TESTStruct));
MessageBox.Show(objTest.number);
MessageBox.Show(objTest.length.ToString());
}
}
}


上面的这段程序执行结果number显示不全,少了一位,只显示01234,找了半天不知道是啥原因,请各位帮忙,多谢多谢
...全文
253 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
蔡袅 2012-01-31
  • 打赏
  • 举报
回复
   object obj = Marshal.PtrToStructure(structPtr, type);

应该是这里从非托管对象到托管对象出了问题,非托管的字符串必须结尾有\0,而你长度是定长了,所以最后一位进入非托管环境充当了结束符,进入托管环境之后还原没了。
xianyunyehe2011 2012-01-31
  • 打赏
  • 举报
回复
还是不大明白楼上的意思,最后一位是'\0',那在这里的字符串应该是7位了,按顺序也应该是截取前六个啊,烦劳各位大侠给看看,解释一下
真相重于对错 2012-01-31
  • 打赏
  • 举报
回复
所有的哲人都是有逻辑的
没有逻辑的人是混乱的

既然不能用string 封送,为何不用byte[] 呢?
xianyunyehe2011 2012-01-31
  • 打赏
  • 举报
回复
把SizeConst改为7可以显示全,但是这个是与其它语言写的程序通信用的,结构体大小有限制,要求这个结构体第一个字段表示有效长度,第二个字段是一个6字节的字符串,总共7个字节不能变
真相重于对错 2012-01-31
  • 打赏
  • 举报
回复
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 6)]
public string number;

===》
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 7)]
public string number;
真相重于对错 2012-01-29
  • 打赏
  • 举报
回复
没仔细看程序,
提醒一下,c 里面字符串最后一位是'\0';
xianyunyehe2011 2012-01-29
  • 打赏
  • 举报
回复
自己顶一下,各位帮忙啊,谢谢了

110,567

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧