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

时间:2024-01-03 12:06:20

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上达到我的屏幕名称千里马吗??