在實際軟件開發過程中,由於公司使用了多種語言開發,在C#中可能需要實現某個功能,而該功能可能用其他語言已經實現了,那麼我們可以調用其他語言寫好的模塊嗎?還有就是,由於C#開發好的項目,我們可以利用reflector等反編譯工具反編譯出其源代碼,所以對於一些核心算法,我們不希望被別人知道,因此為了增強代碼的安全性,我們需要將一些核心算法用C或C++來編寫,然後用C#來調用這些已經寫好的接口。在面對以上情況時,我們該怎麼做呢? 方案一:重新實現 針對第一種情況,我們可以將C或者C++功能用C#來重新實現,這樣的話代碼比較統一,維護比較方便,但是這樣的話增加了軟件開發的成本,把C++的代碼功能改成C#涉及到指針和內存的操作比較繁瑣,況且有開發好的模塊為什麼不重復利用呢?針對第二種情況就不能得到有效解決,雖然可以使用混淆器對代碼進行混淆,但是任然不是很安全。 方案二:封裝COM組件 我們可以將C或者C++的函數封裝成COM組件,在C#中調用時比較方便,但是COM組件需要注冊,而且多次注冊可能也會導致一些問題,同時在處理C或者C++的類型與COM組件的類型轉換的時候也可能有些麻煩。 方案三:使用動態鏈接庫 我們可以直接調用C或者C++已經寫好的動態鏈接庫,這樣比較方便,這樣很好的解決了上述問題。 在實際項目中,我們需要使用C#調用C++的一些接口,因此我使用的是方案三采用動態庫,下面我就在實際中怎麼處理的進行說明。 在調用動態庫的過程中我也遇到了以下一些問題: 1、C++中有指針,C#中需要使用指針嗎? 由於C++中的動態庫中有指針參數,因此我也是用.NET的不安全代碼,使用了C#的指針,但是最後也還是出現了一些問題,如在C#中傳入的參數是一個二維數組時就出現了問題,這個問題我在網上找了好多資料也沒有解決,最後和c++程序員商量了下改變了傳入參數的參數類型。最後也沒有使用指針。 2、C#和C++中的類型如何轉換呢? 雖然C#和C++比較類似,但是其給我們的參數類型我們要與C#的參數類型一一對應起來,因此我找了一些資料把其類型一一對應了,具體看後續說明。 3、C++寫好的動態庫放到那個位置呢? 關於C++動態庫的位置也是個問題,在應用中我們使用了相對路徑和絕對路徑進行測試,有的發現在VS中可以調用到,但是發布後發現無法調用到動態庫,最後只要把動態的dll放到系統的目錄system32下面才解決了改問題,目前還沒找到其他的方法,如有其他的更好方法還請大家指點。 4、如何反編譯C++的dll的名稱,端口? 可以通過Dependency Walker工具進行反編譯查看別人寫的動態庫的信息 5、還有其他的一些細節,如C#調用動態庫需要指定其編碼、代碼寫法等等 public class TestDLL {www.2cto.com [DllImport(@"SomClient.dll", EntryPoint = "CreateSomClient", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] public static extern UInt32 CreateSomClient(String hostIp, UInt16 port); [DllImport(@"SomClient.dll", EntryPoint = "ReleaseSomClient", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] public static extern void ReleaseSomClient(ref UInt32 clientHandle); } 參數說明: EntryPoint 指定要調用的 DLL 入口點。 CharSet 控制名稱及函數中字符串參數的編碼方式。默認值為 CharSet.Ansi。 ExactSpelling 是否修改入口點以對應不同的字符編碼方式。 CallingConvention 指定用於傳遞方法參數的調用約定。默認值為 WinAPI。該值對應於基於32位Intel平台的 __stdcall。 BestFitMapping 是否啟用最佳映射功能,默認為 true。最佳映射功能提供在沒有匹配項時,自動提供匹配的字符