如何使用旧的单线程C++;多线程环境中的库 我有一个旧的C++库,它是在单线程环境中使用的。

如何使用旧的单线程C++;多线程环境中的库 我有一个旧的C++库,它是在单线程环境中使用的。,c++,windows,multithreading,legacy-code,C++,Windows,Multithreading,Legacy Code,库公开了初始化接口(用于更改库的内部数据结构)和使用接口(用于仅读取数据和进行计算) 我的目标是在Windows多线程应用程序中使用这个库,不同的线程调用用不同数据初始化的dll实例 假设重写dll以允许多线程处理是禁止的,那么有没有办法让一个dll的多个实例存在于同一个进程中,使用单独的内存空间,或者通过其他方式获得类似的结果?如果dll包含静态资源,那么这些资源将在创建的所有实例之间共享 一种可能的方法是创建一个实例,并使用某种锁机制限制对它的访问。这可能会根据使用情况降低性能,但如果不修改

库公开了初始化接口(用于更改库的内部数据结构)和使用接口(用于仅读取数据和进行计算)

我的目标是在Windows多线程应用程序中使用这个库,不同的线程调用用不同数据初始化的dll实例


假设重写dll以允许多线程处理是禁止的,那么有没有办法让一个dll的多个实例存在于同一个进程中,使用单独的内存空间,或者通过其他方式获得类似的结果?

如果dll包含静态资源,那么这些资源将在创建的所有实例之间共享


一种可能的方法是创建一个实例,并使用某种锁机制限制对它的访问。这可能会根据使用情况降低性能,但如果不修改DLL的内部结构,则可能很难处理多个实例。

在一个进程内连接到单个DLL的所有线程之间共享静态资源,这会对您不利

然而,有一个技巧可以实现这一点。只要DLL有不同的名称,系统就会认为它们是不同的,从而创建代码和数据的独立实例


实现这一点的方法是,对于每个线程,将DLL复制到一个临时文件,并使用
LoadLibrary
从那里加载。您必须使用显式链接(
GetProcAddress
)而不是lib文件,但这确实是唯一的方法。

我同意一般的想法,但请注意,如果dll使用线程本地存储,它仍然可能出错。由于它是单线程设计的,所以不会故意使用TLS,但它可能通过依赖关系间接使用TLS。因此,如果从一个线程进行设置,您可能会发现来自另一个线程的调用不起作用。包装的下一个层次不是一个锁,而是创建一个线程,其唯一目的是管理此dll,并通过向此线程发送消息并等待响应来访问所有dll的功能。@Steve Jessop:这是我的第一个想法,但是在这种情况下,我一次只能用一组数据初始化dll:理想的解决方案是允许每个线程同时具有不同的初始化参数。@Coffee:啊,对不起,我没有正确地捕捉到这一点,不仅dll不支持多个线程,它还具有全局数据,实际上您希望这些数据是特定于句柄的。我相信你可以用蛮力克隆一个dll——重命名它,然后只通过LoadLibrary/GetProcAddress访问它,而不是通过链接。这只适用于固定数量的副本,但是,我不确定您是否希望您的可执行文件动态地为dll选择一个新名称。只要机器没有锁上,它就可以工作,但很明显有问题。@Coffee我不明白你为什么接受这个答案。它不能回答你的问题。我的答案和史蒂夫的评论(在我添加答案之前我没有读过)是你唯一的选择。我误解你的问题了吗?事实上,您是否只满足于一个DLL实例?另一种方法,根据您的喜好,可以少一些或多一些黑客行为,即创建一个处理DLL加载和I/O的可执行文件,并生成可执行文件的多个实例。另一种变体是公开相同接口的包装DLL,但它使用线程本地存储将每次调用转发到DLL的每个线程副本。这将隔离包装DLL中的所有欺骗。我发现的另一个想法可能很有趣,就是使用不同的AppDomain,为库的每个实例创建一个AppDomain,并将其加载到库中:AppDomain提供单独的内存空间,可以卸载,释放进程内存和加载的程序集。