在动态加载的DLL库中返回字符串失败

时间:2012-08-11 15:59:10

标签: c# .net interop pinvoke

我将完整地描述你的问题和过程。我正在为另一个游戏制作一个编辑器,我有一个用C语言编写的包装器DLL,我正在与之通信。

首先,我从DLL中获得了DllImport调用函数的方法列表。第一种方法是CSharp_new_CEditorInterface,它返回IntPtr。然后CSharp_CEditorInterface_CreateAppulong处理窗口控制它将绘制图形的位置。最后,我应该致电CSharp_CEditorInterface_CloseAppCSharp_delete_CEditorInterface。这些方法使用HandleRefCSharp_new_CEditorInterface返回指针。

但是,我需要多次调用创建和删除方法,并且第二次调用CSharp_CEditorInterface_CreateApp时,它会抛出System.AccessViolationException。所以我决定使用LoadLibrary和FreeLibrary动态加载和卸载DLL。我编写了一个应用程序,通过反射浏览所有p / invoke方法并生成由委托,只读字段和GetProcAddress-es组成的代码。但是,正如我发现的那样,切入点只是部分的。 CSharp_new_CEditorInterface_CSharp_new_CEditorInterface@0。使用我的DLL导出查看器,我保存了所有完整的函数名称,然后在其中搜索。在构造函数中,我调用LoadLibrary和适当的函数加载。在Dispose中,有FreeLibrary

这个解决方案工作正常,函数被称为OK,直到我发现一些返回字符串的函数正在抛出AccessViolationException。使用DllImport方法时,它们可以正常工作。我还发现,当从静态类调用ANY函数时,因此加载另一个模块,调用有问题的函数现在可以,它们返回适当的值。但是,在动态卸载DLL并重新加载之后,它再次无效并猜测抛出了哪个异常。

现在我调用哪个函数以及按什么顺序:

--When initializing--
LoadLibrary(string)  (winapi)
--bunch of GetProcAddress, Marshal.GetDelegateForFunctionPointer--
new_CEditorInterface()  (from DLL)
CreateApp(HandleRef, ulong)  (from DLL)

--When closing in Dispose--
CloseApp(HandleRef)  (from DLL)
delete_CEditorInterface(HandleRef)  (from DLL)
FreeLibrary(IntPtr)  (winapi)

我应该注意,DLL并不是为了一次加载多个而创建的。

有人可以帮帮我吗?

1 个答案:

答案 0 :(得分:0)

试试这个我希望这可以帮助你

[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr LoadLibrary(string libname);

[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
private static extern bool FreeLibrary(IntPtr hModule);

//Load
IntPtr Handle = LoadLibrary(fileName);
if (Handle == IntPtr.Zero)
{
     int errorCode = Marshal.GetLastWin32Error();
     throw new Exception(string.Format("Failed to load library (ErrorCode: {0})",errorCode));
}

//Free
if(Handle != IntPtr.Zero)
        FreeLibrary(Handle);

如果要首先调用函数,则必须创建与此函数匹配的删除 然后使用WinApi GetProcAddress

[DllImport("kernel32.dll", CharSet = CharSet.Ansi)]
private static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName); 


IntPtr funcaddr = GetProcAddress(Handle,functionName);
YourFunctionDelegate function = Marshal.GetDelegateForFunctionPointer(funcaddr,typeof(YourFunctionDelegate )) as YourFunctionDelegate ;
function.Invoke(pass here your parameters);