?
Solved

DLL shared variables problem

Posted on 2003-03-03
11
Medium Priority
?
267 Views
Last Modified: 2013-11-20
I have writen a DLL which is used by several different apps

There are 2 global variables (called started and currentLoggedLevel) that I want to be shared so that if one app makes started=TRUE, every other app sees started as true.
The way I have tried to go about this is to declared the variables as follows:



#pragma data_seg (".shared")
   
     bool started = false;
     int currentLoggedLevel = -1;

#pragma data_seg()


and then to include the following in my .DEF file

SECTIONS
.shared READ WRITE SHARED;



This does not seem to work, and if one application makes started=TRUE, the others still see it as false.

My question is should this technique work i.e. have I got the right idea but have probably done something wrong somewhere else (if not, what technique could I use to achieve this "shared" behaviour ?).


0
Comment
Question by:tpemckiernan
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
11 Comments
 
LVL 1

Expert Comment

by:vadik
ID: 8063680
This is my dll without a *.def file. This is working correct.

#include "stdafx.h"
#include "shr.h"

#include <stdlib.h>
#include <tchar.h>



#pragma data_seg (".shared")
 
    bool started = false;
    int currentLoggedLevel = -1;

#pragma data_seg()

#pragma comment(linker, "/SECTION:.shared,RWS")



BOOL APIENTRY DllMain( HANDLE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                          )
{
    switch (ul_reason_for_call)
     {
          case DLL_PROCESS_ATTACH:
               if (started)
               {
                    TCHAR buf[10];

                    _itot(currentLoggedLevel++, &buf[0], 10);

                    MessageBox(0, TEXT("started"), &buf[0], MB_OK);
                   
               }
               else
               {
                    MessageBox(0, TEXT("not started"), TEXT("not started"), MB_OK);
                    started = true;
                    currentLoggedLevel++;
               }

          case DLL_THREAD_ATTACH:
          case DLL_THREAD_DETACH:
          case DLL_PROCESS_DETACH:
               break;
    }
    return TRUE;
}
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 8095031
tpemckiernan,
Did that work for you?  If that did not work, try:

    static bool started = false;
    static int currentLoggedLevel = -1;

Please reply to all comments.  Thanks for maintaining your open questions!
-- Dan
0
 

Author Comment

by:tpemckiernan
ID: 8099119
Thanks for your suggestions.

declaring the variables as static didn't seem to help

However, the linker comment did seem to help - when apps call the DLL they can read the correct values. However, other DLLS don't read the correct values - any idea why this might be ?
0
Moving data to the cloud? Find out if you’re ready

Before moving to the cloud, it is important to carefully define your db needs, plan for the migration & understand prod. environment. This wp explains how to define what you need from a cloud provider, plan for the migration & what putting a cloud solution into practice entails.

 
LVL 1

Expert Comment

by:vadik
ID: 8099175
What do you means "However, other DLLS don't read the correct values - any idea why this might be "??
DLL's in other processes? Sorry for my English...
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 8099539
>>what technique could I use to achieve this "shared" behaviour

A very simple technique is to create a global MUTEX.

#define strMutexName "MyAppsDllIsWorking"

HANDLE hMutex;
DWORD  dwLastError;

hMutex= CreateMutex(NULL, FALSE, strMutexName);
dwLastError= GetLastError();
if (hMutex==0) {
    // some screball erro, probaly strMutexName has slashes or something
}

if ( dwLastError == ERROR_ALREADY_EXISTS ) {
    // the DLL is already running or whatever
}

.... later....
CloseHandle( hMutex );

=-=-=-=-=-=-=-=-=-=-=-=-
I'm not sure exactly what you are going for, but here is how this works... see if it will do the trick for you:

Whenever any program or DLL or anything executes that CreateMutex API call with the sanem name, the first time it is called, you will get a handle return and no error.  But the next time it is called, you will get

  dwLastError == ERROR_ALREADY_EXISTS

so, you know that some other process called it first.  So the combination of CreateMutex and GetLastError makes for a one-shot 'gateway'.

Mutexes are more often used in synchronzing threads and processes via fns like WaitForSingleObject (and other complicated stuff), but they can also be used in a simpler fashion as shown.

If you are writing in C++, I can give you a tight little class call CLimitSingleInstance that uses this techique to prevent a user from running a second copy of my program and instead I can display the first one (it's probably forgotton on the taskbar).

-- Dan
0
 
LVL 1

Expert Comment

by:keitha1
ID: 8134832
As far as I know, the simplest way to share memory between processes is by using memory-mapped files.
0
 
LVL 1

Expert Comment

by:vadik
ID: 8135120
I don't think so because it's very expensive solution for  two variables only...
0
 
LVL 49

Accepted Solution

by:
DanRollins earned 400 total points
ID: 8142075
This was hard to track down -- I know the technique works since I've used it in hook DLLs, but when I tried, it kept failing!

A clue: Dunpbin did not even display the .shared section!

Here it is:
      HOWTO: Share Data Between Different Mappings of a DLL
      http://support.microsoft.com/default.aspx?scid=kb%3Ben-us%3B125677
and
      http://msdn.microsoft.com/library/en-us/vccore/html/_core_How_do_I_share_data_in_my_DLL_with_an_application_or_with_other_DLLs.3f.asp


In the "fine print" it says that you need to use INITIALIZED data!  For instance, this will fail...

      #pragma data_seg(".shared")
          int nShared;  
      #pragma data_seg()

but this will work exactly as advertized:

      #pragma data_seg(".shared")
         int nShared= 77;  
      #pragma data_seg()


I used the following code for testing (and my thanks go out to  vadik  for the #pragma(linker,... ) tip -- it's better than the often-documented .DEF file variation.

#include "stdafx.h"
#include "DllSharedMem.h"

#pragma data_seg(".shared")   // Make a new section that we'll make shared
   int nShared=77;  
#pragma data_seg() // Back to regular, nonshared data
#pragma comment(linker, "/SECTION:.shared,RWS")

int nUnshared;  

BOOL APIENTRY DllMain( HANDLE hModule, DWORD reason, LPVOID lpReserved ) {
      return TRUE;
}
DLLSHAREDMEM_API int  GetUnsharedInt(void) { return nUnshared; }
DLLSHAREDMEM_API void SetUnsharedInt(int nNewVal) { nUnshared= nNewVal; }
DLLSHAREDMEM_API int  GetSharedInt(void) { return nShared; }
DLLSHAREDMEM_API void SetSharedInt(int nNewVal) { nShared= nNewVal; }


Use that DLL in several processes and the nShared value will be the same everywhere.  There is one thing to watch out for.... If you have more than one copy of the DLL, or if you gave just one copy, but it can be called using different path names, then the modules are considered different and nothing is shard, including code or SHARED data.   See:
      PRB: Problem with Shared Data Sections in DLLs.
      http://support.microsoft.com/default.aspx?scid=kb%3Ben-us%3B147136

-- Dan
0

Featured Post

Moving data to the cloud? Find out if you’re ready

Before moving to the cloud, it is important to carefully define your db needs, plan for the migration & understand prod. environment. This wp explains how to define what you need from a cloud provider, plan for the migration & what putting a cloud solution into practice entails.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction: Ownerdraw of the grid button.  A singleton class implentation and usage. Continuing from the fifth article about sudoku.   Open the project in visual studio. Go to the class view – CGridButton should be visible as a class.  R…
Introduction: Hints for the grid button.  Nested classes, templated collections.  Squash that darned bug! Continuing from the sixth article about sudoku.   Open the project in visual studio. First we will finish with the SUD_SETVALUE messa…
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
How to fix incompatible JVM issue while installing Eclipse While installing Eclipse in windows, got one error like above and unable to proceed with the installation. This video describes how to successfully install Eclipse. How to solve incompa…

770 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question