Tuesday, 13 August 2013

C# Calling C function crash when using LoadLibrary/GetProcAddress

C# Calling C function crash when using LoadLibrary/GetProcAddress

I need to dynamically load DLL and invoke its methods
C code header:
__declspec(dllexport) int Init_Normalization_EN(char* path);
__declspec(dllexport) const char* Process_Normalization_EN(char* input);
C# code using [extern] to statically define library and methods:
[DllImport("TextNormalization_EN.dll", EntryPoint =
"?Init_Normalization_EN@@YAHPAD@Z", CallingConvention =
CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
public static extern int Init_Normalization_EN(IntPtr path);
[DllImport("TextNormalization_EN.dll", EntryPoint =
"?Process_Normalization_EN@@YAPBDPAD@Z", CallingConvention =
CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
public static extern IntPtr Process_Normalization_EN(IntPtr input);
When these declarations are used, interop works fine (for both init and
process of normalization), but I need to point to a DLL dynamically, so I
use the following code:
in the class-level:
[UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet =
CharSet.Unicode)]
private delegate int CallInit(IntPtr ipFolder);
private CallInit Init = null;
[UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet =
CharSet.Unicode)]
private delegate IntPtr CallNormalize(IntPtr ipInput);
private CallNormalize Normalize = null;
in the constructor:
IntPtr pDll = NativeMethods.LoadLibrary(libraryPath);
IntPtr pAddressOfInit = NativeMethods.GetProcAddress(pDll, InitName);
Init = (CallInit)Marshal.GetDelegateForFunctionPointer(pAddressOfInit,
typeof(CallInit));
IntPtr pAddressOfNormalize = NativeMethods.GetProcAddress(pDll,
NormalizeName);
Normalize = (CallNormalize)Marshal.GetDelegateForFunctionPointer(pDll,
typeof(CallNormalize));
IntPtr pFolder = Marshal.StringToCoTaskMemAnsi(dataFolderPath);
int result = this.Init(pFolder);
if (result != 0)
{
InitializeCompleted = true;
}
all this code runs OK and even the call to init the normalizer with a
folder-path works fine (returns a handle non-zero) but when I try to run
the text-normalizer:
IntPtr pInput = Marshal.StringToCoTaskMemAnsi(text);
IntPtr pResult = this.Normalize(pInput);
I get on the second line an application-level exception (that cannot be
caught by try/catch): "Attempted to read or write protected memory. This
is often an indication that other memory is corrupt."
Which is as far as I can understand caused by the returned string which I
try to get as IntPtr as in the [extern] declaration

No comments:

Post a Comment