昨天的贴没人给了!今天再开个讨论讨论!解决的问题:复制数组在内存中的数据到自定义结构中。
类似功能:
在C++中
原型:extern void *memcpy(void *dest, void *src, unsigned int count);
功能:由src所指内存区域复制count个字节到dest所指内存区域。 昨天有朋友回帖说在c#中Marshal.Copy可以实现类似功能。自己查了下帮助,觉得应该是可以的,但使用上有点小问题。
原型:Marshal.Copy (Byte[], Int32, IntPtr, Int32)
功能:将一维的托管 8 位无符号整数数组中的数据复制到非托管内存指针。 //结构
struct retu
{
public byte a;//数据头
public byte b;//下位机地址
public byte c;//命令
public char d;//状态
public float e;//力
public float f;//电压
public float g;//电流
public float h;//运动时间
public byte i;//数据长度
public byte Verify;//校验
public byte j;//数据尾
}
//数组
Byte[] mbyte = new Byte[28]; //使用方法
Marshal.Copy(mbyte, 0, &ret, 28);
异常,说我有些参数无效。应该是&ret的问题。这个参数需要的是IntPtr类型(要复制到的内存指针)。
请问,怎么得出这个结构的指针?
强制类型转换肯定不行。那么这个方法怎么用到这个问题上呢?
类似功能:
在C++中
原型:extern void *memcpy(void *dest, void *src, unsigned int count);
功能:由src所指内存区域复制count个字节到dest所指内存区域。 昨天有朋友回帖说在c#中Marshal.Copy可以实现类似功能。自己查了下帮助,觉得应该是可以的,但使用上有点小问题。
原型:Marshal.Copy (Byte[], Int32, IntPtr, Int32)
功能:将一维的托管 8 位无符号整数数组中的数据复制到非托管内存指针。 //结构
struct retu
{
public byte a;//数据头
public byte b;//下位机地址
public byte c;//命令
public char d;//状态
public float e;//力
public float f;//电压
public float g;//电流
public float h;//运动时间
public byte i;//数据长度
public byte Verify;//校验
public byte j;//数据尾
}
//数组
Byte[] mbyte = new Byte[28]; //使用方法
Marshal.Copy(mbyte, 0, &ret, 28);
异常,说我有些参数无效。应该是&ret的问题。这个参数需要的是IntPtr类型(要复制到的内存指针)。
请问,怎么得出这个结构的指针?
强制类型转换肯定不行。那么这个方法怎么用到这个问题上呢?
解决方案 »
- 为什么我写照网上写的设置文件夹权限的代码没有效果?
- DataGridView合计行,最后一行可能出现被遮住的情况 如何解决!谢谢
- JS 小问题
- 求高人做一个“留言板系统”
- 怎样实现全推数据?
- 多文档(MDI)开发,如何让子窗口一打开就已经最大化了
- DataTable 与 DataAdapter.Update的问题
- 如何实现完了这个后再向下执行呀,那位指导一下呀。谢了。
- 关于日期型变量的问题,急急急!!!!
- 谢谢上次各位高手的踊跃发言 ,散分 + 问题深入 !!! 欢迎踊跃发言!!!
- 你心目中win和web哪個簡單,最好說明理由,有理由給分.看一下我寫的內容先。
- 先后建两个窗口,但从构造函数的得到的变量内容会被同时至更新 为什么呢?难道站指针?
try
{
Marshal.Copy(mbyte, 0, AddrOfPinnedObject, 28);
}
finally
{
retPinned.Free();
}
c#中如何解决类似问题?使用指针可以么If you use Marshal.PtrToStructure(), then you don't need to Marshal.Copy().
If you do want to Marshal.Copy(), thenThe IntPtr can be obtained by pinning the memory (remember the managed memory could be moved by the CLR): GCHandle gch = GCHandle.Alloc(mbyte, GCHandleType.Pinned);
IntPtr ptr = gch.AddrOfPinnedObject();
// Marshal.Copy here
gch.Free();
改成
GCHandle retPinned = GCHandle.Alloc(ret, GCHandleType.Pinned);
...
跟一楼说的同一个东西,不过GCHandle gch = GCHandle.Alloc(mbyte, GCHandleType.Pinned);
黑体部分是不是该改成ret。应给是个结构吧!
static retu GetRetu( byte[] mbyte )
{
if (Marshal.SizeOf(typeof(retu)) == mbyte.Length) // <-- check their sizes do agree.
{
GCHandle gch = GCHandle.Alloc(mbyte, GCHandleType.Pinned);
retu r = (retu)Marshal.PtrToStructure(gch.AddrOfPinnedObject(), typeof(retu));
gch.Free(); return r;
}
else
{
throw new Exception( "no luck, you need to check the manual for the retu struct" );
}
}
我的数组接回来里面只有11个元素:serialPort1.Read(mbyte5, 0, 11);
用16进制表示就是AA F1 89 1 43 81 26 80 3F 5A C0 黑体部分依次是状态,力,电压,电流,时间 我的结构定义:
struct retu
{
public byte a;//数据头
public byte b;//下位机地址
public byte c;//命令
public char d;//状态
public float e;//力
public float f;//电压
public float g;//电流
public float h;//运动时间
public byte i;//数据长度
public byte Verify;//校验
public byte j;//数据尾
} 所以算下来Marshal.SizeOf(typeof(retu))=28,mbyte.Length==11,这样不可能相等!
你好!谢谢你提供的解决方法,但是还有个问题,我把结构修改了一下:
struct retu
{
public byte a;//数据头1
public byte b;//下位机地址
public byte c;//命令
public byte d;//状态1
public float e;//力4
public float f;//电压
public float g;//电流
public float h;//运动时间
public byte i;//数据长度
public byte Verify;//校验
public byte j;//数据尾
}
我数了一下,应该是23个字节(float 占4个byte 占1个),但是(Marshal.SizeOf(typeof(retu))却等译24.怎么回事?That is because of memory alignment. When data are aligned (say in 4 bytes boundary), data access is fast.In mose cases, you should leave the alignment to its default value. But in some cases, (like network communication), we like data be packed one by one without alignment, in such case we can specify the packing of the structure by saying "Pack=1" (I already mentioned it in one of your post).[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct retu
{
...You must first make sure about the layout of communication, otherwise you are going nowhere.
public struct retu
{
...
You must first make sure about the layout of communication, otherwise you are going nowhere.
===========================================
我英语不好,看得似懂非懂的。如果[StructLayout(LayoutKind.Sequential, Pack=1)] 会提示“上下文中没有Pack定义”
我现在从串口接收到一组返回值存放在数组中:
Byte[] mbyte = new Byte[23];
serialPort.Read(mbyte, 0, 23);
mbyte中的内容是(16进制表示):
AA F1 89 1 0 0 0 0 0 0 0 0 0 0 0 0 3F 31 EB 85 13 A0 FF 请问使用什么方法可以使mbyte和retu对应起来,在程序中直接使用retu.e得出力,retu.f得出电压及其他数据。 怎么实现?
还是这段:
using System.Runtime.InteropServices;//...[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct retu
{
//...
}static retu GetRetu(byte[] mbyte)
{
if (Marshal.SizeOf(typeof(retu)) == mbyte.Length) //<-- check their sizes do agree.
{
GCHandle gch = GCHandle.Alloc(mbyte, GCHandleType.Pinned);
retu r = (retu)Marshal.PtrToStructure(gch.AddrOfPinnedObject(), typeof(retu));
gch.Free(); return r;
}
else
{
throw new Exception("no luck, you need to check the manual for the retu struct");
}
}