C#总结(四)调用C++动态库
由于公司很多底層的SDK,都是C++開發,上層的應用軟件卻是C# Winform程序。在實際工作的過程中,就經常碰到了C# 程序調用C++ 動態庫的問題。最近一直在和C++ 打交道,C# 怎么調用C++ 類庫函數。也遇到了一些問題,所以就來總結總結C#程序調用C++動態庫時的各種坑。
?
1.?可能遇到的問題:
? ? ? ? C#在調用動態庫的過程中我也遇到了以下一些問題:
????????1、C++中有指針,C#中需要使用指針嗎?
????????由于C++中的動態庫中有指針參數,因此我也是用.NET的不安全代碼,使用了C#的指針,但是也還是出現了一些問題,如在C#中傳入的參數是一個二維數組時就出現了問題,最后只能改C++函數傳入參數的參數類型。
????????2、C#和C++中的類型如何轉換呢?
??????? 雖然C#和C++比較類似,但是其給我們的參數類型我們要與C#的參數類型一一對應起來,具體看后續說明。
????????3、C++函數中的CallingConventionCharSet 怎么設置?
調用C++函數之前一定要先確認,否則可能出現函數調用導致堆棧不對稱。原因可能是托管的?PInvoke?簽名與非托管的目標簽名不匹配的問題。函數的CallingConvention和CharSet,可以查看動態庫對應的 .h頭文件。
????????4、如何反編譯C++的dll的名稱,端口?
??????? 可以通過Dependency Walker工具進行反編譯查看別人寫的動態庫的信息
5、指針函數如何傳參?
對于函數需要的指針函數,C# 調用時,可以定義委托來傳入參數。?
6、需要注意C++ dll 編譯的平臺是x86還是x64,是多字節的還是雙字節的(Unicode)。
?
2.?通過Dependency Walke查看dll的名稱,端口
下載Dependency 后將對應的C++ dll文件加載進去,就尅看到動態庫的對應的信息,同時也可以通過.h 頭文件查看。
?
3. 如何調用
c#調用c++動態庫一般我們這樣寫
[DllImport(SDK, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]public static extern int IKSDK_Release(); 1. DllImport的第一個參數SDK是動態庫dll的路徑,此dll放在程序運行的根目錄或者c:windows/sytem32下,建議在程序根目錄創建一個子目錄來放置相應的C++ 動態庫文件,方便以后更新。2. CallingConvention 參數是c#調用c++的方式 是個枚舉 msdn解釋如下:
| Cdecl | 調用方清理堆棧。這使您能夠調用具有?varargs?的函數(如?Printf),使之可用于接受可變數目的參數的方法。? |
| FastCal | 不支持此調用約定。 |
| StdCall | 被調用方清理堆棧。這是使用平臺 invoke 調用非托管函數的默認約定。? |
| ThisCall | 第一個參數是?this?指針,它存儲在寄存器 ECX 中。其他參數被推送到堆棧上。此調用約定用于對從非托管 DLL 導出的類調用方法。? |
| Winapi | 此成員實際上不是調用約定,而是使用了默認平臺調用約定。例如,在 Windows 上默認為?StdCall,在 Windows CE.NET 上默認為?Cdecl。? |
3. CharSet參數是控制名稱重整以及將字符串參數封送到函數中的方式。 默認值為 CharSet.Ansi。
4.?entrypoint參數用于標識函數在 DLL 中的位置。在托管對象中,目標函數的原名或序號入口點將標識跨越交互操作邊界的函數。此外,您可以將入口點映射到一個不同的名稱,這實際上是將函數重命名。一般默認不設置此參數。
5. 其他參數,請查看MSDN對于 DllImportAttribute 的說明。
4. 其他說明
C# 調用C++ 動態庫,還有一個特別麻煩的問題就是參數對于的問題。后續會結合網上的資料總結一份詳細的對照表。
?
轉載于:https://www.cnblogs.com/zhangweizhong/p/8119340.html
總結
以上是生活随笔為你收集整理的C#总结(四)调用C++动态库的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Maven3版本的超级POM位置及中央仓
- 下一篇: C#缓存absoluteExpirati