C# 通过共享内存的方式给python传递一张图片

C# 通过共享内存的方式给Python传递一张图片

简介: 需求是需要传到python中一张图片,然后通过python进行处理,我想到了一种进程间通信的方法,共享内存,我的理解就是开辟一块内存,A向内存里面写数据,B再去读取这块内存的数据。

C# 主程序代码

using System;
using System.IO;
using System.IO.MemoryMappedFiles;
using System.Text;
using System.Diagnostics;
using HalconDotNet;

class Program
{
    static void Main()
    {
        // 共享内存名称
        string sharedMemoryName = "TestSharedMemory";

        HImage hImage = new HImage(@"F:\test1.bmp");


        // 要传递的数据
        string message = "Hello from C#! 这是来自C#的消息。";
        int number = 12345;
        double value = 3.14159;

        Console.WriteLine("C#程序启动...");
        Console.WriteLine($"要发送的消息: {message}");
        Console.WriteLine($"要发送的整数: {number}");
        Console.WriteLine($"要发送的浮点数: {value}");

        // 创建共享内存
        using (MemoryMappedFile mmf = MemoryMappedFile.CreateOrOpen(sharedMemoryName, 1024))
        using (MemoryMappedViewAccessor accessor = mmf.CreateViewAccessor())
        {
            // 写入字符串
            byte[] messageBytes = Encoding.UTF8.GetBytes(message);
            accessor.Write(0, messageBytes.Length); // 在位置0写入字符串长度
            accessor.WriteArray(4, messageBytes, 0, messageBytes.Length); // 从位置4开始写入字符串

            // 写入整数(位置100)
            accessor.Write(100, number);

            // 写入浮点数(位置104)
            accessor.Write(104, value);

            // 写入完成标志(位置112)
            accessor.Write(112, 1);

            Console.WriteLine("\n数据已写入共享内存!");

            // 启动Python程序
            StartPythonProgram();

            Console.WriteLine("按任意键退出...");
            Console.ReadKey();
        }
    }

    static void StartPythonProgram()
    {
        try
        {
            // 获取当前目录
            string currentDir = Directory.GetCurrentDirectory();
            string pythonScriptPath = @"C:\Users\Administrator\Desktop\pythonProject3\main.py";

            Console.WriteLine($"正在启动Python脚本: {pythonScriptPath}");

            ProcessStartInfo start = new ProcessStartInfo();
            start.FileName = "python";
            start.Arguments = $"\"{pythonScriptPath}\"";
            start.UseShellExecute = false;
            start.RedirectStandardOutput = true;
            start.RedirectStandardError = true;
            start.CreateNoWindow = true;

            int index = 1;
            while(true)
            {

                using (Process process = Process.Start(start))
                {
                    // 读取Python输出
                    string output = process.StandardOutput.ReadToEnd();
                    string error = process.StandardError.ReadToEnd();

                    process.WaitForExit();

                    if (!string.IsNullOrEmpty(output))
                        Console.WriteLine($"Python输出:\n{output}");

                    if (!string.IsNullOrEmpty(error))
                        Console.WriteLine($"Python错误:\n{error}");
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"启动Python程序失败: {ex.Message}");
            Console.WriteLine("请确保Python已安装并在PATH环境变量中");
        }
    }
}

C# 代码

using System;
using System.IO.MemoryMappedFiles;
using System.Runtime.InteropServices;
using HalconDotNet;

public class SharedMemorySender
{
    public unsafe void SendHObject(HObject image, string mapName = "HalconImageSharedMem")
    {
        MemoryMappedFile mmf = null;
        MemoryMappedViewAccessor accessor = null;

        try
        {
            // 获取图像指针和基本信息
            HOperatorSet.GetImagePointer1(image, out HTuple pointer, out HTuple type, out HTuple width, out HTuple height);

            // 计算图像数据大小
            int pixelSize = GetPixelSize(type);
            int imageDataSize = width.I * height.I * pixelSize;

            // 创建内存映射文件 (大小 = 图像数据 + 4个int头部信息)
            int headerSize = sizeof(int) * 4;
            int totalSize = headerSize + imageDataSize;
            mmf = MemoryMappedFile.CreateNew(mapName, totalSize);

            // 获取访问器并写入头部信息
            accessor = mmf.CreateViewAccessor();
            int offset = 0;

            // 明确指定类型
            accessor.Write(offset, width.I);
            offset += sizeof(int);
            accessor.Write(offset, height.I);
            offset += sizeof(int);
            accessor.Write(offset, pixelSize);
            offset += sizeof(int);

            // 将类型字符串转换为整数编码
            int typeCode = GetTypeCode(type.S);
            accessor.Write(offset, typeCode);
            offset += sizeof(int);

            // 将图像数据拷贝到共享内存 - 使用不安全上下文
            byte* source = (byte*)pointer.L;
            for (int i = 0; i < imageDataSize; i++)
            {
                accessor.Write(offset + i, source[i]);
            }

            Console.WriteLine($"图像已写入共享内存: {width}x{height}, 类型: {type}, 大小: {imageDataSize}字节");
            Console.WriteLine("按任意键退出...");
            Console.ReadKey();
        }
        finally
        {
            accessor?.Dispose();
            mmf?.Dispose();
        }
    }

    private int GetPixelSize(HTuple imageType)
    {
        switch (imageType.S)
        {
            case "byte": return 1;
            case "uint2": return 2;
            case "int4": return 4;
            default: throw new ArgumentException($"不支持的图像类型: {imageType}");
        }
    }

    private int GetTypeCode(string typeString)
    {
        switch (typeString)
        {
            case "byte": return 1;
            case "uint2": return 2;
            case "int4": return 4;
            default: return 1; // 默认byte
        }
    }
}

Python代码

import mmap
import struct

index = 1

def read_shared_memory():
    try:
        print("Python程序启动...")
        print("正在读取共享内存...")


        # 打开共享内存
        # 注意:在Windows上使用命名共享内存,在Linux上使用文件映射
        mm = mmap.mmap(-1, 1024, tagname='TestSharedMemory', access=mmap.ACCESS_READ)

        # 读取字符串长度(4字节整数)
        str_length_bytes = mm.read(4)
        str_length = struct.unpack('I', str_length_bytes)[0]  # 'I' 表示无符号整数

        # 读取字符串内容
        string_data = mm.read(str_length).decode('utf-8')

        # 跳转到整数位置(100)
        mm.seek(100)
        number_data = struct.unpack('i', mm.read(4))[0]  # 'i' 表示有符号整数

        # 读取浮点数(104)
        mm.seek(104)
        value_data = struct.unpack('d', mm.read(8))[0]  # 'd' 表示双精度浮点数

        # 读取完成标志(112)
        mm.seek(112)
        flag = struct.unpack('i', mm.read(4))[0]

        mm.close()

        print("\n从C#程序接收到的数据:")
        print(f"字符串: {string_data}")
        print(f"整数: {number_data}")
        print(f"浮点数: {value_data}")
        print(f"完成标志: {flag}")

        # 返回成功信息
        return "Python程序执行成功!"

    except Exception as e:
        error_msg = f"读取共享内存失败: {str(e)}"
        print(error_msg)
        return error_msg

def main():
    # 你的主要逻辑
    return "==" + str(index)

if __name__ == "__main__":
    # result = read_shared_memory()
    # print(f"\n执行结果: {result}")
    index = index + 1
    exit(main())
posted @ 2025-11-12 10:58  杰西卡若  阅读(6)  评论(0)    收藏  举报