?????.NET Framework 將促進與 COM 組件、COM+ 服務、外部類型庫和許多操作系統服務的交互操作。在托管和非托管對象模型之間,數據類型、方法簽名和錯誤處理機制都存在差異。為了簡化 .NET Framework 組件和非托管代碼之間的互用并便于進行移植,公共語言運行時將從客戶端和服務器中隱藏這兩種對象模型之間的差異。
??????在運行時控制下執行的代碼稱作托管代碼。相反,在運行時之外運行的代碼稱作非托管代碼。COM 組件、ActiveX 接口和 Win32 API 函數都是非托管代碼的示例。
與非托管代碼交互操作
NET Framework比其他開發平臺多提供了很多先進技術, 然而, 很少公司能承受起重新設計和重新實現所有的代碼. 微軟意識到這點, 因此構建了CLR來提供一種機制允許應用程序可以包含托管代碼和非托管的代碼. 特別地, CLR支持三種交互場景:
?? 托管代碼可以調用DLL中的非托管的函數: 托管代碼可以很容易地調喲哦能夠包含在DLL中的函數, 這是通過使用一種稱為P/Invoke (Platform Invoke) 的機制來實現的. 畢竟, 定義在FCL中的很多類型都內部調用了Kernel32.dll, User32.dll等中的函數. 很多編程語言將暴露一種機制使得托管代碼很容易調用包含在DLL中的非托管函數. 例如, 一個C#應用程序可以調用Kernel32.dll中的CreateSemaphore函數.
?? 托管代碼可以使用COM組件(server): 很多公司已經實現了很多非托管的COM組件, 使用這些組件中的類型, 可以創建用于描述COM組件的托管的程序集, 托管的代碼可以訪問這些程序集中的托管的類型, 這就和訪問其他托管類型一樣. 參考與.NET Framework SDK一起發布的Tlbimp.exe工具. 有時候, 你可能沒有一個類型庫或者你想對TlbImp.exe產生的東西獲得更多的控制, 這樣, 你可以手動地構建一個類型, 讓CLR可以使用這個類型來實現適當的互操作. 例如, 你可以在C#應用程序中使用DirectX COM組件.
?? 非托管的代碼可以使用托管的類型(server): 很多現有的非托管的代碼需要你提供COM組件才能讓代碼正常地工作. 很容易通過托管代碼來實現這些組件, 這樣你可避免代碼必須處理引用計數和接口. 例如, 你可以用C#創建一個ActiveX控件或者shell extension. 參考TlbExp.exe和RegAsm.exe工具.
????
??????除了這些場景, 微軟的C++/CLI編譯器(version 14)支持一個新的/clr命令行開關, 這個開關告訴編譯器產生IL代碼, 而不是native CPU指令. 如果你有大量已有的C++代碼, 你可以使用這個新編譯開關重新編譯這些代碼, 新的代碼需要CLR才能執行, 你可以修改代碼來充分利用CLR特有的功能.
但是對于下面的方法, /clr開關目前還不能將它們編譯成IL代碼: 包含內聯匯編語言(通過關鍵字__asm實現); 接受可變數目參數的方法; 調用setjmp的方法; 包含一些內部程序(intrinsic routine)(例如__enable, __disable, __ReturnAddress, __AddressOfReturnAddress)的方法. 對于C++/CLI編譯器不能編譯成IL的完整列表, 可以參考關于編譯器的文檔. 當編譯器不能編譯成IL時, 它會將方法編譯成x86代碼, 使得應用程序仍然能運行.
記住盡管產生的IL代碼是托管的, 但是數據并不是, 也就是說數據對象不是從托管堆上分配的, 因此它們不能使用垃圾回收機制. 實際上, 數據類型沒有包含在metadata中, 并且這些類型的方法名仍然需要經過C++簽名編碼中轉換(mangle).
下面的C代碼調用了標準C運行時庫函數printf, 也調用了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.");
}
編譯這段代碼不是很容易, 如果這個代碼是在文件ManagedCApp.cpp中, 你會執行如下的命令來編譯它:
cl /clr ManagedCApp.cpp
結果是ManagedCApp.exe程序集文件, 如果你運行ManagedCApp.exe, 你將會看到如下的輸出:
C:\>ManagedCApp
Displayed by printf.
Displayed by Console::WriteLine.
如果你使用ILDasm.exe來檢查這個文件, 你將會看到定義在這個程序集中的所有的全局函數和全局字段, 顯然地, 編譯器自動地產生了很多填充代碼. 如果你雙機Main函數, ILDasm會為你顯示出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博客,轉載請標明出處:http://blog.csdn.net/libright/archive/2009/03/04/3957359.aspx
?