Cheok Yan Cheng
Cheok Yan Cheng

Reputation: 42690

Having multiple instance of global variables from same DLL

Currently, I have a system with the following simplified view.

The entire system run under single process
------------------------------------------
       --- DLL0.DLL --- COMMON.DLL (contains global_variable in COMMON.DLL)
EXE ---|
       --- DLL1.DLL --- COMMON.DLL (contains global_variable in COMMON.DLL)

The source code for COMMON.DLL is as follow.

// COMMON.DLL
#ifdef COMMON_EXPORTS
_declspec( dllexport ) int global_variable = 100;
// Function used to access and print global_variable.
__declspec(dllexport) void common_fun_which_access_global_variable();
#else
_declspec(dllimport) int global_variable;
__declspec(dllimport) void common_fun_which_access_global_variable();
#endif

The source code for DLL0.DLL is as follow.

__declspec(dllexport)
void DLL0() {
    printf ("This is DLL0\n");
    printf ("In DLL0, global_variable is %i\n", global_variable);
    common_fun_which_access_global_variable();
    global_variable = 200;
    printf ("DLL0 is now setting global_variable to 200\n");
    common_fun_which_access_global_variable();
}

The source for for DLL1.DLL is as follow.

__declspec(dllexport)
void DLL1() {
    printf ("This is DLL1\n");
    printf ("In DLL1, global_variable is %i\n", global_variable);
    common_fun_which_access_global_variable();
    global_variable = 400;
    printf ("DLL1 is now setting global_variable to 400\n");
    common_fun_which_access_global_variable();
}

The source code for EXE is as follow.

HINSTANCE instance0 = AfxLoadLibrary(_T("DLL0.dll"));
FARPROC fun0 = GetProcAddress(instance0, "DLL0");
HINSTANCE instance1 = AfxLoadLibrary(_T("DLL1.dll"));
FARPROC fun1 = GetProcAddress(instance1, "DLL1");
_fun0();
_fun1();

The output is as follow.

This is DLL0
In DLL0, global_variable is 100
In COMMON, global_varialbe is 100
DLL0 is now setting global_variable to 200
In COMMON, global_varialbe is 200

This is DLL1
In DLL1, global_variable is 200    <-- I wish 100 is being printed.
In COMMON, global_varialbe is 200  <-- I wish 100 is being printed here too.
                                   <-- I wish DLL0 and DLL1 have their own instance of
                                   <-- global_variable respectively.
DLL1 is now setting global_variable to 400
In COMMON, global_varialbe is 400

The entire system is executed within a single process. Although DLL0.DLL and DLL1.DLL are being loaded explicitly each, the dependency COMMON.DLL will only be loaded once in entire application life cycle. EXE will not load same COMMON.DLL twice.

Is there any way, I can achieve the following without violating one of the rules?

  1. DLL0 and DLL1 can have their own instance of global_variable?
  2. global_variable must be global, and re-inside COMMON.DLL?
  3. COMMON.DLL will be loaded through implicit linking using LIB file.
  4. No renaming COMMON.DLL to COMMON-DLL0.DLL and COMMON-DLL1.DLL.
  5. No static linking.
  6. If DLL0 change the value of global_variable, calling common_fun_which_access_global_variable from DLL0 should access to DLL0's changed value. However, calling common_fun_which_access_global_variable from DLL1 shouldn't realize the changes.

** I know this is too much. But I am now dealing with a legacy code. You know :)

Will side-by-side assembly able to solve this kind of problem? What I understand is that, side-by-side assembly is used to solve multiple DLL with same name but different version issues. I am not sure whether it is applicable in my above case?

Or, should I ask the other way around? How can we have 2 instance of COMMON.DLL being loaded within a same EXE?

Upvotes: 1

Views: 2654

Answers (3)

btsimonh
btsimonh

Reputation: 1

I had this exact issue, where I had no control over 3rd party DLL0, DLL1 or COMMON.

The solution I created was to duplicate COMMON with different names, and to patch DLL0 and DLL1 to load their own copies.

(in my case, I had to run many copies of the 'DLL0' level, so wrote a program which duplicated the 'DLL0' and 'COMMON' for each instance I needed, then patched the 'DLL0' copies for the new name of COMMON. The new names had to be the same length as the original, and from memory it was just a search and replace of the specific name text, although from memory there were ANSI and WIDE varieties. Of course this approach may no longer work if the DLLs are signed?)

Upvotes: 0

SpeedBump
SpeedBump

Reputation: 11

Since DLLs have a single, consistent image per process the only way I can see to do what you are asking for is to move COMMON.dll into a unique process per use. That could be done in a variety of ways, depending on what code you have access to, and your tolerance for ugliness.

Can your DLL0 and DLL1 be rewritten to interact with your COMMON.dll via a wrapper? If so have the wrapper spawn a separate process to interact with the common.dll. The wrapper then uses some form of IPC (shared memory perhaps) to communicate with the worker process.

Of course, this is far more complicated that just copying the common.dll to a new name...are you sure it's worth the pain?

Upvotes: 1

skimobear
skimobear

Reputation: 1198

If I understand the situation correctly, COMMON.dll is the legacy code and the legacy code is used by both DLL0.dll and DLL1.dll.

Without knowing all the details I would suggest the following:

1) Create a global variable in DLL0.dll and DLL1.dll.
2) Initialize each global variable from step 1 with COMMON.dll's global_variable value.
3) Use the two new global_variables as needed.

Upvotes: 2

Related Questions