1. 程式人生 > >VS2017編寫純C庫以及使用C#呼叫C庫方法

VS2017編寫純C庫以及使用C#呼叫C庫方法

原博主部落格地址:https://blog.csdn.net/qq21497936
本文章部落格地址:https://blog.csdn.net/qq21497936/article/details/83825098

 

            VS2017編寫純C庫以及使用C#呼叫C庫方法

 

Demo原始碼下載

      https://download.csdn.net/download/qq21497936/10770528

 

建立C庫

使用VS2017建立Visual C++ Dll空專案

開啟VS2017建立Visual C++桌面嚮導,如下圖:

點選確認後,開始嚮導建立工程,如下圖:

點選“確認”,工程目錄,如下圖:

 

建立庫原始碼,並生成C庫

新增標頭檔案(cDllDemo.h)與原始檔(cDllDemo.cpp)

定義變數和函式巨集定義

實現函式原始碼

編譯生成動態庫

添加回調函式

C庫標頭檔案新增(回撥函式的全域性變數指標和設定回撥函式的函式)

C庫原始檔新增

解決被呼叫時可能無法檢視到printf列印資訊

 

winform以及wpf使用C庫

建立wpf工程(winform工程呼叫也是一樣)

設定依賴項,為了每次執行該測試應用之前,先編譯生成對應的dll,方式dll修改未更新,如下圖:

 

填入測試程式碼

執行時出現如下報錯,呼叫不帶輸入引數的不報錯,輸入引數的簽名對不上(就是函式定義);

此時我們修改c#呼叫方式,如下圖:

執行結果:

使用C庫中的全域性變數

       在c中把全域性變數的讀寫封裝成函式,c#通過P/Invoke來呼叫函式(理解為set和get),修改c庫標頭檔案內容如下:

原始檔如下:

       修改wpf程式如下:

執行結果如下:

使用C庫中的回撥函式

       首先,在C庫標頭檔案和原始檔中定義回撥函式全域性變數和回撥函式,如下圖:

       在c#中回撥步驟:1定義委託->2引入C庫函式->3定義靜態委託函式->4定義委託變數->5設定委託

在C#中若出現直接掛掉(當前專案中,若當機無異常或者無已停止執行,目前所知都是呼叫的C庫掛掉的,從C庫找原因),特別注意委託函式需要加上呼叫的方式,是Cdecl不是StdDecl,如下圖:

       如果不寫該項,則表示委託定義預設為StdDecl,讀者可自行嘗試,會跑完會後會直接掛掉,示意如下圖:

理解[UnmanagedFunctionPointer(CallingConvention.Cdecl)]

  1. UnmanagedFunctionPointer:表示動態使用未託管的dll函式指標;
  2. CallingConvention.Cdecl:C呼叫約定(即用__cdecl關鍵字說明)按從右至左的順序壓引數入棧,由呼叫者把引數彈出棧。對於傳送引數的記憶體棧是由呼叫者來維護的(正因為如此,實現可變引數的函式只能使用該呼叫約定)。另外,在函式名修飾約定方面也有所不同。_cdecl是C和C++程式的預設呼叫方式。每一個呼叫它的函式都包含清空堆疊的程式碼,所以產生的可執行檔案大小會比呼叫_stdcall函式的大。函式採用從右到左的壓棧方式。VC將函式編譯後會在函式名前面加上下劃線字首,是MFC預設呼叫約定;
  3. CallingConvention.StdDecl:__stdcall呼叫約定相當於16位動態庫中經常使用的PASCAL呼叫約定。在32位的VC++5.0中PASCAL呼叫約定不再被支援(實際上它已被定義為__stdcall。除了__pascal外,__fortran和__syscall也不被支援),取而代之的是__stdcall呼叫約定。兩者實質上是一致的,即函式的引數自右向左通過棧傳遞,被呼叫的函式在返回前清理傳送引數的記憶體棧但不同的是函式名的修飾部分(關於函式名的修飾部分在後面將詳細說明)。_stdcall是Pascal程式的預設呼叫方式,通常用於Win32Api中,函式採用從右到左的壓棧方式,自己在退出時清空堆疊。VC將函式編譯後會在函式名前面加上下劃線字首,在函式名後加上"@"和引數的位元組數;

c庫列印資訊問題

C庫新增列印語句

執行的程式碼

 

關閉應用後打印出來:

解決被呼叫時可能無法檢視到printf列印資訊

需要重定向輸出,使用setbuf函式,如下圖:

不能在執行時,每次呼叫,所以我們優化一下,定義一個初始化函式,修改庫的標頭檔案和原始檔如下:

 

 

原博主部落格地址:https://blog.csdn.net/qq21497936
本文章部落格地址:https://blog.csdn.net/qq21497936/article/details/83825098