Who owns a global variable in a DLL? Careful now. In Win16 the answer is everybody. That's no surprise since everyone really uses the same memory anyway. For Win32, the answer isn't so clear cut. By default, if you use Borland's tools, the same thing happens. If three programs are using your DLL, they all see the same global variables. With Microsoft Visual C++, it is quite different. By default, a Microsoft DLL always gives each program a private copy of global variables. Consider this partial code from a DLL:
int threshold;
void set_thresh(int n) // export this function
{
threshold=n;
}
int get_thresh(void) // export this function
{
return threshold;
}
If three Win16 programs loaded this DLL and one of them set the threshold value, the other two would "see" the same value. Note that if the DLL unloads (no one is using it), the value isn't preserved.
If you compile the DLL with Borland's compiler, you'll get the same behavior (unless you specify MULTIPLE in the DEF file). With Microsoft, you'll have to do a bit of work to get the same effect.
Here's the plan:
Here's the same variable declaration with the sharing pragma:
#pragma data_seg(".ASHARE")
int threshold=0;
// more shared data could go here
#pragma data_seg()
IF YOU DON'T INITIALIZE THE VARIABLE, THINGS WON'T WORK!
The section name is special. It must be 8 characters or less and start with a period. Otherwise, it can be pretty much any legal identifier. Of course, you can't use ones the compiler already uses for something else (i.e., .CODE, .DATA, .BSS, etc.).
Next, you need a special option passed to the linker. You can set this in the project settings (exactly where depends on what version of VC++ you are using). The setting dialog doesn't have a special place for the option you need; you'll have to modify the command line (at the bottom of the dialog). If you can't change it, make sure you have either Debug or Release build selected, but not both. If both are selected, VC++ won't allow you to edit the command line. Here's what you need:
/SECTION:.ASHARE,RWS
Of course, if you called your section something else, use that instead of ASHARE. The RWS means, Read, Write, Shared. Shared is what gets us what we want.
If you prefer, you can create A DEF file and put a SECTIONS line in it:
LIBRARY DLL SECTIONS .ASHARE READ,WRITE,SHARED
If you use this method, be sure to add the DEF file to your project. MSVC doesn't use a DEF file by default.
If you want to share everything, just set the .DATA and .BSS sections to
shared using one of the above techniques (options or a DEF file).
That's it. Now you can share memory without the trouble of mapping files. You can also share memory in a way that is compatible between Win16 and Win32. One caution: under Windows NT, DLLs don't have to load at the same address for different processes. What this means is that you shouldn't take the address of a shared variable and pass it to another process. Specifically, don't put the address of a shared variable in a shared variable:
// Bad
#pragma data_seg(".ASHARE")
char buf[100]="";
char *bufp=&buf; // bad!
#pragma data_seg()
This works for Windows 95 - the DLL must load at the same address for each
process . (That's right! If you load a DLL, you reserve that space in ALL
processes.) In Windows NT it can (and probably will) fail.