一、定义
MSDN:将数据从非托管内存块封送到托管对象。
重载的方法
二、实例
1、下面的示例创建一个托管结构,将其传输到非托管内存,然后使用 PtrToStructure 方法将其传输回托管内存。
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
namespace 测试interlock
{
public struct Point
{
public int x;
public int y;
}
class Example
{
static void Main()
{
// Create a point struct.
Point p;
p.x = 1;
p.y = 1;
Console.WriteLine("The value of first point is " + p.x + " and " + p.y + ".");
// 初始化一块非托管内存,大小为结构体所占的内存大小
IntPtr pnt = Marshal.AllocHGlobal(Marshal.SizeOf(p));
try
{
//将Point p的数据复制到非托管内存中去
Marshal.StructureToPtr(p, pnt, false);
// Create another point.
Point anotherP;
//将非托管内存的数据复制到新建的Point anotherP中
anotherP = (Point)Marshal.PtrToStructure(pnt, typeof(Point));
Console.WriteLine("The value of new point is " + anotherP.x + " and " + anotherP.y + ".");
Console.ReadKey();
}
finally
{
// Free the unmanaged memory.
Marshal.FreeHGlobal(pnt);
}
}
}
}
2、结构体中包含字符串
using System;
using System.Text;
using System.Runtime.InteropServices;
namespace testStructureToPtr
{
public static class define //define some constant
{
public const int MAX_LENGTH_OF_IDENTICARDID = 20; //maximum length of identicardid
public const int MAX_LENGTH_OF_NAME = 50; //maximum length of name
public const int MAX_LENGTH_OF_COUNTRY = 50; //maximum length of country
public const int MAX_LENGTH_OF_NATION = 50; //maximum length of nation
public const int MAX_LENGTH_OF_BIRTHDAY = 8; //maximum length of birthday
public const int MAX_LENGTH_OF_ADDRESS = 200; //maximum length of address
}
public struct PERSON //person structure
{
//MarshalAs:指示如何在托管代码和非托管代码之间封送数据
//UnmanagedType:指定如何将参数或字段封送到非托管内存块
[MarshalAs(UnmanagedType.ByValArray, SizeConst = define.MAX_LENGTH_OF_IDENTICARDID)]
public byte[] identicardid;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = define.MAX_LENGTH_OF_NAME)]
public byte[] name;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = define.MAX_LENGTH_OF_COUNTRY)]
public byte[] country;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = define.MAX_LENGTH_OF_NATION)]
public byte[] nation;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = define.MAX_LENGTH_OF_BIRTHDAY)]
public byte[] birthday;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = define.MAX_LENGTH_OF_ADDRESS)]
public byte[] address;
}
class testProgram
{
private static byte _fillChar = 0; //the fill character
//convert string to byte array in Ascii with length is len
public static byte[] CodeBytes(string str, int len)
{
if (string.IsNullOrEmpty(str))
{
str = string.Empty;
}
byte[] result = new byte[len];
byte[] strBytes = Encoding.Default.GetBytes(str);
//copy the array converted into result, and fill the remaining bytes with 0
for (int i = 0; i < len; i++)
result[i] = ((i < strBytes.Length) ? strBytes[i] : _fillChar);
return result;
}
//show the person information
public static void ShowPerson(PERSON person)
{
Console.WriteLine("cardid :" + Encoding.ASCII.GetString(person.identicardid));
Console.WriteLine("name :" + Encoding.ASCII.GetString(person.name));
Console.WriteLine("country :" + Encoding.ASCII.GetString(person.country));
Console.WriteLine("nation :" + Encoding.ASCII.GetString(person.nation));
Console.WriteLine("birthday :" + Encoding.ASCII.GetString(person.birthday));
Console.WriteLine("address :" + Encoding.ASCII.GetString(person.address));
}
static void Main(string[] args)
{
PERSON person;
person.identicardid = CodeBytes("123456198001011111", define.MAX_LENGTH_OF_IDENTICARDID);
person.name = CodeBytes("jackson", define.MAX_LENGTH_OF_NAME);
person.country = CodeBytes("China", define.MAX_LENGTH_OF_COUNTRY);
person.nation = CodeBytes("HanZu", define.MAX_LENGTH_OF_NATION);
person.birthday = CodeBytes("19800101", define.MAX_LENGTH_OF_BIRTHDAY);
person.address = CodeBytes("Luoshan Road, Shanghai", define.MAX_LENGTH_OF_ADDRESS);
int nSizeOfPerson = Marshal.SizeOf(person);
IntPtr intPtr = Marshal.AllocHGlobal(nSizeOfPerson);
Console.WriteLine("The person infomation is as follows:");
ShowPerson(person);
try
{
//将数据从托管对象封送到非托管内存块,该内存块开始地址为intPtr
Marshal.StructureToPtr(person, intPtr, true);
//将数据从非托管内存块封送到新分配的指定类型的托管对象anotherPerson
PERSON anotherPerson = (PERSON)Marshal.PtrToStructure(intPtr, typeof(PERSON));
Console.WriteLine("The person after copied is as follows:");
ShowPerson(anotherPerson);
Console.ReadKey();
}
catch (ArgumentException)
{
throw;
}
finally
{
Marshal.FreeHGlobal(intPtr); //free tha memory
}
}
}
}
参考:
https://blog.csdn.net/livelylittlefish/article/details/2423764