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++ 動態庫,還有一個特別麻煩的問題就是參數對於的問題。后續會結合網上的資料總結一份詳細的對照表。

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM