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方法用于分配指定字节数的内存块。

营销型网站