CLR完全介绍: 托管代码与非托管代码之间的封送处理

让我们面对现实吧。这个世界并不完美。几乎很少有公司在完全用托管代码开发程序,除此之外仍存在很多需要您处理的旧式非托管代码。您怎样将托管和非托管项目集成起来呢?在形式上是采用从托管应用程序调用非托管代码,还是从非托管代码应用程序调用托管代码?

幸运的是,Microsoft .NET Framework 互操作在托管和非托管代码之间开辟了一条通道,而封送处理则在该连接中扮演着非常重要的角色,因为它允许在两者之间进行数据交换(请参见图 1)。有很多因素会影响 CLR 在非托管和托管领域之间封送数据的方式,包括诸如 [MarshalAs]、[StructLayout]、[InAttribute] 和 [OutAttribute] 等属性,以及 C# 中 out 和 ref 之类的语言关键字。

Figure 1 Bridging the Gap between Managed and Unmanaged Code

因为这些因素很多,所以它可能是进行正确封送的一大难题,因为这项工作要求了解很多有关非托管和托管代码的详细情况。在本专栏中,我们会介绍您在日常工作中尝试进行封送处理时将遇到的一些基本却又容易混淆的主题。我们不会介绍自定义封送处理、封送处理复杂的结构或其他高级主题,但是如果真正理解了这些基本的概念,您就为处理这些问题做好准备了。

[InAttribute] 和 [OutAttribute]

我们要讨论的第一个封送处理主题是关于 InAttribute 和 OutAttribute 的使用,这是位于 System.Runtime.InteropServices 命名空间中的两种属性类型。(在将这些属性应用到您的代码中时,C# 和 Visual Basic 允许使用缩写形式 [In] 和 [Out],但是为了避免混淆我们坚持使用全名。)

当应用于方法参数和返回值时,这些属性会控制封送处理的方向,因此它们又被称为方向属性。[InAttribute] 告知 CLR 在调用开始的时候将数据从调用方封送到被调用方,[OutAttribute] 则告知 CLR 在返回的时候将数据从被调用方封送回调用方。调用方和被调用方都可以是非托管或托管代码。例如,在 P/Invoke 调用中,是托管代码在调用非托管代码。但是在反向 P/Invoke 调用中,就可能是非托管代码通过函数指针调用托管代码。

[InAttribute] 和 [OutAttribute] 有四种可能的使用组合:只用 [InAttribute]、只用 [OutAttribute]、同时使用 [InAttribute, OutAttribute] 以及两者都不用。如果没有指定任何一个属性,那就是要 CLR 自己确定方向属性,默认情况下通常是使用 [InAttribute]。但是,如果是 StringBuilder 类,则在没有指定任何一个属性的情况下,会同时使用 [InAttribute] 和 [OutAttribute]。(有关详细信息,请参阅后面有关 StringBuilder 的部分。)另外,使用 C# 中的 out 和 ref 关键字可能会更改已应用的属性,如图 2 所示。请注意,如果没有为参数指定关键字,就意味着它是默认的输入参数。

Figure 2 Out and Ref and Their Associated Attributes

C# 关键字 属性
(未指定) [InAttribute]
out [OutAttribute]
ref [InAttribute],[OutAttribute]
时间: 2024-08-02 19:12:16

CLR完全介绍: 托管代码与非托管代码之间的封送处理的相关文章

求助,急,c++和c#之间数据封送问题

问题描述 这个是一个联合体中有两个结构体,每个结构体内部数据结构可能会差别较大.怎么在c#那边构造出相同的数据结构来取数据?typedefunion{struct{shortS1Short;longS1Long;charS1Char;}S1;struct{charS2CharA[20];__int64S2Int64;shortS2Short;}S2;}TestUnion;//数据结构extern"C"_declspec(dllexport)int_stdcalloutUnion(Tes

CLR 完全介绍: “Orcas”中新增的库类

下一版本的 Microsoft .NET Framework(将随附当前代号为"Orcas"的下一版 Visual Studio 提供)的程序集分为两组,内部称为"red bits"和"green bits".red bits 包括先前在 .NET Framework 2.0 和 3.0 中提供的所有库(例如,mscorlib.dll 和 system.dll).为了确保使 Visual Studio"Orcas"具有高度的向

通过托管代码访问非托管代码

问题描述 我先说一下我的项目的思路:我是想通过托管代码访问非托管代码,首先通过类似与如下的代码编译生成托管代码的dll文件.[DllImport("C:\ProgramFiles\VNI\imsl\cnl600\vc98pc\lib\imslcmath_dll.dll",EntryPoint="imsl_d_lin_sol_gen",ExactSpelling=false,CallingConvention=CallingConvention.Cdecl)]unsa

.NET简谈互操作(七:数据封送之介绍)

互操作系列文章: .NET简谈互操作(一:开篇介绍) .NET简谈互操作(二:先睹为快) .NET简谈互操作(三:基础知识之DllImport特性) .NET简谈互操作(四:基础知识之Dispose非托管内存) .NET简谈互操作(五:基础知识之Dynamic平台调用) .NET简谈互操作(六:基础知识之提升平台调用性能) .NET简谈互操作(七:数据封送之介绍) 我们继续.NET互操作学习.互操作的基础知识已经差不多完了,当然一篇小小的文章很难全面的讲述互操作的方方面面,本人只是总结出关键的地

CLR 完全介绍: 编写可靠的.NET代码

当我们谈论某样东西具有可靠性时,我们是指它值得信赖,而且可以预测.但是就软件而言,还必须具备其他重要属性,才可以说代码具有可靠性. 软件必须具有复原性,意思是说在出现内部和外部中断情况时,它仍然可以继续正常运行.它必须是可恢复的,以便它知道如何将自己恢复到先前已知的一致状态.软件必须可预测,这样它会提供及时的预期服务.它必须不可中断,意思是更改和升级都不会影响它的服务.最后,软件必须是生产就绪的,意思是它包含最少的 bug,并且只需要进行数量有限的更新.如果满足了这些条件,那么软件就真正称得上可

CLR完全介绍

发现和纠正托管应用程序中的内存问题可能十分困难. 内存问题的表现形式多种多样.例如,您会观 察到,您的应用程序的内存使用量在不断增加,最终导致"内存不足"(OOM) 异常(您的应用 程序甚至可能在有大量可用物理内存的情况下引发内存不足异常).但以下任何一种情况均表明内存可能 出现了问题: 引发 OutOfMemoryException(内存不足异常). 进程占用了太多内存,您无法确定任何明显 的原因. 似乎垃圾收集功能并没有快速清理对象. 托管堆碎片过多. 应用程序过 度占用 CPU.

CLR完全介绍: 反射之反思

您清晰的组件化目标是否因在库间共享过多类型信息而落空?或许您需要高效的强类型化数据存储,但如果每次对象模型发展后都需要更新您的数据库架构,那会耗费很大成本,所以您更愿意在运行时推断出其类型架构吗?您需要交付能接受任意用户对象的组件,并以某种智能化的方式处理它们吗?您希望库的调方者能以编程方式向您说明它们的类型吗? 如果您发现自己在苦苦维持强类型化数据结构的同时,又冀望于最大化运行时灵活性,那么您大概会愿意考虑反射,以及它如何改善您的软件.在本专栏中,我将探讨 Microsoft .NET Fra

CLR完全介绍: .NET的内部诊断工具

很多诊断工具都需要使用 CLR 分析 API,甚至包括那些在严格意义上讲不是探查器的工具.因此,如 果您曾经想知道这些工具是如何工作的,那么,了解 API 的分析会是个良好的开端.在本专栏中,您将 看到它们是如何工作的,并了解一些有用的提示和技巧.您还将在"其他分析资源"侧栏内找 到一些基本的资源. 若要使用 CLR 分析 API,需要使用非托管语言(通常是 C++)来创建 DLL,然后设置一些环境变量, 用于指导公共语言运行库 (CLR) 加载 DLL 并允许它使用分析 API.此

实时系统解决方案 TIBCO Rendezvous — 技术介绍(消息中间件|基于数据库的主动推送)

TIBCO Rendezvous - 技术介绍 1.1.1. TIBCO Rendezvous - 技术介绍 TIBCO Rendezvous(或称为TIBCO RV)产品是一种中间件,它具有发布/订阅(Publish/Subscribe).基于主题寻址(Subject-Based Addressing) 和自定义数据信息(Self-Describing Data Messages)等专利技术功能,使不同应用平台上的信息在一个共享的虚拟总线Information Bus(TIB)上进行传输交换.