我将完整地描述你的问题和过程。我正在为另一个游戏制作一个编辑器,我有一个用C语言编写的包装器DLL,我正在与之通信。
首先,我从DLL中获得了DllImport
调用函数的方法列表。第一种方法是CSharp_new_CEditorInterface
,它返回IntPtr
。然后CSharp_CEditorInterface_CreateApp
让ulong
处理窗口控制它将绘制图形的位置。最后,我应该致电CSharp_CEditorInterface_CloseApp
和CSharp_delete_CEditorInterface
。这些方法使用HandleRef
从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
。
这个解决方案工作正常,函数被称为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并不是为了一次加载多个而创建的。
有人可以帮帮我吗?
答案 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);