关于C#与C++共享内存空间时string类型映射的问题

首先是网上抄来的方法。

C#程序创建共享空间

public struct ServiceMsg
    {
        public int Id;
        public long NowTime;
        public string Message;
    }
public unsafe void CreateShare()
        {
            //定义内存大小
            int size = 1024;

            //创建共享内存
            MemoryMappedFile shareMemory = MemoryMappedFile.CreateOrOpen("shareTest", size);
            Debug.WriteLine("创建共享内存完成...");
            var stream = shareMemory.CreateViewStream(0, size);

            ServiceMsg serviceMsg = new ServiceMsg()
            {
                Id = 1,
                NowTime = DateTime.Now.Ticks,
                Message = "Im CSharp"
            };
            Debug.WriteLine($"写入数据 id{serviceMsg.Id} , nowTime{serviceMsg.NowTime}, message{serviceMsg.Message}");
            int typeSize = Marshal.SizeOf(serviceMsg);
            byte[] data = new byte[typeSize];
            fixed (byte* pb = &data[0])
            {
                Marshal.StructureToPtr(serviceMsg, new IntPtr(pb), true);
            }
            stream.Write(data);

            //线程等待10秒
            System.Threading.Thread.Sleep(10000);
            stream.Dispose();
        }

C++程序接入共享内存

struct ServiceMsg
{
    int Id;
    INT64 NowTime;
    char* Message;
};

int main()
{
    LPVOID pBuffer;
    string strMapName("shareTest");
    HANDLE hMap = OpenFileMapping(FILE_MAP_ALL_ACCESS, 0, strMapName.c_str());
    if (NULL == hMap)
    {
        cout << "无共享内存..." << endl;
    }
    else
    {
        while (true)
        {
            Sleep(1000);
            pBuffer = MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
            ServiceMsg* data = (ServiceMsg*)pBuffer;
            //std::string cliToStd = marshal_as<std::string>(data->Message);
            cout << "读取共享内存数据:Id:" << data->Id << "NowTime:" << data->NowTime << "Message:" << data->Message << endl;
        }
    }
}

运行结果:C++只能获取Id和NowTime字段的值,Message无法获取。

查找原因:

1.查看C#内存发现Message存放的是一个指针,指向了C#进程空间的地址。

 很明显,圈出来的地方就是Message存放的地址,转到该地址0x000001BA7884D3B0就是我们Message的内容。

 2.既然C#将地址写入了共享内存,那么来看看C++中该地址是什么。

 转到该地址,什么也没有,这地址不在C++程序的内存范围内。Message的地址当然不在C++的内存空间中。

解决问题:

我们可以给Messahe字段加上[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 30)]特性,注意SizeConst需要大于等于你给定的字符串长度,否则会截取。

然后在C++中使用char[]接收Message

    //C#
    public struct ServiceMsg
    {
        public int Id;
        public long NowTime;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 30)]
        public string Message;
    }

    //C++
    struct ServiceMsg
    {
        int Id;
        INT64 NowTime;
        char Message[];
    };

 查看结果:

 

 

 其他:

我尝试在C++中使用std::string来接收Message,但发现其指向了p字符,不太清楚怎么回事,对C++还是不太熟悉。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 共享内存是一种进程间通信方式,它使得在内存中创建一段可以被多个进程共享并访问的内存空间。这可以提高进程间的通信效率,因为在共享内存中的数据不需要使用复杂的消息传递机制来传递。 在C语言中,通过使用共享内存,可以非常方便地在不同的进程之间共享数据,而避免使用其他进程间通信方式(如管道、消息队列等)。要使用共享内存,在C语言中可以使用system V或POSIX标准的共享内存函数库,如shmget、shmctl等函数来进行共享内存的创建和管理。例如,可以使用shmget函数来创建共享内存区域,然后使用shmat函数将其映射到进程的地址空间中,实现对共享内存的访问。 需要注意的是,在使用共享内存,需要保证进程之间对共享内存的读写操作的互斥性,以避免数据的不一致性和冲突。因此,在使用共享内存,通常需要使用信号量、互斥锁等机制来对共享内存进行同步和保护。 总的来说,共享内存在C语言中的应用广泛,可以用来实现进程之间高效、快速的数据共享,同也需要一定的技术和经验来有效地使用和管理。 ### 回答2: 共享内存是一种进程间通信的方式,它可以让多个进程之间快速、高效地共享数据。在共享内存中,几个进程可以通过一个共享的内存区域来访问同一组数据。这种方式通常比其他的进程间通信方式,比如管道、消息队列等更快速、更高效。 在C语言中,我们可以使用系统提供的共享内存函数来创建、读取、写入、删除共享内存。在创建共享内存,我们需要指定共享内存的大小,并且需要给共享内存分配一个标识符,这个标识符可以让多个进程之间访问同一个共享内存。 在读写共享内存,我们需要先将共享内存映射到当前进程的空间中,然后就可以通过指针访问共享内存中的数据了。在访问完共享内存后,我们需要将共享内存从当前进程的空间中解除映射,以免出现内存泄漏等问题。 总之,共享内存是一种非常有用的进程间通信方式,它可以帮助多个进程高效地共享数据。因此,我们在编写多进程程序,可以尝试使用共享内存来提高程序的效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值