.NET Framework 2.0 组件和非托管代码与交互操作详解(转)
?????.NET Framework 將促進(jìn)與 COM 組件、COM+ 服務(wù)、外部類型庫(kù)和許多操作系統(tǒng)服務(wù)的交互操作。在托管和非托管對(duì)象模型之間,數(shù)據(jù)類型、方法簽名和錯(cuò)誤處理機(jī)制都存在差異。為了簡(jiǎn)化 .NET Framework 組件和非托管代碼之間的互用并便于進(jìn)行移植,公共語言運(yùn)行時(shí)將從客戶端和服務(wù)器中隱藏這兩種對(duì)象模型之間的差異。
??????在運(yùn)行時(shí)控制下執(zhí)行的代碼稱作托管代碼。相反,在運(yùn)行時(shí)之外運(yùn)行的代碼稱作非托管代碼。COM 組件、ActiveX 接口和 Win32 API 函數(shù)都是非托管代碼的示例。
與非托管代碼交互操作
NET Framework比其他開發(fā)平臺(tái)多提供了很多先進(jìn)技術(shù), 然而, 很少公司能承受起重新設(shè)計(jì)和重新實(shí)現(xiàn)所有的代碼. 微軟意識(shí)到這點(diǎn), 因此構(gòu)建了CLR來提供一種機(jī)制允許應(yīng)用程序可以包含托管代碼和非托管的代碼. 特別地, CLR支持三種交互場(chǎng)景:
?? 托管代碼可以調(diào)用DLL中的非托管的函數(shù): 托管代碼可以很容易地調(diào)喲哦能夠包含在DLL中的函數(shù), 這是通過使用一種稱為P/Invoke (Platform Invoke) 的機(jī)制來實(shí)現(xiàn)的. 畢竟, 定義在FCL中的很多類型都內(nèi)部調(diào)用了Kernel32.dll, User32.dll等中的函數(shù). 很多編程語言將暴露一種機(jī)制使得托管代碼很容易調(diào)用包含在DLL中的非托管函數(shù). 例如, 一個(gè)C#應(yīng)用程序可以調(diào)用Kernel32.dll中的CreateSemaphore函數(shù).
?? 托管代碼可以使用COM組件(server): 很多公司已經(jīng)實(shí)現(xiàn)了很多非托管的COM組件, 使用這些組件中的類型, 可以創(chuàng)建用于描述COM組件的托管的程序集, 托管的代碼可以訪問這些程序集中的托管的類型, 這就和訪問其他托管類型一樣. 參考與.NET Framework SDK一起發(fā)布的Tlbimp.exe工具. 有時(shí)候, 你可能沒有一個(gè)類型庫(kù)或者你想對(duì)TlbImp.exe產(chǎn)生的東西獲得更多的控制, 這樣, 你可以手動(dòng)地構(gòu)建一個(gè)類型, 讓CLR可以使用這個(gè)類型來實(shí)現(xiàn)適當(dāng)?shù)幕ゲ僮? 例如, 你可以在C#應(yīng)用程序中使用DirectX COM組件.
?? 非托管的代碼可以使用托管的類型(server): 很多現(xiàn)有的非托管的代碼需要你提供COM組件才能讓代碼正常地工作. 很容易通過托管代碼來實(shí)現(xiàn)這些組件, 這樣你可避免代碼必須處理引用計(jì)數(shù)和接口. 例如, 你可以用C#創(chuàng)建一個(gè)ActiveX控件或者shell extension. 參考TlbExp.exe和RegAsm.exe工具.
????
??????除了這些場(chǎng)景, 微軟的C++/CLI編譯器(version 14)支持一個(gè)新的/clr命令行開關(guān), 這個(gè)開關(guān)告訴編譯器產(chǎn)生IL代碼, 而不是native CPU指令. 如果你有大量已有的C++代碼, 你可以使用這個(gè)新編譯開關(guān)重新編譯這些代碼, 新的代碼需要CLR才能執(zhí)行, 你可以修改代碼來充分利用CLR特有的功能.
但是對(duì)于下面的方法, /clr開關(guān)目前還不能將它們編譯成IL代碼: 包含內(nèi)聯(lián)匯編語言(通過關(guān)鍵字__asm實(shí)現(xiàn)); 接受可變數(shù)目參數(shù)的方法; 調(diào)用setjmp的方法; 包含一些內(nèi)部程序(intrinsic routine)(例如__enable, __disable, __ReturnAddress, __AddressOfReturnAddress)的方法. 對(duì)于C++/CLI編譯器不能編譯成IL的完整列表, 可以參考關(guān)于編譯器的文檔. 當(dāng)編譯器不能編譯成IL時(shí), 它會(huì)將方法編譯成x86代碼, 使得應(yīng)用程序仍然能運(yùn)行.
記住盡管產(chǎn)生的IL代碼是托管的, 但是數(shù)據(jù)并不是, 也就是說數(shù)據(jù)對(duì)象不是從托管堆上分配的, 因此它們不能使用垃圾回收機(jī)制. 實(shí)際上, 數(shù)據(jù)類型沒有包含在metadata中, 并且這些類型的方法名仍然需要經(jīng)過C++簽名編碼中轉(zhuǎn)換(mangle).
下面的C代碼調(diào)用了標(biāo)準(zhǔn)C運(yùn)行時(shí)庫(kù)函數(shù)printf, 也調(diào)用了System.Console.WriteLine方法, System.Console類型定義在FCL中, 因此C/C++代碼可以使用.
#include <stdio.h> // For printf
#using <mscorlib.dll> // For managed types defined in this assembly
using namespace System; // Easily access System namespace types
// Implement a normal C/C++ main function
void main() {
// Call the C runtime library's printf function.
printf("Displayed by printf.\r\n");
// Call the FCL's System.Console's WriteLine method.
Console::WriteLine("Displayed by Console::WriteLine.");
}
編譯這段代碼不是很容易, 如果這個(gè)代碼是在文件ManagedCApp.cpp中, 你會(huì)執(zhí)行如下的命令來編譯它:
cl /clr ManagedCApp.cpp
結(jié)果是ManagedCApp.exe程序集文件, 如果你運(yùn)行ManagedCApp.exe, 你將會(huì)看到如下的輸出:
C:\>ManagedCApp
Displayed by printf.
Displayed by Console::WriteLine.
如果你使用ILDasm.exe來檢查這個(gè)文件, 你將會(huì)看到定義在這個(gè)程序集中的所有的全局函數(shù)和全局字段, 顯然地, 編譯器自動(dòng)地產(chǎn)生了很多填充代碼. 如果你雙機(jī)Main函數(shù), ILDasm會(huì)為你顯示出IL代碼.
.method assembly static int32
modopt([mscorlib]System.Runtime.CompilerServices.CallConvCdecl) main() cil managed
{
? .vtentry 70 : 1
? // Code size 23 (0x17)
? .maxstack 1
? IL_0000: ldsflda valuetype '<CppImplementationDetails>' .$ArrayType$$$BY0BH@$$CBD
?????????????????????? modopt([mscorlib]System.Runtime.CompilerServices.IsConst)
?????????????????????? '??_C@_0BH@GBHlFCOF@Displayed?5by?5printf?4?$AN?6?$AA@'
? IL_0005: call???? vararg int32
?????????????????????? modopt([mscorlib]System.Runtime.CompilerServices.CallConvCdecl)
?????????????????????? printf(
???????????????????????? int8
???????????????????????? modopt(
?????????????????????????? [mscorlib]System.Runtime.CompilerServices.IsSignUnspecifiedByte)
???????????????????????? modopt(
?????????????????????????? [mscorlib]System.Runtime.CompilerServices.IsConst)*
??????????????????????? )
? IL_000a: pop
? IL_000b: ldstr "Displayed by Console::WriteLine"
? IL_0010: call void [mscorlib]System.Console::WriteLine(string)
? IL_0015: ldc.i4.0
? IL_0016: ret
} // end of method 'Global Functions'::main
?
本文來自CSDN博客,轉(zhuǎn)載請(qǐng)標(biāo)明出處:http://blog.csdn.net/libright/archive/2009/03/04/3957359.aspx
?
轉(zhuǎn)載于:https://www.cnblogs.com/elock/archive/2009/09/02/1558902.html
總結(jié)
以上是生活随笔為你收集整理的.NET Framework 2.0 组件和非托管代码与交互操作详解(转)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 兴业银行信用卡有效期多长时间?有效期怎么
- 下一篇: 从零开始实现ASP.NET Core M