I am looking for a way to coordinate DLLs in the same process, in order to provide a data sharing mechanism between them. The goal is to have the same sharing code for all DLLs, and to have them coordinate in such a way that the first one loaded by the main program will act as the manager for shared items, while the others will use this manager. I cannot modify the main application, so having that set up the manager and sharing its memory address with the other DLLs is not possible. The set of DLLs using this mechanism can vary, so I cannot assume explicitly that one of them will be loaded.
One solution I considered is to add the memory address to the environment variables of the process. The first DLL would see that the environment variable is not set yet, create the manager object and set the variable to its address. The other DLLs would see the variable and create a pointer to the manager object from that.
This comes close to what I want, but it seems a bit crude, since there is no guarantee that the environment variable isn’t set already for some reason, and SetEnvironmentVariable/GetEnvironmentVariable can fail for various reasons.
Is there a better way to handle this? I’m looking for a way to store and retreive a named pointer in the context of a process, but if you have a better solution for the underlying problem of getting the DLLs to cooperate I’d be happy to accept this as well.
Combine
GetModuleHandle()withGetProcAddress()to achieve this. The dependent DLLs will obtain the handle to the manager DLL, and then useGetProcAddress()to retrieve pointers from the symbols that it exports.Or just dynamically link the dependent DLLs against the manager DLLs and use a header file for the extern definitions.
I misread your question initially; however, the above approach can still be useful.
You can require that these DLLs all export an identical symbol that will point to some structure or function. Then, when one of the libraries is initialized, it can enumerate the loaded modules in the process and look for that symbol. If dereferencing the pointer returned by
GetProcAddress()returns a null pointer, then this module is the first one loaded and should create the required structure and set its own variable. Otherwise, it uses the value obtained from the pointer.This method is fraught with race-conditions though, if these modules can be initialized concurrently. You would be better off having a single supervisor module that each module can use as a communication point.