0

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

起初我有DllImport从 DLL 调用函数的方法列表。第一种方法是CSharp_new_CEditorInterface返回一个IntPtr. 然后CSharp_CEditorInterface_CreateApp哪个tokeulong句柄到窗口控制它将在哪里绘制图形。最后我应该调用CSharp_CEditorInterface_CloseAppand CSharp_delete_CEditorInterface。这些方法采用HandleRef从返回的 with 指针CSharp_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

该解决方案运行良好,函数调用正常,直到我发现一些返回字符串的函数正在抛出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 不是为了一次加载多个而创建的。

有人可以帮我吗?

4

1 回答 1

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);
于 2012-08-13T11:04:31.653 回答