Marshal的整理分分快三计划

作者:编程技术

分分快三计划 1

 

catch (Exception ee)

正布告诉大家怎么利用 马尔斯hal 做出能够高速释放内部存款和储蓄器的运气组。

  1. [DllImport("jnalib.dll", EntryPoint = "GetVersionPtr")]  
  2. public static extern bool GetVersionPtr(ref OSINFO info);  
  3. public static extern bool GetVersionRef(ref OSINFO info);  

//将内部存款和储蓄器空间转变为对象结构体

释放内存

那便是说什么样释放内部存款和储蓄器?因为这么些申请是从未有过通过管理的,若无手动释放,那么就现身内部存款和储蓄器走漏。

        static void Main(string[] args)
        {
            for (int i = 0; i < 10000; i  )
            {
                Foo();
            }
            Console.ReadKey();
        }

        private static void Foo()
        {
            int n = 100000;//长度
            IntPtr buffer = Marshal.AllocHGlobal(sizeof(int) * n);

        }

地点的代码很快就足以看出内部存储器占用到2G,所以要求手动释放

            Marshal.FreeHGlobal(buffer);

原来的 byte 数组需求使用 1G 内部存款和储蓄器,何况速度相当的慢,而后天利用那些方式只需求7M 内存,速度迅速

分分快三计划 2

就此在急需进行大数组申请的时候,需求不停释放,就足以行使那么些措施。

即使想使用封装好的,请看下边包车型大巴大神弄好的类

参见:C# 无unsafe的非托管大数组(large unmanaged array in c# without 'unsafe' keyword) - BIT祝威 - 博客园

 

//将byte数组拷到分配好的内部存款和储蓄器空间

使用

上面选拔一个连忙申请 int 数组来告诉咱们怎么着利用。

是不是还记得 C 的提请数组?其实上面的措施和 C 的等同

            int n = 100000;//长度
            IntPtr buffer = Marshal.AllocHGlobal(sizeof(int) * n);

当时就足以应用 buffer 作为数组

下直面他的第 k 个因素校勘

            IntPtr buffer = Marshal.AllocHGlobal(sizeof(int) * n);
            int k = 2;

            IntPtr t = buffer   k * sizeof(int);
            var p = Marshal.PtrToStructure<int>(t);
            Console.WriteLine("p "   p); //196713 这时的值是不确定

            p = 2;
            Marshal.StructureToPtr(p,t,false);

            p = Marshal.PtrToStructure<int>(t);
            Console.WriteLine("p "   p);//2

            //遍历
            Console.WriteLine("遍历");
            for (int i = 0; i < 10; i  )
            {
                t = buffer   i * sizeof(int);
                Console.WriteLine(Marshal.PtrToStructure<int>(t));
            }

遍历:

            43909312
            44502144
            2
            0
            0
            24
            1357220181
            196712
            550912
            543686656

能够从上面包车型的士代码看见,主要使用的三个主意是 StructureToPtr 和 PtrToStructure ,而 StructureToPtr 正是从钦点项目写到指针,希望我们还知道什么选用指针,PtrToStructure 正是从指针指向的地点初阶读数据,读钦点项指标多寡。所以能够从 马尔斯hal 把二个等级次序应用另二个等级次序来读取,不过通常要求读取的种类都亟需是鲜明项目大小的,如 char 能够、string 无法。

反过来,StructureToPtr 是对点名指针写入内定的体系,相似也是亟需规定那么些类型的深浅,如能够写入 char 不过不得以写入 string。那正是对数组读写的主意。

那么遍历的时候什么输出一些蹊跷的值,实际上因为从没最初化,里面包车型大巴值是不鲜明的。笔者认为用那些做随机数也不易。

动用 马尔斯hal 是相比安全,因为 ms 做了成都百货上千拍卖,不过也会让程序闪退,如上边包车型地铁代码

        private static void Foo()
        {
            int n = 100000;//长度
            IntPtr buffer = Marshal.AllocHGlobal(sizeof(int) * n);

            try
            {
                var t = buffer   (n * 10) * sizeof(int);
                var p = Marshal.PtrToStructure<int>(t);
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }

            Marshal.FreeHGlobal(buffer);
        }

会现身异常 System.AccessViolationException,那一个极度是无能为力 catch 的,所以利用的时候最棒封装一下

“System.AccessViolationException”类型的未经处理的异常在 未知模块
尝试读取或写入受保护的内存。这通常指示其他内存已损坏

借使必要 catch 那么请在 app.config 增加下边包车型大巴代码

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <runtime>
    <legacyCorruptedStateExceptionsPolicy enabled="true" />
  </runtime>
</configuration>

然后在 Main 函数增添 HandleProcessCorruptedStateExceptions ,请看代码

        [HandleProcessCorruptedStateExceptions]
        static void Main(string[] args)
        {
            AppDomain.CurrentDomain.UnhandledException  = CurrentDomain_UnhandledException;

            for (int i = 0; i < 100000; i  )
            {
                try
                {
                    Foo();
                }
                catch (Exception e)
                {
                    Console.WriteLine(e);

                }
            }
            Console.WriteLine("完成");
            Console.ReadKey();
        }

那时候能够看来步入 UnhandledException ,但是爱莫能助接住,软件依然会崩溃

分分快三计划 3

 

}s; s是二个针对已部分Pen对象的援用,当你把s传给本进度中的贰个函数f时,f能够超级轻便地找到pen的实际目的,但万生龙活虎您把s传到此外三个历程时,甚至是别的风姿罗曼蒂克台机器上的过程时,这些历程就不可能找到pen的莫过于内容。马尔斯hal本领则能够把pen对象中的全体实际内容按准则放到二个缓冲中,(全部的引用或指针都要调换到实际目的卡塔 尔(阿拉伯语:قطر‎然后把缓冲中的内容送到另叁个进程,函数调用完成再用同风流洒脱措施把结果再次回到来。

近年在做 3D ,须要不断申请少年老成段大内存数组,然后就自由他,可是 C# 对于大内部存款和储蓄器不是那个时候释放,所以就存在必然的性质问题。
在搜狐见到了一个人民代表大会神采纳 马尔斯hal 做出急迅申请的气数组,于是自个儿就学他的秘诀来弄三个。本通告诉大家那些类是什么样行使

 

马尔斯hal 类提供了三个方法集,这么些办法用于分配非托管内存、复制非托管内存块、将托管类型转变为非托管类型,另外还提供了在与非托管代码人机联作时使用的别样杂项方法。

介绍

在选择 马尔斯hal 在此以前必要通晓那是怎么着,其实 马尔斯hal 正是多个提供 COM 互操作的艺术。

  1. #define JNAAPI extern "C" __declspec(dllexport) // C方式导出函数  
  2.   
  3. typedef struct      
  4. {    
  5.     int osVersion;    
  6.     int majorVersion;    
  7.     int minorVersion;    
  8.     int buildNum;    
  9.     int platFormId;    
  10.     char szVersion[128];    
  11. }OSINFO;    
  12.   
  13. // 1. 拿到版本消息(传递结构体指针)    
  14. JNAAPI bool GetVersionPtr( OSINFO *info );    
  15. // 2.收获版本新闻(传递结构体引用)    
  16. JNAAPI bool GetVersionRef(OSINFO &info);    

组织检查 OffsetOf、SizeOf

在利用的时候,先来看下原本的 C# 的大数组质量。能够看来在不停gc,质量不佳

C#代码  分分快三计划 4

}

      static void Main(string[] args)
        {
            for (int i = 0; i < 10000; i  )
            {
                Foo();
            }
            Console.ReadKey();
        }

        private static void Foo()
        {
            var foo = new byte[1000000000];
        }

  能够通过二种办法来调用:

try

实际应用

事实上在哪些地点使用?实际上因为大多时候都以应用实例化池,可是实例化池在步入游玩的时候,能够让gc不会让程序暂停,可是会在娱乐步向下少年老成关的时候,不也许急忙清理数据。所以那个时候就可以运用 马尔斯hal 抓实例化池,弹指间就足以清空。

地方的方法一时半刻不告知我们如何做,因为关乎到小卖部的选择。

自身搭建了谐和的博客 应接大家庭访谈问,里面有过多新的博客。独有在自个儿来看博客写成熟之后才会放在csdn或新浪,但是后生可畏旦发布了就不再更新

若果在博客看到有别的不懂的,款待调换,作者搭建了 dotnet 专门的职业工夫大学 应接大家参与

分分快三计划 5
本小说使用文化分享签字-非商业性利用-相似方法共享 4.0 国际许可合同举办许可。接待转发、使用、重新发布,但必得保留小说签名林德熙(富含链接: ),不得用于商业目标,基于本文改过后的创作必需以同等的承认发表。如有任何难点,请与自个儿联系。

  2. 方式二(传入IntPtr(平台通用指针))

return bytes;

Cpp代码  分分快三计划 6

public int[] GridLayer;//须求这几个栅格图层

  1. /** 
  2.  * C#接口,对于包蕴数组类型,只好传递IntPtr 
  3.  */   
  4. [DllImport("jnalib.dll", EntryPoint = "GetVersionArray")]  
  5. public static extern bool GetVersionArray(IntPtr p, int nLen);    
  6.   
  7. // 源目的参数  
  8. OSINFO[] infos = new OSINFO[2];  
  9. for (int i = 0; i < infos.Length; i )  
  10. {  
  11.     infos[i] = new OSINFO();  
  12. }  
  13.   
  14. IntPtr[] ptArr = new IntPtr[1];  
  15. ptArr[0] = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(OSINFO)) * 2); //分配包括多少个成分的数组  
  16. IntPtr pt = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(OSINFO)));   
  17. Marshal.Copy(ptArr, 0, pt, 1); //拷贝指针数组  
  18. GetVersionArray(pt, 2); //调用  
  19.   
  20. //还原成结构体数组  
  21. for (int i = 0; i < 2; i )    
  22. {  
  23.     infos[i]=(OSINFO)Marshal.PtrToStructure((IntPtr)(pt.ToInt32() i*Marshal.SizeOf(typeof(OSINFO))),typeof(OSINFO));  
  24.     Console.WriteLine("OsVersion:{0} szVersion:{1}", infos[i].osVersion, infos[i].szVersion);  
  25. }  

{

 

IUnknown AddRef、QueryInterface、Release

C#代码  分分快三计划 7

Marshal.StructureToPtr(obj, ptr, false);

  三. 复杂结构体的传递

}

Cpp代码  分分快三计划 8

{

 

}

 

//获得结构体的高低

   2. 输入参数, 给复杂结构体赋值后作为输入参数字传送入

return bytes;

   1. 输出参数,结构体作为指针传出

类别 成员

 

[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]

  一. 结构体的传递

public int[] VecLayer;//供给那八个图层。

  1. // OSINFO定义  
  2. [StructLayout(LayoutKind.Sequential)]  
  3. public struct OSINFO  
  4. {  
  5.     public int osVersion;  
  6.     public int majorVersion;  
  7.     public int minorVersion;  
  8.     public int buildNum;  
  9.     public int platFormId;  
  10.     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]  
  11.     public string szVersion;  
  12. }  

{

 

直接读取和写入 ReadByte、ReadInt16、ReadInt32、ReadInt64、ReadIntPtr、WriteByte、WriteInt16、WriteInt32、WriteInt64、WriteIntPtr

   调用方法: 马尔斯hal.StructureToPtr(stu, ptr1, true) 

byte[] bytes = new byte[size];

  1. typedef struct  
  2. {  
  3.     char name[20];  
  4.     int age;  
  5.     double scores[30];  
  6. }Student;  
  7.   
  8. // Class中带有结构体数组类型  
  9. typedef struct  
  10. {  
  11.     int number;  
  12.     Student students[50];  
  13. }Class;  
  14.   
  15. // 传入复杂结构体育项目检测试  
  16. JNAAPI int GetClass(Class *pClass,int len);  

return null;

 

高等封送管理GetManagedThunkForUnmanagedMethodPtr、GetUnmanagedThunkForManagedMethodPtr、NumParamBytes

  1. IntPtr pv = 马尔斯hal.AllocHGlobal(148); //结构体在应用时必必要分配空间(4*sizeof(int) 128)  
  2. Marshal.WriteInt32(pv,148); //向内部存款和储蓄器块里写入数值  
  3. if (GetVersionPtr(pv)) //直接以非托管内部存款和储蓄器块地址为参数  
  4. {  
  5.     Console.WriteLine("--osVersion:{0}", Marshal.ReadInt32(pv, 0));  
  6.     Console.WriteLine("--Major:{0}",Marshal.ReadInt32(pv, 4)); //移动4个字节  
  7.     Console.WriteLine("--BuildNum: "   Marshal.ReadInt32(pv, 12));  
  8.     Console.WriteLine("--szVersion: " Marshal.PtrToStringAnsi((IntPtr)(pv.ToInt32() 20)));  
  9. }  
  10. 马尔斯hal.FreeHGlobal(pv); //管理完记得释放内部存款和储蓄器  

}

  1. 方式一(传入结构体援用),在C#中,结构体是以传值格局传送,类才是以传地址方式传递,加关键字ref就可以. C端传递了三种分歧门类的参数,都足以通过援用来解决.

数码调换托管到非托管:Copy、GetComInterfaceForObject、GetIDispatchForObject、GetIUnknownForObject、StringToBST奥迪Q5、StringToCoTaskMemAnsi、StringToCoTaskMemAuto、StringToCoTaskMemUni、StringToHGlobalAnsi、StringToHGlobalAuto、StringToHGlobalUni、StructureToPtr、UnsafeAddrOfPinnedArrayElement非托管到托管:Copy、GetObjectForIUnknown、GetObjectForNativeVariant、GetObjectsForNativeVariants、GetTypedObjectForIUnknown、GetTypeForITypeInfo、PtrToStringAnsi、PtrToStringAuto、PtrToStringBST牧马人、PtrToStringUni属性:SystemDefaultCharSize、System马克斯DBCSCharSize

Cpp代码  分分快三计划 9

public int ClientArea_x;

   因为商家直接都以做C 开拓的,因客户供给要提供C#本子接口,钻探了一下C#,发现其当者披靡简洁, 在跨语言调用方面封装的很深透,提供了强压的API与之交互作用.那一点比JNA方便多了. Java与C#都只可以调用C格式导出动态库,因为C数据类型相比单黄金时代,轻松映射. 两个都以在地面端提供一套与之映射的C#/java描述接口,通过尾巴部分管理这种映射关系达到调用的指标.

struct{

Cpp代码  分分快三计划 10

IntPtr ptr = Marshal.AllocHGlobal(size);

 

public int Srv_index;

 

举例您的三个布局

C#代码  分分快三计划 11

MessageBox.Show(ee.Message);

   二.结构体数组的传递

public int y_pos;

   对于相当大的结构体指针,不能直接利用结构体类型,转造成IntPtr类型, 那个时候需求将原生类型转变为指针,并给指针赋值

//返回空

 

object obj = Marshal.PtrToStructure(structPtr, typeof(ImageDataMsg));

Cpp代码  分分快三计划 12

public struct ImageDataMsg

 

public static object BytesToStuct2(byte[] bytes, ImageDataMsg type)

 

public int ClientArea_y;

 

内部存款和储蓄器管理COM:AllocCoTaskMem、ReAllocCoTaskMem、FreeCoTaskMem、FreeBSTOdysseyWin32:AllocHGlobal、ReAllocHGlobal、FreeHGlobal两个:DestroyStructure

 

int size = Marshal.SizeOf(obj);

  1. // 接口定义   
  2. [DllImport("jnalib.dll", EntryPoint = "GetClass")]Marshal的整理分分快三计划。  
  3. public static extern int GetClass(IntPtr pv,int len);  
  4.   
  5. // 结构体定义  
  6. // Student  
  7. [StructLayout(LayoutKind.Sequential)]  
  8. public struct Student  
  9. {  
  10.     [MarshalAs(UnmanagedType.ByValTStr,SizeConst=20)]  
  11.     public string name;  
  12.     public int age;  
  13.     [MarshalAs(UnmanagedType.ByValArray, SizeConst = 30)]  
  14.     public double[] scores;  
  15. }  
  16.   
  17. // Class  
  18. [StructLayout(LayoutKind.Sequential)]  
  19. public struct Class  
  20. {  
  21.     public int number;  
  22.     [MarshalAs(UnmanagedType.ByValArray, SizeConst = 50)]Marshal的整理分分快三计划。 // 钦点数组尺寸   
  23.     public Student[] students; // 结构体数组定义  
  24. }  
  25.   
  26. // 调用复杂结构体测量检验  
  27. int size = Marshal.SizeOf(typeof(Class)) * 50;  
  28. IntPtr pBuff = 马尔斯hal.AllocHGlobal(size); // 直接分配肆19个要素的空间,比马尔斯hal.copy方便多了  
  29. GetClass(pBuff, 50);  
  30.   
  31. Class[] pClass = new Class[50];  
  32. for (int i = 0; i < 50; i )  
  33. {  
  34.     IntPtr ptr = new IntPtr(pBuff.ToInt64()   Marshal.SizeOf(typeof(Class)) * i);  
  35.     pClass[Marshal的整理分分快三计划。i] = (Class)Marshal.PtrToStructure(ptr, typeof(Class));  
  36. }  
  37. Marshal.FreeHGlobal(pBuff); // 释放内部存款和储蓄器  

//分配结构体大小的内部存款和储蓄器空间

   调用代码:

}

 

public int Scale_index;//供给的是老大比例尺的图像

  1. // 传递结构体指针  
  2. JNAAPI bool GetVersionArray(OSINFO *info,int nLen);  

[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]

public int x_pos;

马尔斯hal正是把四个协会(类卡塔尔体系化成大器晚成段内部存款和储蓄器,然后送到另两个历程(.net中Application domain)中供另叁个进程中的函数使用。

平台调用实用工具 Prelink、PrelinkAll、GetHINSTANCE

Marshal.FreeHGlobal(structPtr);

}

在RPC,Interop,COM中马尔斯hal应用超级多。

特别注意:马尔斯hal.PtrToStringAuto方法:分配托管 String,并从非托管内部存款和储蓄器中存款和储蓄的字符串向其复制第二个空字符从前的具有字符。

COM 库函数 BindToMoniker、GetActiveObject

if (size > bytes.Length)

IntPtr structPtr = Marshal.AllocHGlobal(size);

类型信息GenerateGuidForType、GenerateProgIdForType、GetTypeInfoName、GetTypeLibGuid、GetTypeLibGuidForAssembly、GetTypeLibLcid、GetTypeLibName、IsComObject、IsTypeVisibleFromCom

//使用那些艺术将byte数组转变为结构体

Marshal.Copy(ptr, bytes, 0, size);

//再次回到结构体

//这么些个地点要钦赐长度,这样就能够赢得结构体的不易长度了

错误管理COM:GetH奥迪Q3ForException、ThrowExceptionForH大切诺基Win32:GetLastWin32Error、GetExceptionCode、GetExceptionPointers两个:GetHLacrosseForLastWin32Error

//释放内部存款和储蓄器空间

{

//byte数高管度小于结构体的高低

return obj;

承载实用工具 GetThreadFromFiberCookie

int size = Marshal.SizeOf(type);

//使用这么些法子将您的结构体转变为bytes数组

public char ConvertType;

{

{

Marshal.Copy(bytes, 0, structPtr, size);

滑动可查看表格全部内容

public char DataType;

COM 实用工具 ChangeWrapperHandleStrength、CreateWrapperOfType、GetComObjectData、GetComSlotForMethodInfo、GetEndComSlot、GetMethodInfoForComSlot、GetStartComSlot、ReleaseComObject、SetComObjectData

Pen pen;

public static byte[] Struct2Bytes(ImageDataMsg obj)

Marshal.FreeHGlobal(ptr);

例1、

在七个不等的实体(四个线程或许经过以至机器、在Managed和Unmanaged之间卡塔 尔(英语:State of Qatar)进行艺术调用和参数字传送递的时候,具体的调用方法和参数的内部存款和储蓄器格式或许须要料定的转移,那个转变的进程叫做马尔斯hal。

本文由分分快三计划发布,转载请注明来源

关键词: 分分快三计划 c#开发笔记