Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 860
ZivF Avatar asked Jul 15 '26 13:07

ZivF


1 Answers

Shouldn't this line:

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

be

Normalize = (CallNormalize)Marshal.GetDelegateForFunctionPointer(
    pAddressOfNormalize,
    typeof(CallNormalize));
like image 55
Jim Mischel Avatar answered Jul 20 '26 10:07

Jim Mischel



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!