總結遇到的引用各種問題:(建議使用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)
{
//.....回調函數體
}