【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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM