views:

1150

answers:

8

Hi,

I am busy coding a dll that supplies several functions to a host application. This application calls the dll dynamically, loading and freeing it after every function call.

I have no control over the host app. I can only work with within the dll. Is there a way I can keep certain variables in memory so that I can reuse them within each function? Obviously a global varable gets cleared when the dll is unloaded by the host app. Saving the dll to file sounds very messy!

Can anyone suggest a way of assigning a variable that i can keep global?

Thanks

+1  A: 

The best way is to use a class containing the "globals". You instantiate an object and give it as parameter to the dll functions. But that won't help you because you are not able to change the calling app.

If you have to keep the global data in the dll, a solution is to write them to a file. But this has serious impact to the performance.

Gamecat
A: 

If I was you I'd save the values of those global vars into a when file the dll is freed and load them when it is initialized. I so no reason to save the memory dump of the dll on the disk.

Aldo
+4  A: 

Warning, dirty hack:

You could load yourself.

Every call to LoadLibrary increments a reference counter, FreeLibrary decrements it. Only if the counter reaches zero, the DLL is unloaded.

So if the first time your DLL gets loaded, you just load your library again, thus incrementing the reference counter. If the calling application calls FreeLibrary the reference counter gets decremented, but the DLL doesn't get unloaded.

EDIT: As mghi pointed out, the DLL will be unloaded if the process terminates, whether the reference count is zero or not.

DR
Yes, but then again this method adds lots of mess on when to decide the time the dll should really unload itself, because It won't need to run all the time. The dll then should check if the host app still exists periodically, which I don't really like, but that's just me.
Aldo
@Aldo: Not true - if only one process uses the DLL it will be unloaded once that process exits, whether the reference count has reached 0 or not.
mghie
+3  A: 

I think you have 2 main options here.

  1. offer 2 versions of your function, the one you have now, plus another where they pass in a buffer (record, whatever) that you can read previous state from, and of course update the state into. Call this the high perf version of the function. They will want to use it.

  2. Save the state like you would a cookie (thats basically what it is) in a file somewhere.

Option 1 would require modification to the host app, but would be compelling for the host app developers to take advantage of, Option 2 would require no changes to the host app, but would not be as performant.

I would not personally be inclined to start mucking about with the reference count, presumably the host app is unloading for a reason, if I was the host app dev, that would annoy me.

Tim Jarvis
thanks - i think this is the best bet.I'd rather save to file and take a performance hit than risk than fiddling with dll references. Maybe the host app developers will go for a high performance version going forward
Crudler
+2  A: 

Another solution, if you have a large amount of global data to share, would be to create a windows service to "cache" the state data. You would also need to implement some sort of IPC that works across the process boundary, such as memory mapped files, mailboxes, COM (single instance for this case), TCP/IP ect. You may find that this overhead would be more than just writing the state to a file, which is why I would only recommend this approach if the amount of state data is excessive, or will only be dealt with in parts of the whole for each request into your dll.

For the COM approach, the service doesn't have to do much other than request (and hold onto) an instance of the com object you will be using to maintain state. Since it is a single instance com object, all requests will be to the same instance, thus allowing you to save your state between requests. Requests to the object are serialized, so this could be a performance issue if you have multiple clients requesting data on the same machine at the same time.

skamradt
To advance this idea, you could make the DLL a very thin layer that re-directs the call to the service. The meat of the work can be done in the service and it can maintain state. An added advantage of this would be the size of the DLL would be reduced and speed up the time it takes to load the DLL ( which you say the app does on every single function call ).
Kieveli
@Kieveli - Good point, but still some sort of IPC needs to be established. Com (single instance) would be a simple solution, and in that case the service can still do nothing but request and hold onto a reference to persist the object.
skamradt
this one will probably be the most fun! But i reckon i'll just stick with file, as u say, the overhead will probably be more, and there is just more ris for something to go wrond. Thanks tho
Crudler
A: 

Write the values to the Registry when the DLL is freed, and read the values from the Registry when the DLL is loaded. Don't forget to provide a default when the read discovers that a key has not been set.

-Al.

A. I. Breveleri
A: 

I agree with the previous comments about global state information being dangerous, although I can imagine it might be needed.

I propose a cleaner version of DR's dirty hack that doesn't have the downside of being permanent like skamradt's answer:

A very small app:

It has no appearance whatsoever, it keeps itself from showing on the taskbar.

Task #1: Load the DLL

Task #2: Take it's command line, run it and wait for it to terminate.

Task #3: Unload the DLL

Task #4: Exit.

The installer:

It finds the shortcut(s) to the main app and modifies them so the small app runs, the original location the shortcut pointed to becomes the first parameter.

Results: The DLL remains in memory only so long as the main app is running but it does not get unloaded every time the program dumps it.

Loren Pechtel
A: 

I'm late to this party, but maybe it'll be useful for somebody else. option 1: Create a shared memory area that holds your variables backed by paging file - if you're able to open that shared memory area, your dll was previously loaded (assuming "private" shared memory name, maybe named something like process_id_yourdllname) - if you can't open it, then you create and initialize it the first time. If you create it, then you don't bother deleting it - but if you open it, you would close it - when unloading. I believe the area will be released when the application closes, as no other applications should have handles to this particular "private" shared memory area.

option 2: Create a second .dll that exists just for the purpose of managing your global variables. Your dll A can load that dll B, and not free it, placing in dll B whatever you need to manage the global variables. It should go away when the application goes away, and I don't think you probably need to care about the (presumably useless) reference counting involved (since you wouldn't be unloading dll B).

contributor