2017-04-27 66 views
1

基本上我需要從Visual C++代碼調用C#代碼。 在閱讀了很多關於可能方式的文章後,我決定使用C++/CLI機制。從Visual C++調用C#代碼

最初我決定在C++本地代碼(dll庫項目)中使用一些函數,它們會從CLR項目中調用一些函數,它會從C#項目中調用一些函數。

之後,我想也許我可以擺脫橋樑項目(CLR項目),因爲它只是過渡到託管世界。我認爲我可以創建我的本地項目,並且可以向其中添加一個C++源文件,並且可以爲該文件啓用CLR支持,而不是整個項目。 所以這意味着我的本地項目將只包含一個可以使用C++/CLI語法的文件並且代表橋接。所有其他文件都只是本機C++源文件。 從設計的角度來看,這是正確的嗎?!

爲了達到上述目的,我想我必須將託管的C#dll文件添加到C++本機dll文件的Additional #using Directories屬性中。 問題是我不知道如何設置基於當前配置的C#dll調試或發佈版本的路徑。

另外我知道我不能將本機C++ DLL添加到C#項目引用。 但它看起來像我可以在本機C++項目中添加一個C#dll作爲參考。怎麼來的 ?!這甚至工作?! 如果我可以將C#dll添加到本機C++項目引用,是否需要設置這些#using目錄?!

回答

5

我可以只啓用該文件CLR的支持,而不是整個項目

有這樣做的,通過選擇CLR項目模板入門之間沒有有效的區別。無論哪種方式,結果都是混合模式.NET程序集,包含MSIL和本機代碼。在項目級別執行此操作只會爲項目中的.cpp文件設置/ clr的默認值。您也可以通過覆蓋單個.cpp文件(現在禁用/ clr)的設置來使用CLR項目模板來執行此操作。最終結果都是一樣的。

我想我必須在託管的C#dll文件添加到其他使用#using目錄

是的,這是做這件事。同樣可以解決您的查詢,您可以在路徑名中使用$(Configuration)宏。在編譯時解析爲「調試」或「釋放」,具體取決於您構建的配置。我應該強調這實際上並非必要。編譯器僅使用C#程序集中的元數據。只是聲明。 .h文件的確切等價物,請注意您很少根據配置使#include變得不同。唯一的情況是,當您在C#源代碼中使用#if DEBUG來包含/排除代碼時,這種情況並不常見。

但它看起來像我可以添加一個C#DLL作爲本地C++項目

這已經在每個VS版本中修修補補用,不是100%肯定,你在做什麼內部參考。實際上,添加引用時很少發生,它只是讓編譯器驅動程序添加/FU compile option。如果.cpp文件沒有用/ clr編譯,那麼它什麼也不做,編譯器完全忽略它。當您在源代碼中使用#using並且沒有使用/ clr時,它會大聲抱怨。否則兩者之間沒有真正的區別,只是更容易用/ FU來控制文件的路徑。

,因爲它不僅使過渡到管理世界

一個忠告是適當的在這裏,有很多事情。你在這裏做的是稱爲「反向調整」,本地代碼調用託管代碼。 C++/CLI主要是爲了完全相反。涉及更多的是,需要發生的不平凡的事情是CLR需要在第一次調用時加載和初始化。這完全是automagic,由使用__declspec(dllexport)時自動生成的存根提供。與Robert Giesecke的「Unmanaged Exports」實用程序所依賴的魔術一樣,您應該看看另一個選項。

但它是有限的。你不能公開一個對象模型,只是簡單的函數。函數調用會增加額外的開銷,儘管它非常適中。而這個大問題,你不能輕易診斷錯誤。 CLR和大多數C#代碼都希望調用者知道如何處理異常。問題是你不能從本機C++代碼。你有一些在使用__try/__except的餘地,但你不能得到有關例外的任何細節。這會將非常簡單的問題(如FileNotFoundException)變成完全不可知的崩潰。您可以通過將調試器類型設置爲「混合」來進行調試,但在發貨後您無法做任何有用的工作。非常難看的支持電話。

在沒有這些問題的情況下完成相同操作的其他方法是在C#庫中使用[ComVisible(true)],允許在本機C++代碼中使用#import。並通過其託管接口自定義託管CLR,這種方法使用的是支持用託管代碼編寫的插件的程序。像AutoCAD這樣的CAD程序就是很好的例子。和Visual Studio。

0

嘗試ILASM 2.0https://msdn.microsoft.com/tr-tr/library/496e4ekx(v=vs.110).aspx

基本上,工作是一樣的C++/CLI的出口。

// unmexports.il 
// Compile with : ilasm unmexports.il /dll 
.assembly extern mscorlib { auto } 
.assembly UnmExports {} 
.module UnmExports.dll 
.method public static void Bar() 
{ 
    .export [1] as bar 
    ldstr "Hello from managed function" 
    call void [mscorlib]System.Console::WriteLine(string) 
    ret 
} 

注意:您可以使用ILDASM反編譯C#和C++/CLI以瞭解如何導出它。 (如例子中)