使用DLLImport進行導入函數的事. C#調用C++的函數其實不止這一種方法, 還有一種方法是用delegate申明函數委托進行調用,這種方法略顯麻煩,但是可以進行回調並應用指針.
在C#中,首先先要定義一個類,用來把DLL中函數地址轉換成委托:
public class DLLWrapper { ///<summary> /// API LoadLibrary ///</summary> [DllImport("Kernel32")] public static extern int LoadLibrary(String funcname); ///<summary> /// API GetProcAddress ///</summary> [DllImport("Kernel32")] public static extern int GetProcAddress(int handle, String funcname); ///<summary> /// API FreeLibrary ///</summary> [DllImport("Kernel32")] public static extern int FreeLibrary(int handle); ///<summary> ///通過非托管函數名轉換為對應的委托, by jingzhongrong ///</summary> ///<param name="dllModule">Get DLL handle by LoadLibrary</param> ///<param name="functionName">Unmanaged function name</param> ///<param name="t">ManageR type對應的委托類型</param> ///<returns>委托實例,可強制轉換為適當的委托類型</returns> public static Delegate GetFunctionAddress(int dllModule, string functionName, Type t) { int address = GetProcAddress(dllModule, functionName); if (address == 0) return null; else return Marshal.GetDelegateForFunctionPointer(new IntPtr(address), t); } ///<summary> ///將表示函數地址的IntPtr實例轉換成對應的委托, by jingzhongrong ///</summary> public static Delegate GetDelegateFromIntPtr(IntPtr address, Type t) { if (address == IntPtr.Zero) return null; else return Marshal.GetDelegateForFunctionPointer(address, t); } ///<summary> ///將表示函數地址的int轉換成對應的委托,by jingzhongrong ///</summary> public static Delegate GetDelegateFromIntPtr(int address, Type t) { if (address == 0) return null; else return Marshal.GetDelegateForFunctionPointer(new IntPtr(address), t); } }
然后, 用delegate聲明函數:
delegate void _amDBRSetThermoModel(int mid, ref int errid);
再然后, 自己寫個private的函數封裝DLL中的函數, hModule()函數的作用是取得DLL的地址,用在多個輸出函數中
private int hModule() { int _hModule = DLLWrapper.LoadLibrary(DLLPATH); if (_hModule == 0) { return 0; } return _hModule; } private void amDBRInitialize() { try { _amDBRInitialize amf = (_amDBRInitialize)DLLWrapper.GetFunctionAddress(hModule(), "amDBRInitialize", typeof(_amDBRInitialize)); amf(); } catch (Exception e) { throw e; } }