加载多个DLL实例(c# /. net)

本文关键字:net 实例 DLL 加载 | 更新日期: 2023-09-27 18:08:59

我正在开发c#/。NET 3.5应用程序。我使用的是用C编写的遗留dll, signals.dll。我使用P/invoke从. net包装器调用它。我正在调用两种类型的处理函数,类型A和b。当我只调用一种类型的处理时,一切都很好。当我交替调用A和B处理时,数据结果被破坏。我相信dll, signals.dll使用了C风格的全局变量,数据会被损坏。

为了解决这个问题,我在磁盘上创建了两个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 dlhandle需要被愚弄到从内存中获取值,而不是从LoadLibrary。怎么做呢?

加载多个DLL实例(c# /. net)

LoadLibrary和LoadLibraryEx都需要文件路径。您将需要一个自定义加载过程,包括内存映射等。我发现了一篇博客文章("从内存加载DLL")描述了这个过程,以及一个匹配的GitHub项目;MemoryModule。

没有just:) -它要复杂得多,涉及

这里是一个链接,可能会有所帮助-从内存加载库/模块

正如@Hans Passant所说,我不鼓励你这样做——尽管在某些情况下这可能是一个诱人的解决方案(但我不认为你真的需要这样做,老实说,也许很好)。

它涉及到处理可移植的可执行格式——我怀疑这个项目涵盖了所有需要做的事情。

您可以尝试制作您的c++/CLI包装器-或导出MemoryLoadLibrary并尝试p/调用-但我怀疑这是否容易工作