包装第三方DLL

时间:2009-04-23 11:06:13

标签: c++ windows com atl

我有一个第三方DLL,需要使用LoadLibrary()动态加载,并使用__cdecl调用约定。我需要能够使用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)

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

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

谢谢杰克逊

2 个答案:

答案 0 :(得分:5)

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

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

这就是我所做的:

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

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

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

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

  • 最好在临时目录中创建副本,这样很明显可以在发生崩溃时删除它,虽然我不确定Vista中是否存在限制以及后来从temp加载DLL DIR。

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

答案 1 :(得分: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

这可能会起作用,具体取决于其他应用程序的细节。无论如何都值得一试。

-don