C#和python端通信之使用共享内存

news2024/12/25 9:40:11

一、前言

    本篇主要实验通过使用共享内存实现C#端代码和python端代码之间的通信,主要目的是相较于直接传输较大的数据(例如图像数据),该方式更节省时间。

二、代码

C#端:

    创建了一个大小为1的共享内存,名为flag1,存放一个byte变量,初始写入0

    创建了一个大小为1的共享内存,名为done,存放一个byte变量,初始写入1

    创建了一个大小为1024 * 16的共享内存,名为result,存放一个string变量,初始写入""

     之后读取图像,并创建和写入至一个大小为960*640*4的共享内存,名为cam1,存放一个byte[]变量 , 然后 flag1 写入1,循环读取done内存,若为1,则将result 内存读取出为string 并显示textBox1

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.Drawing.Imaging;
using System.IO.MemoryMappedFiles;
using System.Runtime.InteropServices;


namespace testShareMemory
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void test_0()
        {
            // 读取图片
            string imagePath = "E:/cshape_test/testShareMemory/001.png";
            Bitmap bitmap = new Bitmap(imagePath);

            // 确保图片大小为960x640
            if (bitmap.Width != 960 || bitmap.Height != 640)
            {
                Console.WriteLine("图片尺寸不符合要求,必须为960x640");
                return;
            }
            MemoryMappedFile mmfCam1 = MemoryMappedFile.CreateOrOpen("cam1", bitmap.Width * bitmap.Height * 4);
            MemoryMappedViewAccessor accessor = mmfCam1.CreateViewAccessor();

            BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
            byte[] buffer = new byte[bitmapData.Stride * bitmapData.Height];
            Marshal.Copy(bitmapData.Scan0, buffer, 0, buffer.Length);
            accessor.WriteArray(0, buffer, 0, buffer.Length);
            bitmap.UnlockBits(bitmapData);

            // 创建共享内存 flag , 并写入1
            var flagMMF = MemoryMappedFile.CreateOrOpen("flag1", 1);
            var flagAccessor = flagMMF.CreateViewAccessor();
            byte flagToWrite = 1;
            flagAccessor.Write(0, flagToWrite);

            //创建共享内存 done , 并写入0
            var doneMMF = MemoryMappedFile.CreateOrOpen("done", 1);
            var doneAccessor = doneMMF.CreateViewAccessor();
            byte doneToWrite = 0;
            doneAccessor.Write(0, doneToWrite);

            //创建共享内存 result , 并写入""
            int res_lens = 1024 * 32;
            MemoryMappedFile mmfResult = MemoryMappedFile.CreateOrOpen("result", res_lens);
            MemoryMappedViewAccessor resAccessor = mmfResult.CreateViewAccessor();
            byte[] strBytes = Encoding.UTF8.GetBytes("");
            //resAccessor.Write(0, strBytes.Length); // 首先写入字符串长度
            resAccessor.WriteArray(0, strBytes, 0, strBytes.Length); // 然后写入字符串字节内容

            // 循环间隔1秒,读取共享内存
            bool done = false;
            int search_times = 0;
            while (!done)
            {

                byte doneValue = doneAccessor.ReadByte(0);
                byte flagValue = flagAccessor.ReadByte(0);

                if (doneValue == 1 && flagValue == 2)
                {
                    // 读取共享内存"result"
                    string result;

                    // 读取字符串长度(前4个字节)
                    int length = resAccessor.ReadInt32(0);

                    // 创建字节数组来存储字符串数据
                    byte[] buffer_str = new byte[length];

                    // 从共享内存读取字符串数据
                    resAccessor.ReadArray(4, buffer_str, 0, length);

                    // 将字节数组转换为字符串
                    string resultString = Encoding.UTF8.GetString(buffer_str);
                    textBox1.Text = "查询到的结果为: " + resultString;

                    done = true; // 设置标志,退出循环

                }
                else
                {
                    // 等待一段时间再继续轮询
                    System.Threading.Thread.Sleep(1000); // 等待1秒
                    search_times++;


                    if (search_times > 100)
                    {
                        //Console.WriteLine("查询超时!"   );
                        textBox1.Text = "查询超时!";
                        break;
                    }
                }
            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {

            test_0();
        }
    }
}

python端:

    循环读取flag1共享内存,若为1,则读取cam1数据,还原为图像数据,将2写入flag1,并将json字符串data写入result内存区,将1写入done,显示图像数据

# -*- coding: utf-8 -*-
"""
Created on Tue Feb 27 17:10:01 2024

@author: WIN10
"""

import os , cv2
import numpy as np

from multiprocessing import shared_memory
import time
import struct

import json

# 创建/打开共享内存
def create_or_open_shared_memory(name, size):
    try:
        shm = shared_memory.SharedMemory(create=False, name=name)
    except FileNotFoundError:
        shm = shared_memory.SharedMemory(create=True, name=name, size=size)
    return shm

def main():

    flag_name = "flag1"
    cam1_name = "cam1"
    done_name = "done"

    # 图像大小
    width, height, channels = 960, 640, 4
    image_size = width * height * channels

    flag_shm = create_or_open_shared_memory(flag_name, size=1)  # 1个字节,用 uint8
    flag_array = np.ndarray((1,), dtype= np.uint8  , buffer=flag_shm.buf)

    done_shm = create_or_open_shared_memory(done_name, size=1)
    done_array = np.ndarray((1,), dtype=np.uint8, buffer=done_shm.buf)

    # 初始化 cam1 共享内存
    cam1_shm = create_or_open_shared_memory(cam1_name, size=image_size)
    cam1_array = np.ndarray((height, width, channels), dtype=np.uint8, buffer=cam1_shm.buf)

    res_shm =  create_or_open_shared_memory("result", size= 1024*16 )


    while True:
        if flag_array[0] == 1:
            # 读取图像数据
            image_rgba = np.copy(cam1_array)
            img  = cv2.cvtColor(image_rgba, cv2.COLOR_RGBA2RGB)  #C#端的bitmap传过来的是4通道的,应该转为3通道

            # 将 2 写入 flag
            flag_array[0] = 2

            #写入 jason字符串到 result
            data = {
                "name": "Mario",
                "age": 28,
            }
            json_str = json.dumps(data)
            json_bytes = json_str.encode('utf-8')
            res_shm.buf[:4] = struct.pack('i', len(json_bytes))
            res_shm.buf[4:4 + len(json_bytes)] = json_bytes

            done_array[0] = 1  #done 区域写入1

            # 显示读取到的图像
            cv2.imshow('Shared Memory Image', img )
            cv2.waitKey(0)

            break

        # 每隔100毫秒检测一次
        time.sleep(0.1)
 
    # 关闭共享内存
    cam1_shm.close()
    flag_shm.close()
    res_shm.close()
    done_shm.close()


if __name__=="__main__":
    main()

三、运行结果

   先运行C# ,再运行python端

python端结果,显示接受到的图像

C#端结果,显示收到python端写入的json字符串

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1847336.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Docker容器基础知识,即linux日常运维命令

Docker 是一个流行的用 Go 语言开发的开源项目,基于Linux内核的cgroup、namespace及 AUFS 等技术,对进程进行封装隔离,由 Dotcloud 公司开发。Docker已成为容器行业的事实标准。 小陈发现一个有趣的事情,容器的英文是Container&am…

数据通信与网络(三)

物理层概述: 物理层是网络体系结构中的最低层 它既不是指连接计算机的具体物理设备,也不是指负责信号传输的具体物理介质, 而是指在连接开放系统的物理媒体上为上一层(指数据链路层)提供传送比特流的一个物理连接。 物理层的主要功能——为…

MDK-ARM 编译后 MAP 文件分析

本文配合 STM32 堆栈空间分布 食用更佳! 一图胜千言。。。

U盘文件夹损坏0字节:现象解析、恢复方法与预防措施

在日常工作和生活中,U盘因其便携性和大容量成为我们存储和传输数据的重要工具。然而,当U盘中的文件夹突然损坏并显示为0字节时,我们可能会感到困惑和焦虑。本文将对U盘文件夹损坏0字节的现象进行详细描述,分析其可能的原因&#x…

[Qt]Qt框架解析:从入门到精通,探索平台开发的无限可能

一、Qt的概述 Qt是一个跨平台的C图形用户界面应用程序框架(GUI)。它为应用程序开发者提供建立艺术级图形界面所需的所有功能。它是完全面向对象的,很容易扩展,并且允许真正的组件编程。开发环境为Qt creator5.8.0,下载…

【MATLAB源码-第229期】基于matlab的有源功率因数校正仿真,采用PI调节改善功率因数;改善后达到99%.

操作环境: MATLAB 2022a 1、算法描述 一、整体结构概述 有源功率因数校正(APFC)是一种用于提高电力系统功率因数的技术,通过控制电流的波形,使其与电压的波形保持一致,从而减少无功功率的产生&#xff…

原来这个东西叫 Docker

大家好,我是徒手敲代码。 今天来聊聊 Docker 三个时代的演变 首先要先了解 Docker 出现的背景。在计算机技术的发展历程中,我们经历了从物理机时代到虚拟机时代,再到容器化时代的演变。 在物理机时代,应用程序直接运行在物理服务…

精准测试与传统的手工测试

大部分测试从业人员都经历了手工测试到自动化测试递进,测试技术及思路都发生了日新月异的变化,有些中厂及大厂都有一套强大且复杂的自动化测试用例时刻保障产品的稳定性及正确性。 所谓精准测试,就是借助一定的技术手段、通过算法的辅助对传…

游戏遇到攻击有什么办法能解决?

随着网络技术的飞速发展,游戏行业在迎来繁荣的同时,也面临着日益严峻的网络威胁。黑客攻击、数据泄露、DDoS攻击等安全事件频发,给游戏服务器带来了极大的挑战。面对愈演愈烈的网络威胁,寻找一个能解决游戏行业攻击问题的安全解决…

【Matlab】CNN-LSTM分类 卷积神经网络-长短期记忆神经网络组合模型(附代码)

资源下载: https://download.csdn.net/download/vvoennvv/89466499 分类算法资源合集:https://download.csdn.net/download/vvoennvv/89466519 目录 Matlab SVM支持向量机分类算法 Matlab RF随机森林分类算法 Matlab RBF径向基神经网络分类算法 Ma…

容器之事件盒

代码&#xff1a; #include <gtk-2.0/gtk/gtk.h> #include <glib-2.0/glib.h> #include <gtk-2.0/gdk/gdkkeysyms.h> #include <stdio.h>static void label_const(GtkWidget *eventbox) {static int i 0;static char citem[100];sprintf(citem, &quo…

OrangePi连接Wi-Fi步骤

下面介绍的是用终端命令行的方式配置WIFI&#xff1a; 首先输入以下命令用于扫描并查看周围的WiFi热点。也可以直接连接。 nmcli dev wifi之后会在终端打出周围所有可以连接的WiFi&#xff0c;按方向键上下可以查看显示更多&#xff0c;按q键退出。 然后同样使用nmcli命令连接…

Java中setLineWrap(true)和setWrapStyleWord(true)优化TextArea

在 Java Swing 开发中&#xff0c;JTextArea 是一个多行的文本区域组件&#xff0c;常用于显示和编辑大量文本。当处理长文本时&#xff0c;默认行为是不换行并且出现水平滚动条&#xff0c;这通常会降低用户体验。幸运的是&#xff0c;JTextArea 提供了两个非常有用的方法&…

解决Few-shot问题的两大方法:元学习与微调

基于元学习&#xff08;Meta-Learning&#xff09;的方法&#xff1a; Few-shot问题或称为Few-shot学习是希望能通过少量的标注数据实现对图像的分类&#xff0c;是元学习(Meta-Learning)的一种。 Few-shot学习&#xff0c;不是为了学习、识别训练集上的数据&#xff0c;泛化…

【面试题分享】重现 string.h 库常用的函数

文章目录 【面试题分享】重现 string.h 库常用的函数一、字符串复制1. strcpy&#xff08;复制字符串直到遇到 null 终止符&#xff09;2. strncpy&#xff08;复制固定长度的字符串&#xff09; 二、字符串连接1. strcat&#xff08;将一个字符串连接到另一个字符串的末尾&…

小程序 获取插件用户openpid?

接口英文名 getPluginOpenPId 功能描述 通过 wx.pluginLogin 接口获得插件用户标志凭证 code 后传到开发者服务器&#xff0c;开发者服务器调用此接口换取插件用户的唯一标识 openpid。 调用方式 HTTPS 调用 第三方调用 调用方式以及出入参和HTTPS相同&#xff0c;仅是调…

慢阻肺患者为何容易营养不良?朗格力教你轻松改善

#肺科营养#朗格力#班古营养#复合营养素#肺部营养#肺部健康# 慢阻肺是我国常见的、高患病率的慢性呼吸系统疾病,会对肺结构和功能产生影响,从而引起各种不良反应,其中营养不良是常见并发症之一。慢阻肺为什么会发生营养不良?营养不良又是怎么伤害慢阻肺的呢?为什么像班古精准…

深度学习之绘图基础

文章目录 1.实验目的2. 需求3.代码结果图片 1.实验目的 熟练绘制各种图像&#xff0c;为深度学习打基础 2. 需求 给定一个函数&#xff0c;需要你画出原图像以及这个函数在某点切线图像 3.代码 # File: python绘制函数图像以及倒数图像.py # Author: chen_song # Time: 20…

【2024最新华为OD-C/D卷试题汇总】[支持在线评测] LYA的测试用例执行计划(100分) - 三语言AC题解(Python/Java/Cpp)

🍭 大家好这里是清隆学长 ,一枚热爱算法的程序员 ✨ 本系列打算持续跟新华为OD-C/D卷的三语言AC题解 💻 ACM银牌🥈| 多次AK大厂笔试 | 编程一对一辅导 👏 感谢大家的订阅➕ 和 喜欢💗 📎在线评测链接 https://app5938.acapp.acwing.com.cn/contest/2/problem/OD…

【尚庭公寓SpringBoot + Vue 项目实战】移动端浏览历史(二十二)

【尚庭公寓SpringBoot Vue 项目实战】移动端浏览历史&#xff08;二十二&#xff09; 文章目录 【尚庭公寓SpringBoot Vue 项目实战】移动端浏览历史&#xff08;二十二&#xff09;1、业务介绍2.接口开发2.1.分页查询浏览历史列表2.2.保存浏览历史 1、业务介绍 浏览历史指的…