如何在多线程环境中使用旧的单线程C++库

Cof*_*ars 4 c++ windows multithreading legacy-code

我有一个旧的C++库,专为在单线程环境中使用而设计.

该库公开了用于初始化的接口,这些接口改变了库的内部数据结构,以及用法,它只读取数据并进行计算.

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

假设重写dll以允许多线程将是禁止的,是否有一些方法让DLL的多个实例存在于同一进程中,具有单独的内存空间,或通过其他方式获得类似的结果?

Sha*_*fiz 6

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

一种可能的方法是创建单个实例并使用某种锁机制限制对它的访问.这可能会降低性能,具体取决于使用情况,但是如果不修改DLL的内部结构,则可能难以使用多个实例.

  • 我同意一般的想法,但要注意,如果dll使用线程本地存储,它仍然可能出错.由于它是专门设计的单线程,它不会故意使用TLS**,但它可能通过依赖项间接使用它.因此,如果您从一个线程设置,您可能会发现来自另一个线程的调用不起作用.下一级包装不仅仅是一个锁,创建一个线程,其唯一目的是管理这个dll,并通过向该线程发送消息并等待响应来访问所有dll的功能. (5认同)
  • @Coffee:啊,对不起,我没有正确地抓住,不仅dll不支持多个线程,它还有全局数据,实际上你想要特定于句柄.我敢肯定你可以通过强力克隆一个dll - 重命名它然后只通过LoadLibrary/GetProcAddress访问它,而不是通过链接.但这对于固定数量的副本来说真的很好,但是,我不确定您是否希望您的可执行文件在运行中为dll选择新名称.只要机器没有被锁定,但是明显是hacky,可能会工作. (2认同)

Dav*_*nan 6

在进程中连接到单个DLL的所有线程之间共享静态资源会在这里与您发生冲突.

但是,有一个技巧可以实现这一目标.只要DLL具有不同的名称,系统就会将它们视为不同,因此会创建单独的代码和数据实例.

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

  • 变体将是一个包装DLL,它暴露相同的接口,但使用线程本地存储将每个调用转发到DLL的每个线程副本.这隔离了包装器DLL中的所有技巧. (2认同)