C# 在动态加载的DLL库中返回字符串失败
我将完整地向您描述我的问题和过程。我正在为别人的游戏制作一个编辑器,我有一个用C语言编写的包装器DLL,我正在与之通信 起初,我有一个方法列表,使用C# 在动态加载的DLL库中返回字符串失败,c#,.net,interop,pinvoke,C#,.net,Interop,Pinvoke,我将完整地向您描述我的问题和过程。我正在为别人的游戏制作一个编辑器,我有一个用C语言编写的包装器DLL,我正在与之通信 起初,我有一个方法列表,使用DllImport从DLL调用函数。第一种方法是CSharp\u new\u ceditor接口,它返回一个IntPtr。然后CSharp\u ceditor interface\u CreateApp将ulong句柄设置为窗口控件,在该控件中绘制图形。最后,我应该调用CSharp\u CEditorInterface\u CloseApp和CSha
DllImport
从DLL调用函数。第一种方法是CSharp\u new\u ceditor接口
,它返回一个IntPtr
。然后CSharp\u ceditor interface\u CreateApp
将ulong
句柄设置为窗口控件,在该控件中绘制图形。最后,我应该调用CSharp\u CEditorInterface\u CloseApp
和CSharp\u delete\u CEditorInterface
。这些方法使用HandleRef
,指针从CSharp\u new\u ceditor接口返回
但是,我需要多次调用creating和deleting方法,第二次调用CSharp\u CEditorInterface\u CreateApp
时,它抛出了System.AccessViolationException
。所以我决定使用LoadLibrary和FreeLibrary动态加载和卸载DLL。我编写了一个应用程序,它通过反射浏览所有p/invoke方法,并生成由委托、只读字段和getproces地址组成的代码。然而,正如我发现的,入口点只是部分CSharp\u new\u ceditor接口
was\u CSharp\u new_CEditorInterface@0
。使用我的DLL导出查看器,我保存了所有完整的函数名,然后在其中搜索。在构造函数中,我调用LoadLibrary
并加载相应的函数。在Dispose
中,有freebrary
这个解决方案工作得很好,函数被称为OK,直到我发现一些返回字符串的函数抛出了AccessViolationException
。使用DllImport
方法时,它们工作正常。我还发现,当从静态类调用任何函数,从而加载另一个模块时,调用有问题的函数现在是可以的,它们返回适当的值。但是,在动态卸载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并不是为了一次加载多个而创建的
有人能帮帮我吗?试试这个我希望这个能帮到你
[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);
如果要首先调用函数,则必须创建与此函数匹配的delegate
然后使用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);
您能否展示一些您实际使用的真实代码,并指出您在代码中遇到问题的地方,这有点难/很难理解显示代码通常比sudo编码更容易为其他人提供帮助。。另外,看看Singleton和/或如何为运行Code的单个实例创建互斥,我想我已经描述了所需的一切。返回字符串的非托管方法在通过DllImport调用时工作正常,但在通过GetProcAddress的指针调用时失败。当使用DllImport加载指定的DLL时,该方法工作正常,直到卸载和重新加载。感谢您的努力,但我已经为函数提供了所有必要的委托。我还检查了句柄不是零。我敢肯定。其他函数以同样的方式加载。只是那些返回字符串的。也许马歇尔斯能解决这个问题?