繁体   English   中英

在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#结构中我能想到的所有组合(字节[],字符串,不安全的结构等),但是我失败了。

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

示例工作代码将不胜感激。

要共享字符串,您需要正确映射它们: 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<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);
            }
        }
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM