C# Marshal类基本概念和入门实例讲解
C# Marshal类是与另一个通信的进程交互的强大工具,该进程可以在同一台计算机或网络上运行。本文旨在介绍Marshal类的基本概念和学习Marshal类的入门实例。
什么是Marshal类
Marshal类是在.NET Framework中提供的一个强大的、可靠的机制,用于在C#应用程序和非托管代码(如Windows API、COM组件、动态链接库等)之间进行交互。Marshal类提供了一组方法,用于在托管代码中使用非托管代码(例如,为了访问Windows注册表信息,我们需要使用由Windows API(非托管代码)提供的功能)。
Marshal类的优点
Marshal类具有以下几个优点:
提供了丰富的互操作性Marshal类提供了一组方法,用于在托管代码中使用非托管代码。这些方法使得应用程序可以与其他非托管代码、操作系统和硬件组件进行通信。
具有更高效的内部工具Marshal类可以更高效的内部处理与非托管代码的通信,并确保如何正确地与非托管代码协作。Marshal类也可以通过向非托管代码传递指针来传递数据。
Marshal类的常用方法和示例
Marshal.PtrToStringAnsi
Marshal.PtrToStringAnsi方法将指定内存地址中的零结尾Ansi字符集字符串转换为此字符串。
下面是使用该方法转换字符串的示例代码:
public class Program{ [DllImport("user32.dll")] public static extern int MessageBox(IntPtr hWnd, string text, string caption, int type); [DllImport("Kernel32.dll")] public static extern IntPtr LoadLibrary(string path); [DllImport("Kernel32.dll")] public static extern IntPtr GetProcAddress(IntPtr lib, string funcName); [DllImport("Kernel32.dll")] public static extern bool FreeLibrary(IntPtr lib); public static void Main(string[] args) { string libName = @"C:\windows\system32\user32.dll"; IntPtr lib = LoadLibrary(libName); if(lib != IntPtr.Zero) { IntPtr function = GetProcAddress(lib, "MessageBoxA"); if (function != IntPtr.Zero) { Marshal.GetDelegateForFunctionPointer(function, typeof(MessageBoxDelegate)); } } else { Console.WriteLine("Failed to Load Library"); } } private delegate int MessageBoxDelegate(IntPtr hWnd, string text, string caption, int type);}该代码加载user32.dll库并获取API函数MessageBoxA。函数原型与系统定义不同,因为返回类型可以是int,而不是一个布尔值。为此,可以使用Marshal.GetDelegateForFunctionPointer函数,用委托类型替代IntPtr类型。
Marshal.AllocHGlobal
Marshal.AllocHGlobal 方法分配指定字节数的内存块,并返回一个表示该块的指针。
下面是使用该方法初始化内存块的示例代码:
double[] test = new double[] { 1, 2, 3, 4, 5 };IntPtr pDoubleArray = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(double)) * test.Length);for (int i = 0; i < test.Length; i++){ Marshal.Copy(BitConverter.GetBytes(test[i]), 0, pDoubleArray + i * Marshal.SizeOf(typeof(double)), Marshal.SizeOf(typeof(double)));}该代码创建了一个包含五个双精度浮点数的数组,分配了足够大的内存以包含整个数组,并使用Marshal.Copy函数将数组元素复制到内存块。
总结
在本文中,我们学习了Marshal类的基本概念。Marhal类使得C#应用程序和非托管代码之间的交互更加简单、可靠和高效。我们还看了两个使用Marshal类的示例。Marshal.PtrToStringAnsi方法用于将指定内存地址中的零结尾Ansi字符集字符串转换为此字符串,而Marshal.AllocHGlobal方法用于分配指定字节数的内存块。