Hi all,
I'm trying to dynamically call unmanaged C++ Dll from within my Web API. For this reason, I created 2 Controller Action:
(1) One is starting the dll: It uses the LoadLibrary to load the dll, and call an init-method in the dll, initializing some parameters for calculation.
(2) Here's is were I need the calculation result from my Dll (using the handle from LoadLibrary in Action 1, I use GetProcAdress to locate the function and create the delegate).
It seems to work fine, but when calling it multiple times, it hangs up - and this very sporadically and unpredictable. When I pause the debugging with Visual Studio, it is paused at my delegate-call for the function...
Can someone please help me?
Here's my code:
[DllImport("kernel32.dll", SetLastError = true)] private static extern IntPtr LoadLibrary(string dllToLoad); [DllImport("kernel32.dll", SetLastError = true)] private static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate bool DllTransfer(ref WebCalcInfo Info); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate bool InitDll([MarshalAs(UnmanagedType.LPStr)]string pExternPath); //This method is called in 1. Action public static bool LoadInitLibrary(string path) { if (!IsLoaded) { PATH = path; if (!Directory.Exists(PATH) && !File.Exists(PATH_DLL)) throw new Exception(string.Format("Dll not found: {0}.", PATH_DLL)); //LoadLibrary hModule = DllInterop.LoadLibrary(PATH_DLL); IsLoaded = (hModule != IntPtr.Zero); if (!IsLoaded) { int errno = Marshal.GetLastWin32Error(); throw new Exception(string.Format("Failed to load library. Error:{0}.", errno)); } //GetPointer: PROC_InitDll IntPtr intPtrInitDll = DllInterop.GetProcAddress(hModule, PROC_InitDll); if (intPtrInitDll == IntPtr.Zero) { int errno = Marshal.GetLastWin32Error(); FreeLibrary(); throw new Exception(string.Format("Process Address not found: PROC_InitDll is IntPtr.Zero. Error:{0}.", errno)); } DllInterop.InitDll initDll = (DllInterop.InitDll)Marshal.GetDelegateForFunctionPointer(intPtrInitDll, typeof(DllInterop.InitDll)); //InitDLL IsInitialized = initDll(string.Format("P={0}", PATH)); if (!IsInitialized) { FreeLibrary(); throw new Exception("PROC_InitDll returned FALSE."); } return true; } return false; } //This method is for the 2.Action public static CalcInfo TransferData(WebCalcInfo calcInfo) { if (!IsLoaded && !string.IsNullOrEmpty(PATH)) { System.Diagnostics.Trace.WriteLine("Library was not loaded, start loading and init Dll.", "TransferData"); LoadInitLibrary(PATH); } IntPtr intPtrTransfer = DllInterop.GetProcAddress(DllInterop.hModule, PROC_DllTransfer); if (intPtrTransfer == IntPtr.Zero) { int errno = Marshal.GetLastWin32Error(); FreeLibrary(); throw new Exception(string.Format("Process Address not found: PROC_DllTransfer is IntPtr.Zero. Error:{0}.", errno)); } DllInterop.DllTransfer dllTransfer = (DllInterop.DllTransfer)Marshal.GetDelegateForFunctionPointer(intPtrTransfer, typeof(DllInterop.DllTransfer)); bool transferResult = dllTransfer(ref Info); // HERE IT HANGS if (!transferResult) { FreeLibrary(); throw new Exception("PROC_DllTransfer returned FALSE."); } }