文章目录
- 学习来源:MSDN官方文档
- 一、Marshal是什么?
- 1、英文释义:
- 2、在MSDN中的定义:
- 3、通俗理解:
- 二、Marshal怎么用?【主要以一些实例来了解】
- 1、Marshal下的方法_部分截图【C#源码】:
- 2、一些示例
- 1)数组(Int64类型)写到非托管内存并读回到托管内存
- 2)数组(double类型)写到非托管内存并读回到托管内存【有疑问!】
- 3)WriteIntPtr()+ReadIntPtr()
- 4)Fields:SystemDefaultCharSize和SystemMaxDBCSCharSize
学习来源:MSDN官方文档
https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.marshal?view=net-7.0
一、Marshal是什么?
1、英文释义:
2、在MSDN中的定义:
即: 提供用于分配非托管内存、复制非托管内存块和将托管类型转换为非托管类型的方法集合,以及与非托管代码交互时使用的其他杂项方法。
3、通俗理解:
Marshal是一个方法集合,主要应用在C#和非托管代码交互时,主要有如下方法:
- 分配非托管内存
- 复制非托管内存块
- 将托管类型转换为非托管类型
- 其他方法(与非托管代码交互时)
二、Marshal怎么用?【主要以一些实例来了解】
1、Marshal下的方法_部分截图【C#源码】:
2、一些示例
1)数组(Int64类型)写到非托管内存并读回到托管内存
using System;
using System.Runtime.InteropServices;
class Example
{
static void Main()
{
//【01】Test1_数组写到非托管内存并读回到托管内存
// Create a managed array.
Int64[] managedArray = { 1, 2, 3, 4 };
// Initialize unmanaged memory to hold the array.
int size = Marshal.SizeOf(managedArray[0]) * managedArray.Length;
IntPtr pnt = Marshal.AllocHGlobal(size);
try
{
// Copy the array to unmanaged memory.
Marshal.Copy(managedArray, 0, pnt, managedArray.Length);
// Copy the unmanaged array back to another managed array.
Int64[] managedArray2 = new Int64[managedArray.Length];
Marshal.Copy(pnt, managedArray2, 0, managedArray.Length);
Console.WriteLine("The array was copied to unmanaged memory and back.");
Console.WriteLine("————————————————");
Console.WriteLine("The array of unmanaged memory:");
//【重点】因为一个Int64占用8个字节,所以下边的偏移量为i*8
for (int i = 0; i < managedArray.Length; i++)
{
Console.Write(Marshal.ReadInt64(pnt, i * 8) + " ");
}
Console.Write("\r\n");
Console.WriteLine("————————————————");
Console.WriteLine("The back array of unmanaged memory:");
for (int i = 0; i < managedArray2.Length; i++)
{
Console.Write(managedArray2[i] + " ");
}
Console.Write("\r\n");
Console.ReadLine();
}
finally
{
// Free the unmanaged memory.
Marshal.FreeHGlobal(pnt);
}
}
}
运行结果:
2)数组(double类型)写到非托管内存并读回到托管内存【有疑问!】
using System;
using System.Runtime.InteropServices;
class Example
{
static void Main()
{
//【02】Test2_数组写到非托管内存并读回到托管内存
//Create a managed array.
double[] managedArray = { 0.1, 0.2, 0.3, 0.4 };
// Initialize unmanaged memory to hold the array.
int size = Marshal.SizeOf(managedArray[0]) * managedArray.Length;
IntPtr pnt = Marshal.AllocHGlobal(size);
try
{
// Copy the array to unmanaged memory.
Marshal.Copy(managedArray, 0, pnt, managedArray.Length);
// Copy the unmanaged array back to another managed array.
double[] managedArray2 = new double[managedArray.Length];
Marshal.Copy(pnt, managedArray2, 0, managedArray.Length);
Console.WriteLine("The array was copied to unmanaged memory and back.");
Console.WriteLine("————————————————");
Console.WriteLine("The array of unmanaged memory:");
//【重点】偏移量为i * Marshal.SizeOf(managedArray[0])
for (int i = 0; i < managedArray.Length; i++)
{
//How to read double???这段代码没有实现想要的效果!
Console.Write(Marshal.ReadInt64(pnt, i * Marshal.SizeOf(managedArray[0])) + " ");
}
Console.Write("\r\n");
Console.WriteLine("————————————————");
Console.WriteLine("The back array of unmanaged memory:");
for (int i = 0; i < managedArray2.Length; i++)
{
Console.Write(managedArray2[i] + " ");
}
Console.Write("\r\n");
Console.ReadLine();
}
finally
{
// Free the unmanaged memory.
Marshal.FreeHGlobal(pnt);
}
}
}
运行结果:
3)WriteIntPtr()+ReadIntPtr()
主要过程:通过IntPtr
分配非托管内存—>写内容到非托管内存中—>从非托管内存中读取内容
Marshal.AllocHGlobal—>Marshal.WriteIntPtr()—>Marshal.ReadIntPtr()
using System;
using System.Runtime.InteropServices;
class Example
{
static void Main()
{
//【03】Test3_WriteIntPtr()+ReadIntPtr()
ReadWriteIntPtr();
Console.ReadLine();
}
static void ReadWriteIntPtr()
{
// Allocate unmanaged memory.
int elementSize = Marshal.SizeOf(typeof(IntPtr));
IntPtr unmanagedArray = Marshal.AllocHGlobal(10 * elementSize);
// Set the 10 elements of the C-style unmanagedArray
for (int i = 0; i < 10; i++)
{
Marshal.WriteIntPtr(unmanagedArray, i * elementSize, (IntPtr)(i + 1));
}
Console.WriteLine("Unmanaged memory written.");
Console.WriteLine("Reading unmanaged memory:");
// Print the 10 elements of the C-style unmanagedArray
for (int i = 0; i < 10; i++)
{
Console.WriteLine(Marshal.ReadIntPtr(unmanagedArray, i * elementSize));
}
Marshal.FreeHGlobal(unmanagedArray);
Console.WriteLine("Done. Press Enter to continue.");
Console.ReadLine();
}
}
运行结果:
4)Fields:SystemDefaultCharSize和SystemMaxDBCSCharSize
using System;
using System.Text;
using System.Runtime.InteropServices;
public struct Point
{
public Int32 x, y;
}
public sealed class App
{
static void Main()
{
// Demonstrate the use of public static fields of the Marshal class.
Console.WriteLine("SystemDefaultCharSize={0}, SystemMaxDBCSCharSize={1}",
Marshal.SystemDefaultCharSize, Marshal.SystemMaxDBCSCharSize);
// Demonstrate the use of the SizeOf method of the Marshal class.
Console.WriteLine("Number of bytes needed by a Point object: {0}",
Marshal.SizeOf(typeof(Point)));
Point p = new Point();
Console.WriteLine("Number of bytes needed by a Point object: {0}",
Marshal.SizeOf(p));
// Demonstrate how to call GlobalAlloc and
// GlobalFree using the Marshal class.
IntPtr hglobal = Marshal.AllocHGlobal(100);
Marshal.FreeHGlobal(hglobal);
Console.ReadLine();
}
}
运行结果: