我正在开发 C#/.NET 3.5 应用程序。我正在使用用 C 编写的旧版 dll,signals.dll。我使用 P/Invoke 从 .NET 包装器中调用它。我正在调用 2 种类型的处理函数,类型 A 和 B。当我只调用一种类型的处理时,一切正常。当我交错调用 A 和 B 处理时,数据结果已损坏。我相信 dll、signals.dll 正在使用 C 风格的全局变量,并且数据被破坏了。
为了解决这个问题,我在磁盘上创建了 2 个 dll 副本,signals.dll 和 signals2.dll。然后我使用 P/Invoke 修改了 .NET 包装器,将 A 类处理定向到一个 dll,将 B 类处理定向到另一个实例。现在,一切正常。
然后我在论坛和那里的解决方案上看到了类似的问题。(支持具有全局数据的插件 DLL 的多个实例)。基本上,该提议的解决方案是从代码动态放置,在磁盘上创建一个新的 .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 的副本,而不是在磁盘上并从那里加载它。我认为只是需要欺骗 IntPtr dllHandle 从内存中获取价值,而不是从 LoadLibrary 中获取价值。怎么做?