C#从入门到精通(30)—C#Marshal类用法总结

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家人工智能学习网站

前言

大家好,我是上位机马工,硕士毕业4年年入40万,目前在一家自动化公司担任软件经理,从事C#上位机软件开发8年以上!我们在C#上位机编程中,我们经常需要进行托管内存和非托管内存数据的交互,所谓托管就是内存由.NET运行时自动管理的对象,我们在C#编程中绝大多数都是涉及的托管内存,而非托管就是操作系统或其他非.NET组件直接控制的资源,常见的是调用工业相机sdk的过程中,相机厂商经常给我们返回图像数据的时候不是直接给我们返回bitmap,而是返回图像数据的地址也就是一个指针IntPtr,这个地址(指针)就是一个非托管地址,这时候就需要我们从这个非托管地址获取图像数据,所以掌握托管内存和非托管内存数据的交互是走向高级上位机软件工程师的必经之路!

1、返回类型在非托管内存中的大小

下面的代码中第一个 Marshal.SizeOf返回某个变量在非托管内存中占用的字节数量,第二个 Marshal.SizeOf返回某个类型在非托管内存中占用的字节数量

	   char a = '1';
	   int aNums = Marshal.SizeOf(a);
	   int aNums1 = Marshal.SizeOf(typeof(Int16));

2、将数据从托管对象封送到非托管内存

Marshal.AllocHGlobal方法用于从非托管内存中分配内存,从而得到该变量在非托管内存中的地址

Marshal.StructureToPtr用于将p这个Point类型的数据从托管对象封送到非托管内存,变量pnt是变量在非托管内存中的地址

        Point p = new Point();
        p.X = 1;
        p.Y = 1;
        IntPtr pnt = Marshal.AllocHGlobal(Marshal.SizeOf(p));//从非托管内存中分配内存
        try
        {
            Marshal.StructureToPtr(p, pnt, false);//将数据从托管对象封送到非托管内存
            Point anotherP; // 创建一个新的Point
            anotherP = (Point)Marshal.PtrToStructure(pnt, typeof(Point));//将数据从非托管内存封送到托管对象
            Console.WriteLine("anotherP" + anotherP.X + " and " + anotherP.Y);
        }
        finally
        {
            Marshal.FreeHGlobal(pnt);// 释放非托管内存
        }

3、将数据从非托管内存封送到托管对象

Marshal.PtrToStructure方法用于将数据从非托管内存封送到托管对象,下面的代码中该方法第一个参数是传入从非托管内存地址,第二个参数是托管对象类型,anotherP就是托管对象。

   Point p = new Point();
    p.X = 1;
    p.Y = 1;
    IntPtr pnt = Marshal.AllocHGlobal(Marshal.SizeOf(p));//从非托管内存中分配内存
    try
    {
        Marshal.StructureToPtr(p, pnt, false);//将数据从托管对象封送到非托管内存
        Point anotherP; // 创建一个新的Point
        anotherP = (Point)Marshal.PtrToStructure(pnt, typeof(Point));//将数据从非托管内存封送到托管对象
        Console.WriteLine("anotherP" + anotherP.X + " and " + anotherP.Y);
    }
    finally
    {
        Marshal.FreeHGlobal(pnt);// 释放非托管内存
    }

4、将托管数组复制到非托管内存

下面的代码中Marshal.AllocHGlobal(array.Length)方法用于从非托管内存中分配内存给字节数组;

Marshal.Copy(array, 0, ptr, array.Length)用于将托管数组的数据复制到非托管内存

  byte[] array = { 1, 2, 3, 4 };
    IntPtr ptr = Marshal.AllocHGlobal(array.Length);//从非托管内存中分配内存
    try
    {
        Marshal.Copy(array, 0, ptr, array.Length); // 将托管数据复制到非托管内存
    }
    finally
    {
        Marshal.FreeHGlobal(ptr);//释放非托管内存
    }

5、将非托管内存指针的数据复制到托管数组

下面的代码中 Marshal.Copy(ptr2, newArray, 0, newArray.Length);用于将非托管内存指针的数据复制到托管数组 ,第一个参数ptr2是非托管内存指针(地址),第二个参数newArray是托管数组,第三个参数0代表将数据复制到数组并且是从数组的第0个数据开始(总共4个数据,数组中第一个数据索引从0开始),第四个参数 newArray.Length代表复制多少元素到数组。

        byte[] array2 = { 5, 6, 7, 8 };
        IntPtr ptr2 = Marshal.AllocHGlobal(array2.Length);//从非托管内存中分配内存
        try
        {
            Marshal.Copy(array2, 0, ptr2, array2.Length); // 将托管数组复制到非托管内存指针   
            byte[] newArray = new byte[4];
            Marshal.Copy(ptr2, newArray, 0, newArray.Length);// 将非托管内存指针的数据复制到托管数组  
        }
        finally
        {
            Marshal.FreeHGlobal(ptr2);
        }
相关推荐
用余生去守护2 分钟前
python报错系列(16)--pyinstaller ????????
开发语言·python
数据小爬虫@6 分钟前
利用Python爬虫快速获取商品历史价格信息
开发语言·爬虫·python
向宇it8 分钟前
【从零开始入门unity游戏开发之——C#篇25】C#面向对象动态多态——virtual、override 和 base 关键字、抽象类和抽象方法
java·开发语言·unity·c#·游戏引擎
莫名其妙小饼干25 分钟前
网上球鞋竞拍系统|Java|SSM|VUE| 前后端分离
java·开发语言·maven·mssql
十年一梦实验室34 分钟前
【C++】sophus : sim_details.hpp 实现了矩阵函数 W、其导数,以及其逆 (十七)
开发语言·c++·线性代数·矩阵
最爱番茄味43 分钟前
Python实例之函数基础打卡篇
开发语言·python
Uu_05kkq1 小时前
【C语言1】C语言常见概念(总结复习篇)——库函数、ASCII码、转义字符
c语言·数据结构·算法
Oneforlove_twoforjob1 小时前
【Java基础面试题033】Java泛型的作用是什么?
java·开发语言
engchina2 小时前
如何在 Python 中忽略烦人的警告?
开发语言·人工智能·python
向宇it2 小时前
【从零开始入门unity游戏开发之——C#篇24】C#面向对象继承——万物之父(object)、装箱和拆箱、sealed 密封类
java·开发语言·unity·c#·游戏引擎