我正在开发C#/ .NET 3.5应用程序。我正在使用C,signals.dll编写的遗留DLL。我使用P / Invoke从.NET包装器调用它。我正在调用两种类型的处理函数,类型A和B.当我只调用一种类型的处理时,一切正常。当我将呼叫交错到A和B处理时,数据结果被破坏。我相信dll,signals.dll正在使用C风格的全局变量,并且数据被破坏。
为了解决这个问题,我在磁盘上创建了2个dll副本,signals.dll和signals2.dll。然后我使用P / Invoke修改了.NET包装器,将A类处理引导到一个dll,将B类处理引导到另一个实例。现在,一切正常。
然后我在论坛和解决方案上看到了类似的问题。 (Supporting multiple instances of a plugin DLL with global data)。 基本上,提出的解决方案是从代码动态布局,在磁盘上创建.dll的新实例(基于需要),并加载它并从中调用函数。代码的关键部分如下所示:
private IntPtr dllHandle;
string myDllPath = Path.Combine(dllDir, String.Format("mylib-{0}.dll", GetHashCode()));
File.Copy(origDllPath, myDllPath);
dllPath = myDllPath;
dllHandle = LoadLibrary(dllPath);
_getVersion = GetProcEntryDelegate<_getVersionDelegate>(dllHandle, "GetVersion");
private delegate int _getVersionDelegate();
private readonly _getVersionDelegate _getVersion;
public int GetVersion()
{
return _getVersion();
}
private static D GetProcEntryDelegate<D>(IntPtr hModule, string name)
where D: class
{
IntPtr addr = _getProcAddress(hModule, name);
if (addr == IntPtr.Zero)
throw new Win32Exception();
return Marshal.GetDelegateForFunctionPointer(addr, typeof(D)) as D;
}
我想到了什么,是否可以修改上面的代码来创建dll IN MEMORY的副本,而不是在磁盘上并从那里加载它。我认为IntPtr dllHandle需要被愚弄从内存中获取价值,而不是来自LoadLibrary。怎么做?
答案 0 :(得分:1)
LoadLibrary和LoadLibraryEx都需要文件路径。您需要一个自定义加载过程,包括内存映射和什么不是。我找到了一个描述过程的blog post ("Loading a DLL from memory")和一个匹配的GitHub项目; MemoryModule。
答案 1 :(得分:1)
关于它没有just
:) - 它更复杂,涉及
这是一个可能有用的链接 - Load Library/Module from Memory
正如@Hans Passant说的那样,我不鼓励你这样做 - 即使它可能是某些场景的诱人解决方案(但我没有看到你真的需要那个老实说,好吧也许)。
它涉及处理portable executable format - 我怀疑该项目涵盖了所有需要完成的工作。
您可以尝试制作C ++ / CLI包装器 - 或导出MemoryLoadLibrary
并尝试P / Invoking - 但我怀疑它是否能够轻松工作。