• 【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:
    {0}
    ", stringA);
            Console.WriteLine("Reversed:
    {0}", stringB);
            //释放为非托管 ANSI 字符串和非托管内存块分配的内存
            Marshal.FreeHGlobal(dptr);
            Marshal.FreeHGlobal(sptr);
        }
    }
    
    //output:
    //
    // Original:
    // I seem to be turned around!
    //
    // Reversed:
    // !dnuora denrut eb ot mees I
    /*******相与枕藉乎舟中,不知东方之既白*******/
  • 相关阅读:
    增强for循环赋值并且向list集合里添加元素,每个元素都一样
    《《《Spring 视频学习笔记
    xml中的<where><if>模糊查询
    《《《layui入门笔记
    《《《Vue element学习笔记
    《《《Spring Boot视频学习笔记
    intellij idea设置打开多个文件显示在多行tab上
    postMan安装完成,打开提示找不到,或者报错 可能原因
    Intellij IDEA debug模式下项目启动慢/无法启动的事件解决过程记录
    idea代码注释
  • 原文地址:https://www.cnblogs.com/Mars-0603/p/14837414.html
Copyright © 2020-2023  润新知