C# 調用C++ DLL

總結遇到的引用各種問題:(建議使用x86的編譯方式)

[DllImport(@"XXX.dll", EntryPoint = "TOEC_ComInit", CharSet = CharSet.Ansi, ExactSpelling = false, CallingConvention = CallingConvention.Cdecl)]
public static extern int Com_Init(int flag);

第一個參數:就是引用的DLL名稱;

第二個參數【EntryPoint】:指示要調用的 DLL 入口點的名稱或序號;就是DLL中要調用的方法名稱;

第三個參數【CharSet】:指示如何向方法封送字符串參數,並控制名稱重整;就是編碼格式;

第四個參數【ExactSpelling】:控制 System.Runtime.InteropServices.DllImportAttribute.CharSet 字段是否使公共語言運行時在非託管,DLL 中搜索入口點名稱,而不使用指定的入口點名稱。

第五個參數【CallingConvention】:指示入口點的調用約定

(1)Winapi:此成員實際上不是調用約定,而是使用了默認平臺調用約定。例如,在 Windows 上默認爲 System.Runtime.InteropServices.CallingConvention.StdCall,在Windows CE.NET 上默認爲 System.Runtime.InteropServices.CallingConvention.Cdecl。
(2)Cdecl:調用方清理堆棧。這使您能夠調用具有 varargs 的函數(如 Printf),使之可用於接受可變數目的參數的方法。
(3)StdCall:被調用方清理堆棧。這是使用平臺 invoke 調用非託管函數的默認約定。
(4)ThisCall:第一個參數是 this 指針,它存儲在寄存器 ECX 中。其他參數被推送到堆棧上。此調用約定用於對從非託管 DLL 導出的類調用方法。
(5)FastCall:不支持此調用約定。

遇到的問題:CallBack::Invoke”類型的已垃圾回收委託進行了回調。這可能會導致應用程序崩潰、損壞和數據丟失。向非託管代碼傳遞委託時,託管應用程序必須讓這些委託保持活動狀態,直到確信不會再次調用它們。

解決辦法:

回調函數寫成全局靜態成員函數。

原始錯誤的寫法:

 [DllImport(@"COM_DLL.dll", EntryPoint = "TOEC_ComRun", CharSet = CharSet.Ansi, ExactSpelling = false, CallingConvention = CallingConvention.Winapi)]
 public static extern int CPP_Run(CallBack cb);
 public delegate void CallBack(tagOutInfo data);
 CPP_Run(handle_sx, par, CallBack_Function);
 public static void CallBack_Function(tagOutInfo data)
 {
        //.....
 }

正確的寫法:

 [DllImport(@"COM_DLL.dll", EntryPoint = "TOEC_ComRun", CharSet = CharSet.Ansi, ExactSpelling = false, CallingConvention = CallingConvention.Winapi)]
 public static extern int CPP_Run(CallBack cb);
 public delegate void CallBack(tagOutInfo data);
 private CallBack cb_f;
 CPP_Run(handle_sx, par, cb_f );
 public void Init(){
   cb_f=CallBack_Function;
 }
 public void CallBack_Function(tagOutInfo data)
 {   
 //.....回調函數體
 }

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章