在 C++ 和 C# 之间共享内存映射文件结构
Sharing Memory Mapped File Structure between c++ and c#
我有 2 个应用程序,1 个是C++的,一个是 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 <stdio.h>
#include <tchar.h>
#include <iostream>
using namespace std;
#define WIN32_LEAN_AND_MEAN
#define _WIN32_WINNT _WIN32_WINNT_WINXP
// System Include
#include <windows.h>
#include <winsock2.h>
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<MemoryMappedFileRights>("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<INFO>(0, out data);
Console.WriteLine(data.Name);
Console.WriteLine(data.Number);
}
}
}
}
}
问题:
我可以使用上面的代码在两个应用程序之间共享数字,但我不能共享字符串。
当我说"不能"分享时,我实际上的意思是,我总是得到奇怪的中国符号,而不是实际的"字符",甚至数字消失了。
我已经在 C# 结构中尝试了我能想到的所有组合( byte[]、字符串、不安全结构等),但我失败了。
请告诉我/向我解释如何在我的 2 个应用程序之间正确共享字符串。
示例工作代码将不胜感激。
要共享字符串,您需要正确映射它们: https://learn.microsoft.com/en-us/dotnet/framework/interop/default-marshaling-for-strings
可能,你需要装饰(ByValTStr
使用你StructLayout
的CharSet
,所以它是ANSI):
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)]
string Name;
编辑:已在 .net 核心上检查。不允许在访问器中使用引用类型。最简单的选择是读取数组并提取值。
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<MemoryMappedFileRights>("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<INFO>(0, out INFO data);
string name;
unsafe
{
name = new String((sbyte*)data.Name, 0, 260);
}
Console.WriteLine(name);
Console.WriteLine(data.Number);
}
}
}
相关文章:
- 添加静态constexpr成员是否会更改结构/类的内存映射
- C/C++ - 查询平台相关的换行符(用于内存映射文件)
- 字符串共享内存映射的向量
- 确保内存映射页位于内存中
- 我可以将新的 std::tuple 放入内存映射区域,并在以后读回吗?
- 内存映射文件访问非常慢
- 内存映射C++中的流数据
- 我正在尝试创建一个C++映射,该映射在boost内存映射文件中具有向量值
- 内存映射区域初始数据
- 内存映射 IO 概念详细信息
- 为什么 du -sh 输出错误大小的内存映射文件
- 您可以将C 对象映射到内存映射的外围设备吗?
- 将 Android 内存映射到具有零拷贝的 GraphicBuffer
- 在内存映射时写入内存映射的文件
- 如何使用 Boost 内存映射解析 C++ 中的 CSV?
- Growing Boost.使用单个写入器的进程间内存映射文件
- 调整窗口内存映射文件的大小,而不会使指针失效
- Winapi:是否需要在可执行内存映射的文件上调用FlushInstructionCache
- 与从C++到C#的内存映射文件共享链式结构
- 在 C++ 和 C# 之间共享内存映射文件结构