1

我有一个需要使用 LoadLibrary() 动态加载并使用 __cdecl 调用约定的第 3 方 DLL。我需要能够使用 VB6 中的 dll,所以我创建了自己的包装 DLL,它使用 __stdcall 调用约定并导出所需的函数。

现在已经有一个额外的要求,我正在努力寻找如何管理;包装的 DLL 为另一个应用程序提供了一个 API,我需要同时连接到应用程序的两个实例。这是一个问题,因为 DLL 没有会话的概念,典型的交互如下所示:

tpc_connect("service1")
// Do some stuff
tpc_disconnect()

我需要做的是

session1 = tpc_connect("service1")
session2 = tpc_connect("service2")
// Do some stuff with session1
// Do some stuff with session2
tpc_disconnect(session1)
tpc_disconnect(session2)

我看到的主要问题是单个进程只能连接到一个服务,所以我尝试的第一个解决方案是通过使用 ATL 创建一个进程外 COM 服务器来将 DLL 包装器移到一个单独的进程中。我现在遇到的问题是我只获得了一个 COM 服务器实例。

所以我的问题(最后)是否有办法强制创建 ATL COM 服务器的新实例?这是解决问题的最佳方法还是有人能想到更好的方法来解决这个问题。

谢谢杰克逊

4

2 回答 2

5

我建议您放弃 COM 服务器的想法并使用原始 DLL 的副本。我自己使用这种方法来获取不是线程安全且不支持多个实例的库的多个实例。

由于文件不同,Windows 会将它们全部加载到单独的地址空间中,从而为您将它们分开。

这就是我所做的:

  • 向包装器添加函数以创建和销毁库的实例。

  • 更改所有其他函数以获取指向它正在使用的库实例的指针。

  • 在创建实例函数中,首先尝试使用随机文件名创建到原始 DLL 的硬链接(即使用CreateHardLink)。如果失败,则使用随机名称制作 DLL 的真实副本。如果您不想,则不需要使用 DLL 扩展。动态加载 DLL 和函数指针的副本,并返回指向内部结构的指针。

  • 在destroy函数中,只需卸载DLL并删除即可。

  • 最好在临时目录中创建副本,以便在发生崩溃时很明显可以将其删除,尽管我不确定 Vista 中是否存在限制以及稍后从临时目录加载 DLL。

这一切对我来说都很完美。

于 2009-04-23T13:12:30.613 回答
1

如果您只需要 2 个会话,您可以制作原始 dll 的副本并将其命名为其他名称。它们在您的包装器 dll 中导出两个单独的调用(每个 dll 一个)。所以你会有:

session1 = tcp_connect("whatever")      'this points to dll1.dll
session2 = tcp_connect2("whatever")     'this points to a copy of dll1 called dll2.dll

这可能取决于其他应用程序的具体情况。无论如何都值得一试。

-大学教师

于 2009-04-23T12:17:33.477 回答