3

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

ZivF
  • 125
  • 1
  • 8
  • 4
    CharSet.Unicode is wrong, it is Ansi. The first argument to GetDelegateForFunctionPointer must be the address of the function you obtained. – Hans Passant Aug 13 '13 at 11:56

1 Answers1

4

Shouldn't this line:

Normalize = (CallNormalize)Marshal.GetDelegateForFunctionPointer(
    pDll,
    typeof(CallNormalize));

be

Normalize = (CallNormalize)Marshal.GetDelegateForFunctionPointer(
    pAddressOfNormalize,
    typeof(CallNormalize));
Jim Mischel
  • 131,090
  • 20
  • 188
  • 351
  • WOW! It was a typo! I just don't beleive I spent a whole day trying to understand it – ZivF Aug 13 '13 at 12:07