c# - 读取内存内存映射文件 C++ 和 C#

标签 c# c++ windows memory-mapped-files

我正在尝试使用内存映射文件共享一个从 C++ 到 C# 的结构。到目前为止,我设法在文件上写入,但无法读取 C# 中的内容。

  1. 用 C++ 发送数据
struct Bus_1553 // this is the structure to send
{
    string name;
    int directions; 
};

struct Bus_1553* p_1553; // set the pointer to it
HANDLE handle; // create the handle


// here we define the data to send
string name = "IFF";
int directions = 3;

bool startShare() // Open the shared memory
{
    try
    {
        handle = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(Bus_1553), L"DataSend");
        p_1553 = (struct Bus_1553*) MapViewOfFile(handle, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, sizeof(Bus_1553));
        return true;
    }
    catch (...)
    {
        return false;
    }

}


int main()
{

    if (startShare() == true)
    {

        while (true)
        {
            if (p_1553 != 0) // populate the memory
            {  

                p_1553->name = name;
                p_1553->directions = directions;
            }

            else
                puts("create shared memory error");
        }
    }
    if (handle != NULL)
        CloseHandle(handle);
    return 0;
} 
  1. 尝试用 C# 阅读
namespace sharedMemoryGET
{
    class sharedMemoryGET
    {
        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        public unsafe struct Bus_Data_1553
        {
            public string name;
            public int directions; // which directions used
        }

        public static MemoryMappedFile mmf;
        public static MemoryMappedViewStream mmfvs;

        static public bool MemOpen() // open the mapped file
        {
            try
            {
                mmf = MemoryMappedFile.OpenExisting("DataSend");
                return true;
            }
            catch
            {
                return false;
            }

        }

        public static void readData()
        {
            if (MemOpen())
                {
                    using (var accessor = mmf.CreateViewAccessor())
                    {
                    accessor.Read(0, out Bus_Data_1553 a);
                    Console.WriteLine(a.name);
                    Console.WriteLine(a.directions);
                    }
                }
            
        }
    }
} 

当要共享的结构中存在字符串时,出现以下错误: 指定的类型必须是不包含引用的结构。

当我删除字符串并仅共享 int 方向时,我得到的值为 0。有人可以帮我解决这个问题吗?

最佳答案

让我们从 C++ 版本的错误开始。我将其加粗以确保没有人忽略它,这非常重要:永远不要将指针写入磁盘

std::string 是一个指针(实际上是 2 个指针)的包装器,它根据需要为您处理分配和重新分配。您绝对不能将它们写入任何地方的"file",您必须改为写入这些指针的内容。

一种简单的方法(在 C 中很流行)是简单地定义一个足够大的缓冲区来保存您的数据,然后根据需要使用它:

struct Bus_1553 // this is the structure to send
{
    char name[128];
    int directions; 
};

要写入 name,请使用 strcpy_s 或您的操作系统等效项。

现在,一旦您用 C++ 将此结构写入共享文件,用 C# 读取它就是让系统(编码器)将大量字节解码为有用的托管对象。您可以通过在结构和字段定义上使用属性来做到这一点:

    [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
    public struct Bus_Data_1553
    {
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
        public string name;
        public int directions; // which directions used
    }

此外,如果您正确使用编码器,则不需要 unsafe

关于c# - 读取内存内存映射文件 C++ 和 C#,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62937645/

相关文章:

c++ - 打印小于 100 的质数

windows - git 认为文件已更改

c# - 如何在 DataBind 后隐藏 GridView 中的列?

c# - 更改背景颜色自定义 C#

c# - native dll 中的动态内存分配

c++ - 为什么下面代码的输出是: DoSecond

node.js - Windows 上监听 1880 端口失败

Windows systemprofile 目录根据用户显示不同

c# - 成员资格远程连接字符串在 SQL Server Management Studio 中有效但在 ASP.NET 中无效(错误 26)

c# - 使用Spring.Net,如何在控制台应用程序中托管WCF服务?