Beispiel für eine DLL mit shared Memory und statischer und dynamischer Bindung

Beispiel für eine Dll, die einen shared Memorybereich definiert, auf den die zwei Anwendungen producer und consumer zugreifen.
Dieses Prinzip kann auch für die Programmierung eines Semaphor verwendet werden.

Beschreibung

Die Anwendung producer schreibt den Wert 2 in das shared memory der sharedMem.dll. Da die DLL nur solange geladen bleibt, solange eine Anwendung darauf zugreift, wartet die Anwendung auf eine Benutzereingabe. Startet man nun die Anwednung consumer, solange producer noch aktiv ist, liest consumer diesen Wert aus dem shared memory aus.

Programmierung

sharedMem.dll

Die DLL sharedMem definiert die Integer Varaible val als shared memory durch das pragma data_seg. Anschliessend muß dieses data_seg noch in shardedMem.def im Bereich SECTIONS als READ WRITE SHARED deklariert werden. Damit steht die Variable während der Laufzeit der DLL allen zugreifenden Programmen zur Verfügung.
Auf die Varaiable val kann mit folgenden Methoden zugegriffen werden:
addVal (setzt den Wert) und
readVal() (liest den Wert aus)
Quelltext sharedMem.dll:

#include "windows.h" //include normalerweise in spitzen Klammern, wegen html-Darstellung ersetzt durch Hochkomma

#pragma data_seg(".shared")
static int val=0;
#pragma data_seg()

BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved) {
return TRUE;
}

extern "C" __declspec (dllexport) void addValue (int a){ val=a; }

extern "C" __declspec (dllexport) int readValue (void) {
return val;
}

Producer.cpp

Producer zeigt sowohl das statische, als auch das dynamische Binden von sharedMem.dll Das statische Binden ist auskommentiert. Beim dynamischen Binden muss beim Linken der Anwendungen consumer und producer sharedMem.lib ins Projekt eingebunden werden. Für das dynamische Binden wird afxext.h benötigt. Der Header wird in StdAfx.h eingebunden.
Producer setzt das shared memory auf den Wert 2. Um sicherzugehen, dass der Wert gesetzt wurde wird er nach dem Setzen ausgelesen. Anschliessend kann mit consumer der Wert ausgelesen werden. Producer bleibt nach dem Setzen und Auslesen des shared Memorys aktiv, damit die DLL nicht terminiert und das shared memory nicht freigegeben wird.
Quelltext producer.cpp:
#include "StdAfx.h"
#include "conio.h"
//Für statisches Binden entkommentieren
/* __declspec (dllimport) int readValue ();
__declspec (dllimport) void addValue (int);
*/
int main(int argc, char* argv[]){
int i=0;
//Dynamisches Binden
typedef void (LPADD)(int);
typedef int (LPREAD)(void);
HINSTANCE hDLL = NULL;
LPADD* lpAddValue;
LPREAD* lpReadValue;
hDLL = ::LoadLibrary("C:\\Programme\\Microsoft Visual Studio\\MyProjects\\Java2C\\SharedMem\\Debug\\SharedMem.dll");
if( hDLL == NULL )
printf("Could not load the DLL");

else{
lpAddValue = (LPADD*)::GetProcAddress(hDLL, "addValue");
lpReadValue = (LPREAD*)::GetProcAddress(hDLL, "readValue");
}
//Ende dynamisches Binden
printf("Setze Wert in Dll auf 2");
// addValue(2);//Statisch
(*lpAddValue)(2);//Dynamisch
printf("Auslesen des Wertes in der DLL");
// i=readValue(); //Statisch
i=(*lpReadValue)(); //Dynamisch
printf("Wert= %d",i);
while (!kbhit()); //DLL am Leben halten
return 0;
}

Consumer.cpp

Consumer liest den vom Producer gesetzten Wert aus dem shared memory.
Quelltext consumer.cpp:
#include "stdafx.h"
//int __declspec (dllimport) readValue (); //statisch
int main(int argc, char* argv[]){
//Dynamisches Binden:
typedef int (LPREAD)(void);
HINSTANCE hDLL = NULL;
LPREAD* lpReadValue;
hDLL = ::LoadLibrary("C:\\Programme\\Microsoft Visual Studio\\MyProjects\\Java2C\\Debug\\Java2C.dll"); if( hDLL == NULL )
printf("Could not load the DLL ");
else{
lpReadValue = (LPREAD*)::GetProcAddress(hDLL, "readValue");
}
//Ende Dynamisches Binden
printf("Auslesen des Wertes in der DLL");
// int i=readValue() //Statisch
int i=(*lpReadValue)(); //Dynamisch
printf("Wert= %d ",i);
return 0;

}
Download VC++ Projekt Shared Mem 

Sollten bei der Verwendung Fehler auftreten, melden Sie diese bitte per Mail an: Dieter Ebhart