I am using sharedmemory in my c# app with c++ interop. Currently I am marshalling a struct to a pointer and broadcasting the message. The program I am broadcasting to, opens up correctly with the debug message, but doesn't show/bring-in the data that I had in use within my struct.
Thanks!
The app I am trying to talk to was written in c++ and I am coding in c#. I am using all the DLLImports correctly (I think) and it compiles and runs error free.
using System.Runtime.InteropServices;
[DllImport("user32", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode)]
public static extern uint RegisterWindowMessageW([In]string lpString);
[DllImport("user32", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi)]
public static extern uint RegisterWindowMessageA([In]string lpString);
[DllImport("kernel32", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Auto)]
public static extern IntPtr OpenFileMapping(FileMapAccessRights dwDesiredAccess, int bInheritHandle, [In]String lpName);
[DllImport("kernel32", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Auto)]
public static extern IntPtr MapViewOfFile(IntPtr hFileMappingObject, FileMapAccessRights dwDesiredAccess, uint dwFileOffsetHigh, uint dwFileOffsetLow, UIntPtr dwNumberOfBytesToMap);
[DllImport("kernel32", CallingConvention = CallingConvention.StdCall)]
public static extern int UnmapViewOfFile(IntPtr lpBaseAddress);
[DllImport("kernel32", CallingConvention = CallingConvention.StdCall)]
public static extern int CloseHandle(IntPtr hObject);
[DllImport("user32.dll")]
public static extern IntPtr PostMessage(IntPtr hWnd, uint msg, int wParam, int lParam);
uint WM_ZOOM_XYZ = RegisterWindowMessageA("WM_ZOOM_XYZ");
int i = Broadcast_Zoom_Message(10000, 10000, 0, WM_ZOOM_XYZ);
public int Broadcast_Zoom_Message(double dbX, double dbY, double dbZ, uint uMessage)
{
string smSharedMemory = "COORDINATES";
IntPtr hMem = OpenFileMapping(FileMapAccessRights.Write, FALSE, smSharedMemory);
if (IntPtr.Zero == hMem)
{
return 0;
}
IntPtr pvHead = MapViewOfFile(hMem, FileMapAccessRights.Write, 0, 0, UIntPtr.Zero);
if (IntPtr.Zero == pvHead)
{
CloseHandle(hMem);
MessageBox.Show(
"Unable to view " + smSharedMemory,
"Error", MessageBoxButtons.OK, MessageBoxIcon.Stop);
return 0;
}
CoordinatesStruct structCoords = new CoordinatesStruct();
Marshal.PtrToStructure(pvHead, structCoords);
int bVersionOk = FALSE;
if (1 == structCoords.uMajorVersion)
{
if (WM_ZOOM_XYZ == uMessage)
{
structCoords.dbDesiredX = dbX;
structCoords.dbDesiredY = dbY;
structCoords.dbDesiredZ = dbZ;
}
bVersionOk = TRUE;
}
else
{
MessageBox.Show(
"Unrecognized shared memory: " +
structCoords.uMajorVersion.ToString() + "." + structCoords.uMinorVersion.ToString());
}
if (IntPtr.Zero != hMem)
{
CloseHandle(hMem);
}
UnmapViewOfFile(pvHead);
IntPtr HWND_BROADCAST = (IntPtr)0xffff;
if (bVersionOk == TRUE)
{
PostMessage(HWND_BROADCAST, uMessage, 0, 0);
return 1;
}
else
return 0;
}
I think your intention was to put the changed structCoords
back to the mapped file. When we use Marshal.PtrToStructure()
we receive a copy of the content of the unmanaged memory. The changes of the received object will not reflect in the unmanaged memory. When we are done with the data, we should put the changes back to the memory using Marshal.StructureToPtr
.
Here is what I think it should be:
if (1 == structCoords.uMajorVersion)
{
if (WM_ZOOM_XYZ == uMessage)
{
structCoords.dbDesiredX = dbX;
structCoords.dbDesiredY = dbY;
structCoords.dbDesiredZ = dbZ;
}
bVersionOk = TRUE;
Marshal.StructureToPtr(structCoords , pvHead, false); // <-- this is what you (I) forgot!
}