在c ++和c#之间共享内存映射文件结构

我有2个应用程序,1个是C ++,1个是C#。 以下是我在C ++中的结构:

struct INFO { char Name[MAX_PATH]; int Number; }; 

以下是我尝试在C#中复制结构:

 [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public struct INFO { public byte Name; public int Number; } 

C ++程序(准备编译和测试):

 #include  #include  #include  using namespace std; #define WIN32_LEAN_AND_MEAN #define _WIN32_WINNT _WIN32_WINNT_WINXP // System Include #include  #include  struct INFO { char Name[MAX_PATH]; int Number; }; HANDLE FileMappingHandle; INFO* FileMapping; void EntryProc() { if ((FileMappingHandle = CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, sizeof(INFO), "Local\\INFO_MAPPING")) == 0) { return; } if ((FileMapping = (INFO*)MapViewOfFile(FileMappingHandle, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(INFO))) == 0) { return; } strcpy(FileMapping->Name, "DARKVADER"); FileMapping->Number = 1337; printf("FileMapping->Name: %s", FileMapping->Name); printf("FileMapping->Number: %d", FileMapping->Number); } int main() { EntryProc(); do { cout << '\n' << "Press the Enter key to continue."; } while (cin.get() != '\n'); return 0; } 

C#程序(准备编译和测试):

 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.Runtime.InteropServices; using System.IO.MemoryMappedFiles; namespace WindowsFormsApplication1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); this.DoMap(); } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public struct INFO { public byte Name; public int Number; } public void DoMap() { MemoryMappedFileSecurity CustomSecurity = new MemoryMappedFileSecurity(); CustomSecurity.AddAccessRule(new System.Security.AccessControl.AccessRule("everyone", MemoryMappedFileRights.FullControl, System.Security.AccessControl.AccessControlType.Allow)); //access memory mapped file (need persistence) using (var memMapFile = MemoryMappedFile.CreateOrOpen("Local\\INFO_MAPPING", 1024, MemoryMappedFileAccess.ReadWriteExecute, MemoryMappedFileOptions.None, CustomSecurity, System.IO.HandleInheritability.Inheritable)) { using (var accessor = memMapFile.CreateViewAccessor()) { INFO data; accessor.Read(0, out data); Console.WriteLine(data.Name); Console.WriteLine(data.Number); } } } } } 

问题:

我可以使用上面的代码在两个应用程序之间共享数字,但我无法共享字符串。

当我说“不能”分享时,我实际上的意思是,而不是实际的“人物”,我总是得到奇怪的中国符号,甚至数字消失。

我在C#struct中尝试了所有我能想到的组合(byte [],string,unsafe struct等),但是我失败了。

请告诉我/向我解释如何在我的2个应用程序之间共享正确的字符串。

可以理解示例工作代码。

要共享字符串,您需要正确映射它们: https : //docs.microsoft.com/en-us/dotnet/framework/interop/default-marshaling-for-strings

可能你需要装饰( ByValTStr使用你的StructLayout CharSet ,所以它是ANSI):

 [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)] string Name; 

编辑:检查.net核心。 不允许在Accessor中使用引用类型。 最简单的选择是读取数组并提取值。

 var buffer = new byte[264]; accessor.ReadArray(0, buffer, 0, buffer.Length); var endIndex = Array.FindIndex(buffer, 0, 260, x => x == 0); var name = Encoding.ASCII.GetString(buffer, 0, endIndex == -1 ? 260 : endIndex); var number = BitConverter.ToInt32(buffer, 260); 

另一个是使用不安全的:

 [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Ansi)] public unsafe struct INFO { [FieldOffset(0)] public fixed byte Name[260]; [FieldOffset(260)] public int Number; } class Program { static void Main(string[] args) { //CustomSecurity.AddAccessRule(new System.Security.AccessControl.AccessRule("everyone", MemoryMappedFileRights.FullControl, System.Security.AccessControl.AccessControlType.Allow)); //access memory mapped file (need persistence) using (var memMapFile = MemoryMappedFile.CreateOrOpen( "Local\\INFO_MAPPING", 1024, MemoryMappedFileAccess.ReadWriteExecute, MemoryMappedFileOptions.None, System.IO.HandleInheritability.Inheritable)) { using (var accessor = memMapFile.CreateViewAccessor()) { accessor.Read(0, out INFO data); string name; unsafe { name = new String((sbyte*)data.Name, 0, 260); } Console.WriteLine(name); Console.WriteLine(data.Number); } } }