【C#】Marshal.SizeOf 方法、Marshal.AllocHGlobal 方法、IntPtr 结构

1、Marshal.SizeOf

返回的非托管大小(以字节为单位)。

using System;
using System.Runtime.InteropServices;

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 + ".");
        //先获取p的内存大小 再分配内存
        IntPtr pnt = Marshal.AllocHGlobal(Marshal.SizeOf(p));
      

        try
        {

            //将数据从托管对象封送到非托管内存块
            //p是要封送的数据的托管对象
            //pnt是指向非托管内存块的指针
            Marshal.StructureToPtr(p, pnt, false);

            Point anotherP;
            //将数据从非托管内存块封送到托管对象
            //pnt是指向非托管内存块的指针
            //第二个参数是将数据复制到其中的对象。 这必须是格式化类的实例。
            anotherP = (Point)Marshal.PtrToStructure(pnt, typeof(Point));

            Console.WriteLine("The value of new point is " + anotherP.x + " and " + anotherP.y + ".");
        }
        finally
        {
            // Free the unmanaged memory.
            Marshal.FreeHGlobal(pnt); //释放内存
        }
    }
}

 

2、Marshal.AllocHGlobal

从进程的非托管内存中分配内存。

AllocHGlobal(Int32)  通过使用指定的字节数,从进程的非托管内存中分配内存。

AllocHGlobal(IntPtr) 通过使用指向指定字节数的指针,从进程的非托管内存中分配内存。

返回值:指向新分配的内存的指针。 必须使用 FreeHGlobal(IntPtr) 方法释放该内存。

IntPtr hglobal = Marshal.AllocHGlobal(100);
Marshal.FreeHGlobal(hglobal);

 

3、Marshal.SizeOf和sizeof的区别

https://www.cnblogs.com/jxnclyk/archive/2010/06/09/1754438.html

 

4、IntPtr 结构:用于表示指针或句柄的平台特定类型。

示例:使用托管指针来反转数组中的字符

using System;
using System.Runtime.InteropServices;

class NotTooSafeStringReverse
{
    static public void Main()
    {
        string stringA = "I seem to be turned around!";
        int copylen = stringA.Length;

        //将 Unicode 字符串作为 ANSI (单字节) 字符复制到非托管内存。返回IntPtr指向非托管字符串的开头的对象。
        IntPtr sptr = Marshal.StringToHGlobalAnsi(stringA);
        //分配与非托管字符串占用的字节数相同的字节数
        IntPtr dptr = Marshal.AllocHGlobal(copylen + 1);

        // The unsafe section where byte pointers are used.
        unsafe
        {
           //获取指向字符串的起始地址和非托管内存块的非托管指针,并将该字符串的长度小于该字符串的长度添加到 ANSI 字符串的起始地址
          //由于非托管字符串指针现在指向字符串的末尾,因此复制操作会将字符串末尾的字符复制到内存块的开头
            byte *src = (byte *)sptr.ToPointer();
            byte *dst = (byte *)dptr.ToPointer();

            if (copylen > 0)
            {
                src += copylen - 1;
                //使用循环将字符串中的每个字符复制到非托管内存块。
                while (copylen-- > 0)
                {
                    *dst++ = *src--;
                }
                *dst = 0;
            }
        }
        //将包含复制的 ANSI 字符串的非托管内存块转换为托管的Unicode String对象
        string stringB = Marshal.PtrToStringAnsi(dptr);

        Console.WriteLine("Original:\n{0}\n", stringA);
        Console.WriteLine("Reversed:\n{0}", stringB);
        //释放为非托管 ANSI 字符串和非托管内存块分配的内存
        Marshal.FreeHGlobal(dptr);
        Marshal.FreeHGlobal(sptr);
    }
}

//output:
//
// Original:
// I seem to be turned around!
//
// Reversed:
// !dnuora denrut eb ot mees I

 

posted @ 2021-06-01 15:31  不溯流光  阅读(4075)  评论(0编辑  收藏  举报