Windows平台C++与Python命名共享内存传图黑屏问题排查
问题分析与解决方案
核心问题:Windows下共享内存命名空间不兼容
Boost.Interprocess在Windows平台创建共享内存时,默认会将名称放入Local命名空间(前缀为Local\),而Python的mmap模块直接使用传入的名称时,不会自动添加该前缀,导致Python实际打开的是一个全新的空共享内存,因此读取到全0数据,显示黑屏。
分步修复方案
1. 统一共享内存命名规则
方案A:修改C++代码显式指定命名空间
在创建共享内存时,直接使用带Local\前缀的名称:
#define SHM_NAME "Local\\SharedMemory"
方案B:修改Python代码添加前缀
将Python中的共享内存名称改为:
SHM_NAME = "Local\\SharedMemory"
2. 修正BMP文件的读取逻辑
BMP文件包含54字节的文件头+信息头,直接写入整个文件会导致头部数据被当成像素值。需要只写入像素数据:
在C++代码中,读取文件时跳过前54字节:
// 跳过BMP文件头(54字节) imageFile.seek(54); // 再执行拷贝操作 auto end = std::copy(std::istreambuf_iterator<char>(imageFile), std::istreambuf_iterator<char>(), static_cast<char*>(region.get_address())); // 验证写入字节数 size_t bytes_written = std::distance(std::istreambuf_iterator<char>(imageFile), end); if (bytes_written != (BYTES_NUMBER - 54)) { std::cerr << "Failed to write full image data to shared memory." << std::endl; return 1; }
同时注意调整BYTES_NUMBER为实际像素数据的大小(原文件大小-54)。
3. 匹配BMP的像素格式
BMP文件默认存储像素为BGR顺序,而你Python代码中指定的是RGB格式,这会导致颜色错乱甚至黑屏。修改Python代码的格式参数:
# 先按BGR读取,再转换为RGB image = Image.frombytes("BGR", (IMAGE_WIDTH, IMAGE_HEIGHT), image_data, "raw").convert("RGB")
4. 验证共享内存数据完整性
在Python读取后,可以先检查数据是否全0:
if all(b == 0 for b in image_data): print("Error: Read all zero data from shared memory") else: print(f"Read {len(image_data)} bytes, first 10 bytes: {image_data[:10]}")
修正后的完整代码示例
C++代码
#include <boost/interprocess/shared_memory_object.hpp> #include <boost/interprocess/mapped_region.hpp> #include <iostream> #include <fstream> #include <iterator> using namespace boost::interprocess; #define SHM_NAME "Local\\SharedMemory" #define PIXEL_BYTES 541744 // 原文件大小541798 - 54字节头 int main() { try { shared_memory_object shm(open_or_create, SHM_NAME, read_write); shm.truncate(PIXEL_BYTES); mapped_region region(shm, read_write); std::ifstream imageFile("input.bmp", std::ios::binary); if (!imageFile) { std::cerr << "Failed to open the image file." << std::endl; return 1; } // 跳过BMP文件头 imageFile.seekg(54); if (!imageFile) { std::cerr << "Image file is too small to be a valid BMP." << std::endl; return 1; } auto start = std::istreambuf_iterator<char>(imageFile); auto end_iter = std::istreambuf_iterator<char>(); auto copy_end = std::copy(start, end_iter, static_cast<char*>(region.get_address())); size_t bytes_written = std::distance(start, copy_end); if (bytes_written != PIXEL_BYTES) { std::cerr << "Only wrote " << bytes_written << " bytes, expected " << PIXEL_BYTES << std::endl; return 1; } imageFile.close(); std::cout << "Image pixel data successfully written to shared memory." << std::endl; std::string command = "python sharedMemory.py"; std::system(command.c_str()); std::cout << "Press any key to exit." << std::endl; _getch(); // 清理共享内存 shared_memory_object::remove(SHM_NAME); } catch (const std::exception& e) { std::cerr << "Error: " << e.what() << std::endl; shared_memory_object::remove(SHM_NAME); return 1; } return 0; }
Python代码
import mmap from PIL import Image SHM_NAME = "Local\\SharedMemory" PIXEL_BYTES = 541744 IMAGE_WIDTH = 511 IMAGE_HEIGHT = 265 if __name__ == "__main__": try: shm = mmap.mmap(-1, PIXEL_BYTES, SHM_NAME) image_data = shm.read(PIXEL_BYTES) shm.close() if all(b == 0 for b in image_data): print("Error: Read all zero data from shared memory") else: # BMP像素是BGR顺序,转换为RGB显示 image = Image.frombytes("BGR", (IMAGE_WIDTH, IMAGE_HEIGHT), image_data, "raw").convert("RGB") image.show() except Exception as e: print(f"Error: {e}")
内容的提问来源于stack exchange,提问作者am_289
相关产品推荐
相关产品推荐

