Shared Memory: Another problem
I am trying to make the C# code and the C code communicate with eachother by a named shared memory. I am able to get them to access the memory by pointing to the memory location, and they runs fine independently. However, if I run the C and C# exes at the same time the C# will points to null in the memory location.
// Note: You must compile this file using the C# /unsafe switch.
//[assembly: SecurityPermission(SecurityAction.RequestMinimum, Execution = true)]
// This class includes several Win32 interop definitions.
internal class Win32
{
public static readonly IntPtr InvalidHandleValue = new IntPtr(-1);
public const UInt32 FILE_MAP_WRITE = 2;
public const UInt32 PAGE_READWRITE = 0x04;
[DllImport("Kernel32")]
public static extern IntPtr CreateFileMapping(IntPtr hFile,
IntPtr pAttributes, UInt32 flProtect,
UInt32 dwMaximumSizeHigh, UInt32 dwMaximumSizeLow, String pName);
[DllImport("Kernel32")]
public static extern IntPtr OpenFileMapping(UInt32 dwDesiredAccess,
Boolean bInheritHandle, String name);
[DllImport("Kernel32")]
public static extern Boolean CloseHandle(IntPtr handle);
[DllImport("Kernel32")]
public static extern IntPtr MapViewOfFile(IntPtr hFileMappingObject,
UInt32 dwDesiredAccess,
UInt32 dwFileOffsetHigh, UInt32 dwFileOffsetLow,
IntPtr dwNumberOfBytesToMap);
[DllImport("Kernel32")]
public static extern Boolean UnmapViewOfFile(IntPtr address);
[DllImport("Kernel32")]
public static extern IntPtr GetCurrentProcess();
}
....
class App
{
[STAThread]
static void Main(string[] args)
{
//Serialize();
//Console.WriteLine();
Deserialize();
}
unsafe static void Deserialize()
{
IntPtr hFileMap = IntPtr.Zero;
IntPtr address;
hFileMap = Win32.CreateFileMapping(Win32.InvalidHandleValue,
IntPtr.Zero, Win32.PAGE_READWRITE,
0, 4096, "TestSharedEvent");
Console.WriteLine("CreateFileMapping returned: " + hFileMap);
if (hFileMap == IntPtr.Zero)
throw new Exception("Could not create memory-mapped file.");
address = Win32.MapViewOfFile(hFileMap, Win32.FILE_MAP_WRITE,
0, 0, IntPtr.Zero);
Console.WriteLine("MapViewOfFile returned: " + address);
Win32.memset(address, 0, 4096);
Console.WriteLine("memset worked"); Console.WriteLine("New value: " + *(Byte*)address);
Thread.Sleep(1000);
//Dispose(address)
}
}
}
The C code looks almost exactly the same, except it could access the memory directly so no DLL calls and it writes the information on the shared memory.
[3630 byte] By [
adroit2] at [2007-12-21]
This is a one C# application.
The first section of the code is just a decleration to import window API from Kernel32.dll. This is just so I can get access to the memory. This is the code that I've received from my first post: http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=469838&SiteID=1
The second section is the main part of the code that use the imported API to create a named shared memory called "TestSharedMemory". It should be receiving information from the shared segment of the memory.
When I run the C# code alone, it was able to access the part of the memory. I have done couple of stepping through and it looks like it actually points to a memory location and would read data from it (but the data would be "null" because there is on other application writing data to it). However, if the I run the same C# application while the C application is running, the C# pointer would points to null instead of a memory location.
It seems like the C# and C application are pointing to the same memory location, but if they're running at the same time the C application would locks the C# one out.
Here is the C code (Notice that it is very similar to the main function in C#):
#include <stdio.h>
#include <windows.h>
void main(int argc, char* argv[])
{
HANDLE mappedFile = 0;
int oneSecond = 1000;
char* shared = NULL;
HANDLE eventHnd;
eventHnd = CreateEvent(NULL, FALSE, FALSE, "TestSharedEvent");
mappedFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL,
PAGE_READWRITE, 0, 4096, "TestSharedMemory");
printf("CreateFileMapping returned %d\n", mappedFile);
fflush(NULL); shared = (char*)MapViewOfFile(mappedFile, FILE_MAP_WRITE, 0, 0, 0);
printf("MapViewOfFile returned %p\n", shared);
fflush(NULL);
memset(shared, 0, 4096);
printf("memset worked\n");
fflush(NULL);
int counter = 0;
while (1)
{
sprintf(shared, "value %d", counter++);
printf("Sending new string: %s\n", shared);
SetEvent(eventHnd);
// STEP 5
Sleep(1000);
}
UnmapViewOfFile(shared);
}
I also tried running two C application at the same time (one sending and the other receiving the memory) , and it works just fine.
There's two application in total, one C# and one C. I thought you were asking if the code in my original post was two seperate application, that code is for one application.
Give me another try. Here is the working prototype code that I've got. If you run the master code, it will start sending information to the memory. If you, then, start up the slave code, it will starts receiving the information from the memory.
I just want to convert the slave code to C#.
EXE file #1: Mater C code sending information:
#include <stdio.h>
#include <windows.h>
void main(int argc, char* argv[])
{
HANDLE mappedFile = 0;
int oneSecond = 1000;
char* shared = NULL;
HANDLE eventHnd;
eventHnd = CreateEvent(NULL, FALSE, FALSE, "TestSharedEvent");
// STEP 1
mappedFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL,
PAGE_READWRITE, 0, 4096, "TestSharedMemory");
printf("CreateFileMapping returned %d\n", mappedFile);
fflush(NULL); // STEP 2
shared = (char*)MapViewOfFile(mappedFile, FILE_MAP_WRITE, 0, 0, 0);
printf("MapViewOfFile returned %p\n", shared);
fflush(NULL);
memset(shared, 0, 4096);
printf("memset worked\n");
fflush(NULL);
int counter = 0;
while (1)
{
sprintf(shared, "value %d", counter++);
printf("Sending new string: %s\n", shared);
SetEvent(eventHnd);
// STEP 5
Sleep(1000);
}
UnmapViewOfFile(shared);
}
EXE File #2 Slave C code receiving information:
#include <stdio.h>
#include <windows.h>
#define SCREEN_SIZE (320*240/8)
void main(int argc, char* argv[])
{
HANDLE mappedFile = 0;
int oneSecond = 1000;
char* shared = NULL;
HANDLE eventHnd;
eventHnd = CreateEvent(NULL, FALSE, FALSE, "TestSharedEvent");
// STEP 1
mappedFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL,
PAGE_READWRITE, 0, SCREEN_SIZE, "TestSharedMemory");
printf("CreateFileMapping returned %d\n", mappedFile);
fflush(NULL); // STEP 2
shared = (char*)MapViewOfFile(mappedFile, FILE_MAP_WRITE, 0, 0, 0);
printf("MapViewOfFile returned %p\n", shared);
fflush(NULL);
memset(shared, 0, 4096);
int value = 0;
printf("memset worked\n");
fflush(NULL);
while (1)
{
WaitForSingleObject(eventHnd, INFINITE);
// STEP 5
printf("New value %s\n", shared);
Sleep(oneSecond);
}
UnmapViewOfFile(shared);
}
Make File:
CPPFILES1 = master.cpp
CPPFILES2 = slave.cpp
OBJS1 = $(CPPFILES1:s;.cpp;$O;)
OBJS2 = $(CPPFILES2:s;.cpp;$O;)
EXETARGET1 = master$E
EXETARGET2 = slave$E
link: deps $(EXETARGET1) $(EXETARGET2)
$(EXETARGET1): $(OBJS1)
$(EXETARGET2): $(OBJS2)
deps:: includes$(DEP)
includes$(DEP): $(CPPFILES1) $(CPPFILES2)
.INCLUDE .IGNORE : includes$(DEP)
I know that I am terrible at explaining things, sorry about that. I am trying though. Is that a little more clear? Or do you need more info? I'm not sure what other information you need to make this more clear.
Thank you, for trying to help. I truly appreciate it.