tags:

views:

158

answers:

2

Hi,

I have a 3rd party DLL that needs to be loaded dynamically using LoadLibrary() and which uses the __cdecl calling convention. I need to be able to use the dll from VB6 so I've created a wrapper DLL of my own that uses the __stdcall calling convention and exports the functions that are needed.

An additional requirement has now arrived and I am struggling to see how to manage; the wrapped DLL provides an API to another application and I need to connect to two instances of the application concurrently. This is a problem as the DLL has no concept of a session, a typical interaction would like like this:

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

and what i need to be able to do is

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

The main problem as I see it is that a single process can only be conected to one service, so the first solution I tried was to move the DLL wrapper out to a seperate process by creating an Out-Of-Process COM server using ATL. The problem I now have is that I only get a single instance of the COM sever.

So my questions (finally) are is there a way to force a new instance of the ATL COM server to be created? Is this the best approach to the problem or can someone think of a better way to tackle this.

Thanks Jackson

+1  A: 

if you only need 2 sessions you may be able to make a copy of the original dll and name it something else. they in your wrapper dll export two separate calls (one for each dll). so you'd have:

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

this might work depending on the specifics of the other application. worth a shot anyway.

-don

Don Dickinson
+4  A: 

I suggest that you dump the COM server idea and go with copies of the original DLL. I have used this approach myself to get multiple instances of libraries that aren't threadsafe and don't support multiple instances.

Since the files are different, Windows will load them all into separate address spaces and thus keep them separated for you.

This is what I did:

  • Add functions to the wrapper to create and destroy instances of the library.

  • Change all other functions to take a pointer to the instance of the library that it is using.

  • In the create instance function, first attempt to make a hard link to the original DLL using a random file name (i.e. use CreateHardLink). If that fails, then make a true copy of the DLL using a random name. You don't need to use the DLL extension if you don't want to. Dynamically load that copy of the DLL and function pointers and return a pointer to your internal structure.

  • In the destroy function, just unload the DLL and delete it.

  • Best to create the copy in the temporary directory so that it is obvious that it can be removed in event of a crash, although I am not sure if there are restrictions in Vista and later on loading DLLs from the temp dir.

This all works perfectly for me.

brofield
A quick test shows that this does seem to work. Thanks!
Jackson
Finished implementing the wrapper - I tried using CreateHardLink instead of a copy but it didn't work for me so went with a full copy of the DLL in the end.
Jackson
CreateHardLink only works when on an NTFS drive and the target is on the same partition as the source. In my wrapper, I first try CreateHardLink, since that will avoid a file copy and will be fast, however if that fails then I do the real copy. Glad it helped you.
brofield