Marshal 类的内存操作的一般功能

Marshal类

提供了一个方法集,这些方法用于分配非托管内存、复制非托管内存块、将托管类型转换为非托管类型,此外还提供了在与非托管代码交互时使用的其他杂项方法。

命名空间:System.Runtime.InteropServices

Marshal 类中定义的 static 方法对于处理非托管代码至关重要。此类中定义的大多数方法通常由需要在托管和非托管编程模型之间提供桥梁的开发人员使用。

例如,StringToHGlobalAnsi 方法将 ANSI 字符从指定的字符串(在托管堆中)复制到非托管堆中的缓冲区。该方法还分配大小正确的目标堆。

公共方法


方法名称


说明


AddRef


递增指定接口上的引用计数。


AllocCoTaskMem


从 COM 任务内存分配器分配指定大小的内存块。


AllocHGlobal  


使用 LocalAlloc 分配内存块。


BindToMoniker


获取由指定的名字对象标识的接口指针。


ChangeWrapperHandleStrength


在 COM 可调用包装 (CCW) 句柄包含的对象上更改它的强度。


Copy  


将数据从托管数组复制到非托管内存指针,或从非托管内存指针复制到托管数组。


CreateAggregatedObject


聚合托管对象和指定的   COM 对象。


CreateWrapperOfType


在指定类型的对象中包装指定的 COM 对象。


DestroyStructure


释放指定的非托管内存块所指向的所有子结构。


Equals


。 确定两个   Object   实例是否相等。 (从 Object   继承。)


FinalReleaseComObject


通过将提供的运行库可调用包装 (RCW) 的引用计数设置为 0,释放对 RCW 的所有引用。


FreeBSTR


使用   SysFreeString 释放 BSTR。


FreeCoTaskMem


释放由非托管 COM 任务内存分配器使用 Marshal.AllocCoTaskMem   分配的内存块。


FreeHGlobal  


释放以前使用 AllocHGlobal   从进程的非托管内存中分配的内存。


GenerateGuidForType


返回指定类型的全局唯一标识符 (GUID),或使用类型库导出程序 (TlbExp.exe) 所用的算法生成 GUID。


GenerateProgIdForType


返回指定类型的编程标识符   (ProgID)。


GetActiveObject


从运行对象表 (ROT)   获取指定对象的运行实例。


GetComInterfaceForObject


返回一个接口指针,该接口指针表示对象的指定接口。


GetComInterfaceForObjectInContext


返回一个接口指针,该指针表示对象的指定接口(如果调用方与对象在同一上下文中)。


GetComObjectData


从指定的 COM 对象获取指定键所引用的数据。


GetComSlotForMethodInfo


获取指定的 System.Reflection.MemberInfo   在向 COM 公开时的虚函数表 (VTBL) 槽。


GetDelegateForFunctionPointer


将非托管函数指针转换为委托。


GetEndComSlot


获取在向 COM 公开时某个类型的虚函数表 (VTBL) 中的最后一个槽。


GetExceptionCode


检索标识所发生异常的类型的代码。


GetExceptionForHR


。 将 HRESULT 错误代码转换为对应的 Exception   对象。


GetExceptionPointers


检索与计算机无关的异常描述以及有关异常发生时线程的状态信息。


GetFunctionPointerForDelegate


将委托转换为可从非托管代码调用的函数指针。


GetHashCode


用作特定类型的哈希函数。GetHashCode   适合在哈希算法和数据结构(如哈希表)中使用。 (从 Object   继承。)


GetHINSTANCE


返回指定模块的实例句柄   (HINSTANCE)。


GetHRForException


将指定异常转换为   HRESULT。


GetHRForLastWin32Error


返回 HRESULT,它与使用 Marshal   执行的 Win32 代码引起的最后一个错误相对应。


GetIDispatchForObject


从托管对象返回一个   IDispatch 接口。


GetIDispatchForObjectInContext


如果调用方与托管对象在同一上下文中,则从该对象返回一个 IDispatch 接口指针。


GetITypeInfoForType


从托管类型返回一个   ITypeInfo 接口。


GetIUnknownForObject


从托管对象返回一个   IUnknown 接口。


GetIUnknownForObjectInContext


如果调用方与托管对象在同一上下文中,则从该对象返回一个 IUnknown 接口。


GetLastWin32Error


返回由上一个非托管函数返回的错误代码,该函数是使用设置了 DllImportAttribute.SetLastError   标志的平台调用来调用的。


GetManagedThunkForUnmanagedMethodPtr


获取指向 thunk 的指针,该 thunk 封送从托管代码到非托管代码的调用。


GetMethodInfoForComSlot


检索指定的虚函数表   (VTBL) 槽的 MethodInfo


GetNativeVariantForObject


将对象转换为 COM   VARIANT。


GetObjectForIUnknown


返回通过指向 COM 对象的 IUnknown 接口的指针表示该对象的类型实例。


GetObjectForNativeVariant


将 COM   VARIANT 转换为对象。


GetObjectsForNativeVariants


将 COM   VARIANT 数组转换为对象数组。


GetStartComSlot


获取虚函数表   (VTBL) 中第一个包含用户定义的方法的槽。


GetThreadFromFiberCookie


将纤程 Cookie 转换为相应的 System.Threading.Thread   实例。


GetType


获取当前实例的 Type。 (从 Object   继承。)


GetTypedObjectForIUnknown


返回表示 COM 对象的指定类型的托管对象。


GetTypeForITypeInfo


将 ITypeInfo 转换为托管 Type 对象。


GetTypeInfoName


。 检索由 ITypeInfo 表示的类型的名称。


GetTypeLibGuid


。 检索类型库的库标识符 (LIBID)。


GetTypeLibGuidForAssembly


检索从指定程序集导出类型库时分配给该类型库的库标识符 (LIBID)。


GetTypeLibLcid


。 检索类型库的 LCID。


GetTypeLibName


。 检索类型库的名称。


GetTypeLibVersionForAssembly


检索将从指定程序集导出的类型库的版本号。


GetUniqueObjectForIUnknown


为给定的   IUnknown 创建唯一的运行库可调用包装 (RCW) 对象。


GetUnmanagedThunkForManagedMethodPtr


获取指向 thunk 的指针,该 thunk 封送从非托管代码到托管代码的调用。


IsComObject


指示指定对象是否表示   COM 对象。


IsTypeVisibleFromCom


指示类型对 COM 客户端是否可见。


NumParamBytes


计算在非托管内存中保存指定方法的参数所需要的字节数。


OffsetOf


返回托管类的非托管形式的字段偏移量。


Prelink


在不调用方法的情况下执行一次性方法设置任务。


PrelinkAll


对类上的所有方法执行预链接检查。


PtrToStringAnsi


分配托管 String   并向其复制所有或部分非托管 ANSI 字符串。


PtrToStringAuto


分配托管 String,并从非托管字符串向其复制指定数目的字符。


PtrToStringBSTR


分配托管 String,并向其复制存储在非托管内存中的 BSTR 字符串。


PtrToStringUni


分配托管 String,并从非托管 Unicode 字符串向其复制指定数目的字符。


PtrToStructure  


将数据从非托管内存块封送到托管对象。


QueryInterface


从 COM 对象请求指向指定接口的指针。


ReadByte


从非托管指针读取单个字节。


ReadInt16


从非托管内存中读取一个 16 位有符号整数。


ReadInt32


从非托管内存中读取一个 32 位有符号整数。


ReadInt64


从非托管内存中读取一个 64 位有符号整数。


ReadIntPtr


从非托管内存中读取处理器本机大小的整数。


ReAllocCoTaskMem


调整以前用   AllocCoTaskMem 分配的内存块的大小。


ReAllocHGlobal


调整以前用   AllocHGlobal 分配的内存块的大小。


ReferenceEquals


确定指定的 Object   实例是否是相同的实例。 (从 Object   继承。)


Release


递减指定接口上的引用计数。


ReleaseComObject


递减所提供的运行库可调用包装的引用计数。


ReleaseThreadCache


释放线程缓存。


SecureStringToBSTR


分配 BSTR 并向其复制托管 SecureString   对象的内容。


SecureStringToCoTaskMemAnsi


将托管   SecureString 对象的内容复制到从非托管   COM 任务分配器分配的内存块。


SecureStringToCoTaskMemUnicode


将托管   SecureString 对象的内容复制到从非托管   COM 任务分配器分配的内存块。


SecureStringToGlobalAllocAnsi


将托管   SecureString 中的内容复制到非托管内存,并在复制时转换为 ANSI 格式。


SecureStringToGlobalAllocUnicode


向非托管内存复制托管   SecureString 的内容。


SetComObjectData


设置由指定 COM 对象中的指定键引用的数据。


SizeOf  


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


StringToBSTR


分配 BSTR 并向其复制托管 String 的内容。


StringToCoTaskMemAnsi


将托管 String 的内容复制到从非托管 COM 任务分配器分配的内存块。


StringToCoTaskMemAuto


将托管 String 的内容复制到从非托管 COM 任务分配器分配的内存块。


StringToCoTaskMemUni


将托管 String 的内容复制到从非托管 COM 任务分配器分配的内存块。


StringToHGlobalAnsi


将托管 String 中的内容复制到非托管内存,并在复制时转换为 ANSI 格式。


StringToHGlobalAuto


向非托管内存复制托管   String 的内容,并在需要时转换为   ANSI 格式。


StringToHGlobalUni


向非托管内存复制托管   String 的内容。


StructureToPtr  


将数据从托管对象封送到非托管内存块。


ThrowExceptionForHR


用特定的失败 HRESULT 值引发异常。


ToString


返回表示当前   Object 的 String。 (从 Object   继承。)


UnsafeAddrOfPinnedArrayElement


获取指定数组中指定索引处的元素的地址。


WriteByte


将单个字节值写入到非托管内存。


WriteInt16


将 16 位有符号整数写入非托管内存。


WriteInt32


将 32 位有符号整数写入非托管内存。


WriteInt64


将 64 位有符号整数写入非托管内存。


WriteIntPtr


将一个处理器本机大小的整数值写入非托管内存。


ZeroFreeBSTR


释放 BSTR 指针,该指针是使用 SecureStringToBSTR   方法分配的。


ZeroFreeCoTaskMemAnsi


释放非托管字符串指针,该指针是使用 SecureStringToCoTaskMemAnsi   方法分配的。


ZeroFreeCoTaskMemUnicode


释放非托管字符串指针,该指针是使用 SecureStringToCoTaskMemUnicode   方法分配的。


ZeroFreeGlobalAllocAnsi


释放非托管字符串指针,该指针是使用 SecureStringToGlobalAllocAnsi   方法分配的。


ZeroFreeGlobalAllocUnicode


释放非托管字符串指针,该指针是使用 SecureStringToCoTaskMemUnicode 方法分配的。

简介

Marshal 类中有许多成员,但他们大多是公用事业援助COM代码进行互操作。

使用.NET,Visual Basic中有很大的权力,以至于处理在与 Windows 系统较低水平层次,并从外部库的非托管代码的工作。这权力是发现了三个新的工具:IntPtr的,NET的平台相关的内存地址代表性的GCHandle,从而你针和检索的管理内存堆的数据的地址; Marshal类的一站式。您的内存分配,清理,和操作的需要。
如果您决定与VB.NET直接内存操作,你需要了解的第一件事是IntPtr类型。

IntPtr 的是一个结构,它表示两个地址和处理(大多数处理 Windows 的指针的指针)。

IntPtr 的实例也依赖于平台的(或独立,取决于你的观点)。在32位系统,IntPtr 的是32位,而在64位系统 IntPtr 的是64位。这样做的好处是,你不需要更改或重新编译你的代码,或两个平台内的任何.NET Framework的公开的方式与地址和处理工作的功能。

使用 IntPtr 类型,这种功能是封送到非托管代码,仅仅作为内部地址编号,这意味着你可以通过一个 IntPtr 类型的变量的任何非托管代码的预计指针。因此,好消息是,虽然你不能在VB.NET中使用这样的: 如void * Dim MyPointer 这个工程精辟VB.NET:作为 IntPtr 的 DIM MyPointer
请注意,在Beta 1没有IntPtr类型??相反,工作指针和处理使用 Integer 类型。

IntPtr 类型有 ToInt32 方法的地址转换为一个整数,但可以将导致在64位系统的溢出异常。 IntPtr 也有 ToInt64 方法,但你必须保持跟踪的平台,如果你想要做的这些转换。StrPtr()和 VarPtr()NBSP在 VB.NET 这两个无证 VB 的6个功能变量的返回地址。相同的功能,可以在VB.NET的GCHandle类。

让我们来看看如何放到一个 IntPtr 变量的地址。您可以使用的 GCHandle 的类,它有一个 AddrOfPinnedObject 的方法返回一个变量一个IntPtr。

您必须"针"的数据,然后才可以得到这个地址。这可以防止不经意间移动数据的垃圾收集器,而你指的是原来的地址。这代码引脚一个变量,其地址显示在控制台窗口,并释放句柄:"昏暗的管理变量DIM MyString的字符串=阿德南塞缪尔? "针变量和创建"GC的处理实例昏暗的GH(MyString中,GCHandleType.Pinned)的GCHandle = GCHandle.Alloc "得到的变量的地址DIM AddrOfMyString作为IntPtr的= gh.AddrOfPinnedObject() Console.WriteLine(AddrOfMyString.ToString()) "自由的处理,并脱离"变量gh.Free()说明AllocHGlobal和AllocCoTaskMem
上的本机堆内部使用GlobalAlloc函数分配内存AllocHGlobal; AllocCoTaskMem,这是类似的,而是使用的COM内存管理器(CoTaskMemAlloc来)。这两个函数有一个参数,分配的字节数。这两个函数返回一个IntPtr,新分配的缓冲区的基地址。释放内存,您使用的FreeHGlobal或FreeCoTaskMem方法,取决于分配方法您使用。这些函数有一个参数,新分配的缓冲区的分配函数返回地址。
使用WriteByte,WriteInt16,WriteInt32,或WriteInt64方法简单的数字数据写入到一个非托管的缓冲区。每个函数作为参数的写操作的目的地址和数值你想要写。这些功能也重载以允许可选的第三个参数指示从抵消所提供的地址,它可以是有用的,如果你试图填充数组元素或结构领域的内存,例如:"分配一些内存,并获得它的地址DIM MyPointer的IntPtr = Marshal.AllocHGlobal(4) "写入到该地址的数量255Marshal.WriteInt32(MyPointer,255) "一些更多的代码(调用"例如的非托管代码) "空闲内存Marshal.FreeHGlobal(MyPointer)
您也可以使用提供的地址,而不是你自己分配的非托管代码:D??IM MyPointer作为IntPtr的新的IntPtr([插入整数地址_                从这里非托管代码)] Marshal.WriteInt32(MyPointer,255)
反过来也有可能。你可以阅读简单的数字数据,从一个IntPtr地址使用的readByte ReadInt16,ReadInt32,并ReadInt64方法:DIM MyInteger为整数= Marshal.ReadInt32(MyPointer)字符串函数
阅读和写作字符串相似,读,写简单的数字数据,有一个小的例外:你不先分配内存,然后写一个字符串。相反,在非托管内存中创建一个字符串的行为分配的空间,并返回字符串的地址。写有七个方法:StringToBSTR,StringToCoTaskMemAnsi,StringToCoTaskMemUni,StringToCoTaskMemAuto,StringToHGlobalAnsi,StringToHGlobalUni和StringToHGlobalAuto。 StringToCoTaskMemxxx功能字符串数据写入到COM分配的内存,而StringToHGlobalxxx功能写入到本地的非托管堆。结束在ANSI的函数写单字节ANSI字符串。结束在统一的函数写双字节的Unicode字符串。功能,自动结束写入ANSI或Unicode字符串,这取决于操作系统:Windows 98和ME,NT为基础的平台(Windows NT 4.0中,2000年,和XP)的Unicode字符串的ANSI字符串。 StringToBSTR写一个自动化BSTR,这是类似于使用SysAllocString函数。这些函数接受一个字符串作为输入参数,并返回一个指针,得到的字符串:DIM MyStrPointer的IntPtr = Marshal.StringToHGlobalAuto(quot;您好Worldquot;)
四个读的方法呢??PtrToStringAnsi,PtrToStringUni,PtrToStringAuto,PtrToStringBSTR??在一个给定的地址读取数据,并创建一个托管String对象,其中包含的字符的副本。 PtrToStringAnsi如果非托管字符串是ANSI,PtrToStringUni如果非托管字符串是Unicode,或PtrToStringBSTR如果非托管字符串是BSTR类型。 PtrToStringAuto假定非托管字符串是一个Windows 98或ME系统的ANSI和Unicode的Windows NT 4.0,2000或XP平台上。 PtrToStringAuto实际上是调用PtrToStringAnsi或PtrToStringUni,取决于操作系统。每个函数重载接受一个可选的数字复制的字符。如果你没有提供的字符数,函数看起来为终止空字符:"复制整个字符串昏暗的MyString的字符串= Marshal.PtrToStringAuto(MyPointer)"复制前5个字符DIM MyString的字符串= Marshal.PtrToStringAuto(MyPointer,5)
拿着一个字符串要释放非托管内存缓冲区,可以调用FreeHGlobal或FreeCoTaskMem成员。要免费StringToBSTR创建一个BSTR,你叫FreeBSTR,这反过来又调用FreeSysString功能。 - ; StructureToPtr和PtrToStructure
你写的非托管内存结构(用户定义类型)使用的StructureToPtr方法。这种方法需要你有时间提前分配的内存缓冲区。它有三个参数:您要编写的结构,内存缓冲区的地址(IntPtr的),和一个删除标志。删除标志设置为True湿巾和释放任何现有的数据从缓冲区。这是非常重要的,因为你可能会导致内存泄漏不删除现有的缓冲空间。例如,如果结构的领域之一,是另一种结构或字符串的引用,数据被外地引用不会被释放,如果该参数设置为False。还要注意的是结构复制到非托管内存,使用特定的格式(你可以控制可选),和非托管的副本可能不像完全的托管表示。使用sizeof的方法来确定缓冲区所需的字节数:DIM MYVARIABLE为点MyVariable.X = 100MyVariable.Y = 250DIM MyPointer作为IntPtr的Marshal.AllocHGlobal(Marshal.SizeOf(MYVARIABLE))Marshal.StructureToPtr(MYVARIABLE,MyPointer,假)
使用PtrToStructure方法扭转的过程和读从非托管内存结构。您可以使用此方法可以作为一个函数返回一个结构的副本类型的基础上,或填补了结构参数作为一个子。请注意,PtrToStructure返回一个Object类型的引用,和Option Strict On时,您必须转换为结构类型(例如,所使用的CType):作为点DIM MyPointMyPoint = CTYPE(Marshal.PtrToStructure(MyPointer的GetType(点)),点)复制方法
读取和写入阵列中的数据,尤其是宝贵的,当你需要二进制数据流。 Copy方法读取和写入,根据您传递给它的参数。如果你想写入数据,你需要先分配一些缓冲区空间,就像你会使用字符串。接下来,您呼叫的复制方法,并通过数组本身,目的地址(IntPtr的分配),你要开始复制的元素的数组的索引,和缓冲区的大小:DIM MyData的(255)作为字节"在这里插入代码,以填补字节数组DIM BufferAddress的IntPtr = Marshal.AllocHGlobal(256)Marshal.Copy(MYDATA,0,BufferAddress,256)
要阅读从非托管内存中的数组,调用复制的方法,并通过缓冲区的地址(IntPtr的),你想从缓冲区中的数据填充数组,数组的索引,你要开始复制到了,你要复制的数据的大小:MyData的DIM(255)以字节 Marshal.Copy(BufferAddress,MYDATA,0,256)
Marshal类中有更多的方法,但他们大多是公用事业援助COM代码进行互操作。结论
这些功能也相当有助于封送处理以及asnbsp管理的数据; CopyMemory如非托管的内存也被称为RtlMoveMomry功能的一个很好的替代。
我总是乐于帮助,因此,如果您有任何疑问,或对我的文章建议,感到自由。您还可以在MSN Messenger上达到我的屏幕名称千里马吗??

时间: 2024-10-07 22:31:25

Marshal 类的内存操作的一般功能的相关文章

详解 字符内存操作流

目录 字符内存操作流 CharArrayWrite类: CharArrayReader类: StringWriter类: StringReader类: (请观看本人博文--<详解 内存操作流>) @ 字符内存操作流 字符内存操作流 按照功能分 ,共分为 两种: 分类: 操作字符数组 CharArrayWrite CharArrayReader 操作字符串 StringWriter StringReader 那么,本人现在就对这两种字符内存操作流进行下讲解: 首先是 操作字符数粗的 CharAr

客户端服务器通讯常用的一种方法——Marshal类

这个类是.NETFramework2.0中的类,所以我们能够将其用于Unity中.与这个类类似的还有litjson等,可能是为了节省字节空间,Marshal类只仅仅将值进行打包成bytes流,而json还包含前面的key值.当然你也可以选择json的方式,我这里仅仅介绍Marshal类的使用. Marshal类支持从托管内存空间复制数据到非托管内存空间,或是从非托管内存空间到托管内存空间.如果你研究在线的MSDN文档库,你会看到在桌面.NET框架下这个类支持的分配非托管内存空间的方法和其他的一些

java基础知识回顾之javaIO类--内存操作流ByteArrayInputStream和ByteArrayOutputSteam(操作字节数组)

直接看代码: package cn.itcast.io.p6.bytestream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; public class ByteArrayStreamDemo { /** * @param args * @throws IOException * 特点 * 1.内存操作流 * 2.不操作底层资源,不调

【转】《深入理解计算机系统》C程序中常见的内存操作有关的典型编程错误

原文地址:http://blog.csdn.net/slvher/article/details/9150597 对C/C++程序员来说,内存管理是个不小的挑战,绝对值得慎之又慎,否则让由上万行代码构成的模块跑起来后才出现内存崩溃,是很让人痛苦的.因为崩溃的位置在时间和空间上,通常是在距真正的错误源一段距离之后才表现出来.前几天线上模块因堆内存写越界1个字节引起各种诡异崩溃,定位问题过程中的折腾仍历历在目,今天读到<深入理解计算机系统>第9章-虚拟存储器,发现书中总结了C程序中常见的内存操作有

IO-05内存操作流06管道流

JAVA中可以将输出的位置设置在内存上,此时使用ByteArrayInputStream,ByteArrayOutputStream来完成输入,输出功能. 利用这两个类实现大小字母的转换: package lianxijihe; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; impo

JAVA的IO操作:内存操作流

掌握内存操作流 输入和输出都是从文件中来的,当然,也可将输出的位置设置在内存上,这就需要ByteArrayInputStream和ByteArrayOutputStream ByteArrayInputStream:将内容写入到内存中, ByteArrayOutputStream:将内存中数据输出 此时的操作应该以内存为操作点. 利用此类 完成一些功能. 常用方法 ByteArrayInputStream :是InputStream子类. public class ByteArrayInputS

Java API —— IO流(数据操作流 &amp; 内存操作流 &amp; 打印流 &amp; 标准输入输出流 &amp; 随机访问流 &amp; 合并流 &amp; 序列化流 &amp; Properties &amp; NIO)

1.操作基本数据类型的流 1) 操作基本数据类型 · DataInputStream:数据输入流允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型.应用程序可以使用数据输出流写入稍后由数据输入流读取的数据. · DataOutputStream:数据输出流允许应用程序以适当方式将基本 Java 数据类型写入输出流中.然后,应用程序可以使用数据输入流将数据读入. package datastreamdemos; import java.io.*; /** * Created b

类对象内存分布

================================================================================================ 如何计算类对象占用的字节数? 一个空类的话1个字节.这是为了保证n个连续空类声明时,变量地址有偏移,防止变量覆盖. 非空类的话用关键字sizeof计算.如果手工计算就相当麻烦,光padding就一堆规则了.而且有些额外信息比如虚函数(多个虚函数也只产生一个vptr指针)等等.一个类成员 ,当有虚函数时,有

Java基础系列10:内存操作流,管道流,合并流,压缩流以及回退流

前言:这篇文章将对几个"非主流"的IO流进行简单的介绍 一 内存操作流 内存操作流的主要作用是完成内存的输入和输出.比如说在某些情况下需要生成一些临时信息,而将这些临时信息保存在文件中不仅要进行文件的读写而且在功能完成之后还需要删除这个临时文件,因此比较麻烦,这时或许就需要用到内存操作流了. 需要用到的API是:ByteArrayInputStream和ByteArrayOutputStream,分别表示输入流和输出流,示例代码如下: package javase.io; import