Shared Memory in DLL

Hi ppl!!
My problem is simple. I'm supposed to implement a counter that counts how applications/instances of applications are using my DLL.
I need the counter to be a shared variable. I am new to C++ and I tried out a few things without success.
Note:I'm using VC++ 2010 and my applications load the DLL with LoadLibrary() function.

Okay first I tried the #pragma data_seg directive. This is my DLL .cpp code.
__________________________________________________________________

#pragma data_seg(".myseg")
long Counter2=0;
#pragma data_seg()
#pragma comment(linker, "/section:.myseg,RWS")
EXPORT int Add(int a, int b)
{
return a+b;
}


EXPORT int ret()
{
return Counter2;
}


BOOL WINAPI DllMain(HINSTANCE hinstDLL, // DLL module handle
DWORD fdwReason, // reason called
LPVOID lpvReserved) // reserved
{

switch (fdwReason)
{
// DLL load due to process initialization or LoadLibrary

case DLL_PROCESS_ATTACH:InterlockedIncrement(&Counter2);

break;

// The attached process creates a new thread

case DLL_THREAD_ATTACH:
break;

// The thread of the attached process terminates

case DLL_THREAD_DETACH:
break;



case DLL_PROCESS_DETACH:
break;

default:
break;
}

return TRUE;
UNREFERENCED_PARAMETER(hinstDLL);
UNREFERENCED_PARAMETER(lpvReserved);
}

____________________________________________________________
the problem with this?

each time an application uses the DLL, Counter2 is initialized to 0. and so it never gets incremented!!!

So anyways, I tried this second implementation using memory mapped files, but ran into a problem again.

1. I used the CreateFileMapping() and MapViewOfFile()...but apparently you can only write WCHAR strings into MMF(mem mapped file)s. How do I put my integer counter in there?

2. How do I initialize the MMF? How will my DLL know if it's being used by the first application or the second or the third?

I am pasting my stupid DLL .cpp code that doesnt work, just in case that helps.

__________________________________________________________________________
#define SHMEMSIZE 30

using namespace std;
//char szname[]="FileMappingObject";
//WCHAR cBuf[30];
char dBuf[30];
static HANDLE hMapObject = CreateFileMapping(
INVALID_HANDLE_VALUE, // use paging file
NULL, // default security attributes
PAGE_READWRITE, // read/write access
0, // size: high 32-bits
SHMEMSIZE, // size: low 32-bits
TEXT("dllmemfilemap")); // name of map object


static LPVOID lpvMem = MapViewOfFile(
hMapObject, // object to map view of
FILE_MAP_WRITE, // read/write access
0, // high offset: map from
0, // low offset: beginning
0); // default: map entire file

VOID __cdecl SetSharedMem(char *lpszBuf)
{
char * lpszTmp;
DWORD dwCount=1;

// Get the address of the shared memory block

lpszTmp = (LPWSTR) lpvMem;

// Copy the null-terminated string into shared memory

while (*lpszBuf && dwCount<SHMEMSIZE)
{
*lpszTmp++ = *lpszBuf++;
dwCount++;
}
*lpszTmp = '\0';
}

VOID __cdecl GetSharedMem(char * lpszBuf, DWORD cchSize)
{
char* lpszTmp;

// Get the address of the shared memory block

lpszTmp = (char *) lpvMem;

// Copy from shared memory into the caller's buffer

while (*lpszTmp && --cchSize)
*lpszBuf++ = *lpszTmp++;
*lpszBuf = '\0';
}
// hMapFile = // name of mapping object


EXPORT int Add(int a, int b)
{
return a+b;
}


EXPORT char ret()
{
return dBuf[0];
}

LPCTSTR pBuf=(LPTSTR) MapViewOfFile(hMapObject, // handle to map object
FILE_MAP_ALL_ACCESS, // read/write permission
0,
0,
SHMEMSIZE);



BOOL WINAPI DllMain(HINSTANCE hinstDLL, // DLL module handle
DWORD fdwReason, // reason called
LPVOID lpvReserved) // reserved
{
//WCHAR c;

switch (fdwReason)
{
// DLL load due to process initialization or LoadLibrary

case DLL_PROCESS_ATTACH:
SetSharedMem("This is a test string");
// _getch();
GetSharedMem(dBuf, 30);

//wtoc(dBuf,cBuf);


break;

// The attached process creates a new thread

case DLL_THREAD_ATTACH:
break;

// The thread of the attached process terminates

case DLL_THREAD_DETACH:
break;



case DLL_PROCESS_DETACH:
break;

default:
break;
}

return TRUE;
UNREFERENCED_PARAMETER(hinstDLL);
UNREFERENCED_PARAMETER(lpvReserved);
}
__________________________________________________________________________

Any help will be greatly appreciated!! Thanks!!
what you need is a named resource. The slowest variant would be a file.

if you want to use memory mapping you need CreateFileMapping() and the corresponding OpenFileMapping(). See:

http://msdn.microsoft.com/en-us/library/windows/desktop/aa366791%28v=vs.85%29.aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/aa366551%28v=vs.85%29.aspx


I used the CreateFileMapping() and MapViewOfFile()...but apparently you can only write WCHAR strings into MMF(mem mapped file)s
No you can cast it to integer or whatever you want. The result of the mapping is a void *


Please use code tags: [code]Your code[/code]
See: http://www.cplusplus.com/articles/z13hAqkS/
Okay, but how do I initialize the file. If I write the initialization code in the .cpp file of my DLL, it will get initialized every time the DLL is used.
I don't know if I really understand what you mean.

Note this:
MSDN wrote:
Prefixing the file mapping object names with "Global\" allows processes to communicate with each other even if they are in different terminal server sessions.
CreateFileMapping() must fail if a process has already done it

The following code is for DLL_PROCESS_ATTACH:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
...
   hMapFile = CreateFileMapping(
                 INVALID_HANDLE_VALUE,    // use paging file
                 NULL,                    // default security
                 PAGE_READWRITE,          // read/write access
                 0,                       // maximum object size (high-order DWORD)
                 BUF_SIZE,                // maximum object size (low-order DWORD)
                 szName);                 // name of mapping object

   if (hMapFile == NULL)
   {
      _tprintf(TEXT("Could not create file mapping object (%d).\n"),
             GetLastError());

      hMapFile = OpenFileMapping(
                         FILE_MAP_ALL_ACCESS,   // read/write access
                         FALSE,                 // do not inherit the name
                         szName);               // name of mapping object

      if (hMapFile == NULL)
      {
            _tprintf(TEXT("Could not open file mapping object (%d).\n"),
                   GetLastError());
            return 1;
      }
   }
...

Convert the result of MapViewOfFile() to int *. So you can see what instance it is. Increase the value.

In DLL_PROCESS_DETACH you need to Decrease the value and close the handle.


Don't forget to UnmapViewOfFile() after you used the memory
Okay I'll try that. Thanks a ton! :)
If you just want to share a count, you can just use an atom, but you'd have to sync access with a mutex.
@coder777: Just 1 thing. I'll make this question as clear as possible. Suppose I have 2 apps loading my DLL- App1 and App2.
Suppose App1 is the first app that loads the Dll, so when it does tht, it has to initialize the memory mapped file.(with 0). How do I write a code such that it is initialized to 0 only when App1 loads it, and not everytime any app loads it. Basically, I want to make sure that if I write a code for initializing, it does not initialize everytime the DLL is loaded, but only when the first app loads it.
I hope I've made my question clear.
if you were able to CreateFileMapping (the result hMapFile != NULL) you know that you are the first and you need to initialize the memory.

There's a problem when two programs are starting at the same time. The second program may OpenFileMapping before you initialized it. To make it fool proof you need named mutex

kbw wrote:
you can just use an atom
how so?
Atoms are really old and go way back. Early WIN16 subsystems use them, like the clipboard and DDE. There's some blurb on Atoms here: http://msdn.microsoft.com/en-us/library/windows/desktop/ms649053%28v=vs.85%29.aspx

Atoms are global values, strings or numbers, that exist in the system. They can be accessed by all apps.
Topic archived. No new replies allowed.