Solved

Share memory between a C++ program and a C# program

Posted on 2009-04-09
19
2,493 Views
Last Modified: 2013-12-03
Hi all,

I currently have 2 c++ programs running windows, one that creates a file mapping object that shares some variables, and one that opens the file mapping object and takes the variables and uses them.

I need the second program to ultimately be a C# console app, but I cannot find any information online about sharing memory in C#. I'll post my C++ code that I ultimately need to port over to C#.

Does anyone know how I would go about doing this? Thanks for your help!
#define MAX			500

#define BUF_SIZE	256	
 

#include <stdio.h>

#include <string.h>

#include <sys/types.h>

#include <windows.h>

#include <conio.h>

#include <tchar.h>

#include <memory.h>
 

char szName[] = "Global\\MyFileMappingObject";
 

int main()

{
 

	printf("Client Simple Simulator\n");
 

	HANDLE hMapFile_1 = OpenFileMapping(

		FILE_MAP_ALL_ACCESS,

		FALSE,

		szName);
 

	LPCTSTR pBuf_1 = (LPTSTR)MapViewOfFile(

		hMapFile_1,

		FILE_MAP_ALL_ACCESS,

		0,

		0,

		BUF_SIZE);
 

	printf("\n%s\n", pBuf_1);
 

	getch();
 

	UnmapViewOfFile(pBuf_1);

	CloseHandle(hMapFile_1);
 

	return 0;

}

Open in new window

0
Comment
Question by:ehensens
  • 8
  • 7
  • 2
19 Comments
 
LVL 86

Assisted Solution

by:jkr
jkr earned 150 total points
Comment Utility
I already posted a link to http://www.codeproject.com/KB/threads/sharedmemipc.aspx ("Interprocess Communication using Shared Memory") in your other question - you'll find the C# counterpart at http://www.codeproject.com/KB/threads/csthreadmsg.aspx ("A C# Framework for Interprocess Synchronization and Communication"). Tieing both these ends together, you have a C#/C++ IPC using shared memory.
0
 

Author Comment

by:ehensens
Comment Utility
Hi jkr,

Sorry, for some reason I didn't get any email saying that you had posted a possible solution to my other question or I would have seen that link first. I'll check this out.
0
 
LVL 39

Assisted Solution

by:abel
abel earned 350 total points
Comment Utility
You can do it the same way as in C++, if that feels most convenient for you, but in C# that means a little more work because you have to P/Invoke your win32 API functions. An example of how that's done for MapViewOfFile is found here: http://www.pinvoke.net/default.aspx/kernel32/MapViewOfFile.html

If you'll end up with C#-only applications in the end, you can also stick to MemoryStream, which is very simple way to use any stream in-memory only.

If you want to have access to direct memory locations, you can use the UnmanagedMemoryStream class in C#.

Depending on the end result you're after, you can choose either or a combination of these approaches.

-- Abel --
0
 
LVL 39

Expert Comment

by:abel
Comment Utility
ah, I see jkr also posted some. In addition, I came across the following link claiming to have be a full wrapper for memory mapped files and interop services, it may save you some time: http://github.com/tomasr/filemap/tree/master
0
 

Author Comment

by:ehensens
Comment Utility
Hi everyone, thanks so much for your help, but I fear that I am still doing something wrong. I am getting the following errors:

Error    1    The best overloaded method match for 'C_Sharp_Client_Simulator.Program.MapViewOfFile(System.IntPtr, C_Sharp_Client_Simulator.Program.FileMapAccess, uint, uint, uint)' has some invalid arguments

Error    2    Argument '2': cannot convert from 'uint' to 'C_Sharp_Client_Simulator.Program.FileMapAccess'

Can anyone spot what I'm doing wrong here?




using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Runtime.InteropServices;
 
 

namespace C_Sharp_Client_Simulator

{

    class Program

    {

        [DllImport("kernel32.dll", SetLastError = true)]

        static extern IntPtr OpenFileMapping(

            uint dwDesiredAccess, 

            bool bInheritHandle,

            string lpName);
 

        [DllImport("kernel32.dll", SetLastError = true)]

        static extern IntPtr MapViewOfFile(

            IntPtr hFileMappingObject,

            FileMapAccess dwDesiredAccess,

            uint dwFileOffsetHigh,

            uint dwFileOffsetLow,

            uint dwNumberOfBytesToMap);
 

        [Flags]

        public enum FileMapAccess : uint

        {

            FileMapCopy = 0x0001,

            FileMapWrite = 0x0002,

            FileMapRead = 0x0004,

            FileMapAllAccess = 0x001f,

            fileMapExecute = 0x0020,

        }
 

        public static IntPtr Attach()

        {

            string szName = "Global\\MyFileMappingObject";

            uint BUF_SIZE = 256;
 

            UInt32 STANDARD_RIGHTS_REQUIRED = 0x000F0000;

            UInt32 SECTION_QUERY = 0x0001;

            UInt32 SECTION_MAP_WRITE = 0x0002;

            UInt32 SECTION_MAP_READ = 0x0004;

            UInt32 SECTION_MAP_EXECUTE = 0x0008;

            UInt32 SECTION_EXTEND_SIZE = 0x0010;

            UInt32 SECTION_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | SECTION_QUERY |

            SECTION_MAP_WRITE |

            SECTION_MAP_READ |

            SECTION_MAP_EXECUTE |

            SECTION_EXTEND_SIZE);

            UInt32 FILE_MAP_ALL_ACCESS = SECTION_ALL_ACCESS;
 

            IntPtr hMapFile_1 = OpenFileMapping(FILE_MAP_ALL_ACCESS, false, szName);

            IntPtr pBuf = MapViewOfFile(hMapFile_1, FILE_MAP_ALL_ACCESS, 0, 0, BUF_SIZE);

            return pBuf;

        }
 
 

        static int Main(string[] args)

        {

            Console.WriteLine("C# Client Simulator");
 

            IntPtr valueInMemory = Attach();
 

            Console.WriteLine("{0}", valueInMemory);
 

            Console.ReadLine();
 

            return 0;

        }

    }

}

Open in new window

0
 

Author Comment

by:ehensens
Comment Utility
Update:

I have changed my code to the following, and I am at least getting it to compile, but I'm not familiar with IntPtr, and the return of the MapViewOfFile is of type IntPtr and when I console.writeline the return value it's just a long int. Can anyone lend some insight as to what I'm doing wrong here? Thanks a bunch!

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Runtime.InteropServices;
 
 

namespace C_Sharp_Client_Simulator

{

    class Program

    {

        [DllImport("kernel32.dll", SetLastError = true)]

        static extern IntPtr OpenFileMapping(

            uint dwDesiredAccess,

            bool bInheritHandle,

            string lpName);
 

        

        [DllImport("kernel32.dll", SetLastError = true)]

        static extern IntPtr MapViewOfFile(

            IntPtr hFileMappingObject,

            uint dwDesiredAccess,

            uint dwFileOffsetHigh,

            uint dwFileOffsetLow,

            uint dwNumberOfBytesToMap);
 

        

        /*[Flags]

        public enum FileMapAccess : uint

        {

            FileMapCopy = 0x0001,

            FileMapWrite = 0x0002,

            FileMapRead = 0x0004,

            FileMapAllAccess = 0x001f,

            fileMapExecute = 0x0020,

        }*/
 

        public static void attach()

        {

            string szName = "Global\\MyFileMappingObject";

            uint BUF_SIZE = 256;
 

            UInt32 STANDARD_RIGHTS_REQUIRED = 0x000F0000;

            UInt32 SECTION_QUERY = 0x0001;

            UInt32 SECTION_MAP_WRITE = 0x0002;

            UInt32 SECTION_MAP_READ = 0x0004;

            UInt32 SECTION_MAP_EXECUTE = 0x0008;

            UInt32 SECTION_EXTEND_SIZE = 0x0010;

            UInt32 SECTION_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | SECTION_QUERY |

            SECTION_MAP_WRITE |

            SECTION_MAP_READ |

            SECTION_MAP_EXECUTE |

            SECTION_EXTEND_SIZE);

            UInt32 FILE_MAP_ALL_ACCESS = SECTION_ALL_ACCESS;

            uint AccessType = 0x001f;

            //FileMapAccess AccessType = FileMapAllAccess;
 

            IntPtr hMapFile_1 = OpenFileMapping(FILE_MAP_ALL_ACCESS, false, szName);

            IntPtr pBuf = MapViewOfFile(hMapFile_1, AccessType, 0, 0, BUF_SIZE);
 

            Console.WriteLine("\n{0}\n", pBuf);

        }
 
 

        static int Main(string[] args)

        {

            Console.WriteLine("C# Client Simulator");
 

            attach();
 

            //IntPtr valueInMemory = Attach();
 

            //Console.WriteLine("{0}", valueInMemory);
 

            Console.ReadLine();
 

            return 0;

        }

    }

}

Open in new window

0
 
LVL 39

Accepted Solution

by:
abel earned 350 total points
Comment Utility
You can do one of two things from that code: either you use the constants, as you do in the calling of the function, in which case you should declare the function with uint for the flags. Or you use the enum, in which case you should both declare and use the enum.

I can understand that the example of that page is a bit blurred because it mixes both methods:




// change the calling of the method by using a typed enum

IntPtr pBuf = MapViewOfFile(hMapFile_1, FileMapAccess.FileMapAllAccess, 0, 0, BUF_SIZE);
 

//or change the declaration to use the untyped constants:
 

[DllImport("kernel32.dll", SetLastError = true)]

   static extern IntPtr MapViewOfFile(

      IntPtr hFileMappingObject,

      uint dwDesiredAccess,

      uint dwFileOffsetHigh,

      uint dwFileOffsetLow,

      uint dwNumberOfBytesToMap);

Open in new window

0
 
LVL 39

Expert Comment

by:abel
Comment Utility
just saw your last comment, but I'm off for two hours, will be back soon!
0
What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

 

Author Comment

by:ehensens
Comment Utility
So now that I get it to compile (see my code), I am printing out the value on the screen, which should be a char[] "hello" from my c++ program, but it's appearing each time as 6 or 7 digit numbers.

Anyone have any ideas? Please help out; if I can increase the amount of points beyond 500 please let me know how.


using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Runtime.InteropServices;
 
 

namespace C_Sharp_Client_Simulator

{

    class Program

    {

        [DllImport("kernel32.dll", SetLastError = true)]

        static extern IntPtr OpenFileMapping(

            uint dwDesiredAccess,

            bool bInheritHandle,

            string lpName);
 

        

        [DllImport("kernel32.dll", SetLastError = true)]

        static extern IntPtr MapViewOfFile(

        //static extern string MapViewOfFile(

            IntPtr hFileMappingObject,

            uint dwDesiredAccess,

            uint dwFileOffsetHigh,

            uint dwFileOffsetLow,

            uint dwNumberOfBytesToMap);
 

        public static void attach()

        {

            string szName = "Global\\MyFileMappingObject";

            uint BUF_SIZE = 256;
 

            UInt32 STANDARD_RIGHTS_REQUIRED = 0x000F0000;

            UInt32 SECTION_QUERY = 0x0001;

            UInt32 SECTION_MAP_WRITE = 0x0002;

            UInt32 SECTION_MAP_READ = 0x0004;

            UInt32 SECTION_MAP_EXECUTE = 0x0008;

            UInt32 SECTION_EXTEND_SIZE = 0x0010;

            UInt32 SECTION_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | SECTION_QUERY |

            SECTION_MAP_WRITE |

            SECTION_MAP_READ |

            SECTION_MAP_EXECUTE |

            SECTION_EXTEND_SIZE);

            UInt32 FILE_MAP_ALL_ACCESS = SECTION_ALL_ACCESS;

            uint AccessType = 0x001f;
 

            IntPtr hMapFile_1 = OpenFileMapping(FILE_MAP_ALL_ACCESS, false, szName);

            //string pBuf = MapViewOfFile(hMapFile_1, AccessType, 0, 0, BUF_SIZE);

            IntPtr pBuf = MapViewOfFile(hMapFile_1, AccessType, 0, 0, BUF_SIZE);
 

            Console.WriteLine(pBuf);

        }
 
 

        static int Main(string[] args)

        {

            Console.WriteLine("C# Client Simulator");
 

            attach();
 

            Console.ReadLine();
 

            return 0;

        }

    }

}

Open in new window

0
 

Author Comment

by:ehensens
Comment Utility
got it. the fix is:

string pBufString = System.Runtime.InteropServices.Marshal.PtrToStringAnsi(pBuf);
0
 
LVL 39

Expert Comment

by:abel
Comment Utility
Sorry, like I said, i needed to run. Just got back. Glad you found it out. Note that you should use

System.Runtime.InteropServices.Marshal.PtrToStringUni

in many cases if the contents goes beyond the first 127 characters of US-ASCII. That is, because the Ansi (8 bit) is there still for old style strings and storage, but on win32 windows, all strings and data is commonly stored in utf-8 or utf-16 (in memory, all strings are utf-16). Using PtrToStringUni can be a lot saver and save you from trouble in the future when some é, ä, æ or å pops up incorrectly encoded showing as a different character....

-- Abel --
0
 

Author Comment

by:ehensens
Comment Utility
Thanks for everyone's help, I am really busy now but after the long weekend I will divvy up the points.
0
 
LVL 86

Expert Comment

by:jkr
Comment Utility
So, the above articles didn't help at all?
0
 
LVL 39

Expert Comment

by:abel
Comment Utility
I think it did. See a few comments back, where the OP says "got it. the fix is:". On that point, I continued slightly. Why the OP didn't at least share the points is beyond me. Shall I post a request for split?

-- Abel --
0
 

Author Comment

by:ehensens
Comment Utility
Sorry, how do I change it now?
0
 
LVL 39

Expert Comment

by:abel
Comment Utility
you can do so by clicking the "Request Attention" link, right under your question. You can then type a small message to the moderators, including the IDs of the comments you want to split between and they will change it for you.
0
 

Author Comment

by:ehensens
Comment Utility
That would be great, jkr, thanks.
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

This article is for Object-Oriented Programming (OOP) beginners. An Interface contains declarations of events, indexers, methods and/or properties. Any class which implements the Interface should provide the concrete implementation for each Inter…
Real-time is more about the business, not the technology. In day-to-day life, to make real-time decisions like buying or investing, business needs the latest information(e.g. Gold Rate/Stock Rate). Unlike traditional days, you need not wait for a fe…
The goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…

763 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

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now