2013-05-30 19 views
1

我發現有一堆項目(SharpDX等)被編譯爲允許CLR「管理」本機代碼,然後直接從例如c#調用本機代碼(C++函數)。託管C++庫,它是如何工作的?

我想弄明白這是如何工作的。如果你們中任何人都知道,這將是很好的。

到目前爲止我所看到的是,我可以將C#項目中的引用添加到「CLR兼容」C++庫中,就像任何其他c#庫(不需要反射)一樣,添加它就像:「using myCppLibrary 「然後調用任何可用的方法。

當我去看剛剛添加的引用中可用的函數時,似乎可以從c#訪問C++庫的標頭(.h)文件中聲明爲PUBLIC的任何東西,因爲它們會自動轉換爲由編譯器編寫的c#代碼。

因此,實際上正在發生的事情是:

我宣佈我的C++庫的公共方法/變量在頭文件(.h)。 我編譯它們檢查CLR管理在庫的屬性選項卡中是否可用。 (我正在使用Visual Studio 2012) 編譯器爲每個包含任何公共方法/屬性的頭文件(.h)生成c#類。

但我不明白的是,當我打電話讓我們說,來自「myCppLibrary」的giveNumber()函數..該函數的執行在哪裏進行?

CLR是否會自動與C++本機代碼進行互通或實際上發生了什麼?

回答

2

當您在C++中啓用CLR時,編譯器會將C++代碼編譯爲IL而不是本地代碼。在這種情況下,C++,稱爲C++/CLI增加有各種特徵,以允許它使用垃圾收集器,具有優於垃圾收集存儲器是否被固定,以避免其移動約精細控制等

書寫一般而言,C++/CLI是一項專業任務,需要C++和C#的知識(可以做出一些細微差別和缺陷)。通常推薦用於本機代碼和託管代碼之間的接口,但可用於將整個庫製作成.net。

+0

爲什麼downvote?這在技術上是正確的。 – usr

+0

@us我想知道同樣的事情,但是如果我搞砸了,我太尷尬了。如果你可以提供更好的答案,那麼我只需要5-10分鐘的時間就可以看到更好的答案。 – TooTone

+0

我想有人發現cpp.exe可能會將C++編譯爲IL,這是非常不可信的。當我在前一段時間瞭解到這一點時,我也很驚訝。 – usr

3

不太確定我完全理解你所看到的。但很有可能你會看到錯誤的副作用。 C++/CLI編譯器能夠將任何與C++ 03兼容的本地C++代碼編譯爲IL。 IL和抖動都足夠靈活以支持這一點。就像由C#編譯器生成的IL一樣,這種IL將在運行時轉換爲機器代碼,並以完全相同的方式進行優化。

然而,這不是而是使它成爲託管代碼。這個代碼創建的任何對象仍然是本地對象,它們被分配到非託管內存中,就像本地C++編譯器所做的那樣。垃圾收集器完全無視它們。

那麼錯誤就是允許將代碼翻譯成IL。您錯過了C++代碼生成器可以在編譯時花費額外時間來查找最佳優化機器代碼的額外時間。抖動也得到了優化,但它不能做得很好,不得不在有限的時間內進行操作。當然,你會在運行時使用開銷。

本地結構和類將在程序集元數據中可見。但是它們只是不透明的值類型,沒有它們的成員可以訪問C#程序。你不能直接從C#中調用這樣一個本地類的方法。爲了可用,C++/CLI程序必須聲明類型爲ref上下文關鍵字。像ref類,C#類的確切等價物。

因此,將本地代碼編譯爲機器代碼非常重要,就像常規C++編譯器一樣。你通過編譯一個沒有/ clr的.cpp源文件來實現。或者通過使用#pragma unmanaged和#pragma managed這樣的代碼封裝這些代碼,在機器代碼和IL代之間來回切換編譯器。您從C++/CLI獲得的增值是ref類中的方法可以直接使用本機代碼,而不必像Catch那樣在C#中遇到麻煩。並且使用本地C++類,這是C#完全無法做到的。

相關問題