我需要动态加载DLL并调用其方法
C代码标题:
__declspec(dllexport) int Init_Normalization_EN(char* path);
__declspec(dllexport) const char* Process_Normalization_EN(char* input);
使用[extern]静态定义库和方法的C#代码:
[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);
当使用这些声明时,interop工作正常(对于初始化和规范化过程),但我需要动态指向DLL,所以我使用以下代码:
在班级:
[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;
在构造函数中:
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;
}
所有这些代码运行正常甚至调用init文件夹路径的规范化工具正常工作(返回句柄非零) 但 当我尝试运行text-normalizer时:
IntPtr pInput = Marshal.StringToCoTaskMemAnsi(text);
IntPtr pResult = this.Normalize(pInput);
我在第二行遇到了应用程序级异常(try / catch无法捕获): “试图读取或写入受保护的内存。这通常表明其他内存已损坏。”
据我所知,返回的字符串是我尝试获取的IntPtr,如[extern]声明中那样
答案 0 :(得分:3)
不应该这一行:
Normalize = (CallNormalize)Marshal.GetDelegateForFunctionPointer(
pDll,
typeof(CallNormalize));
是
Normalize = (CallNormalize)Marshal.GetDelegateForFunctionPointer(
pAddressOfNormalize,
typeof(CallNormalize));