Windows平台Python与C++共享内存交互实现示例请求
On Windows, Qt's QSharedMemory automatically prefixes the provided key with a namespace derived from the application's executable path to avoid naming collisions. This means even if you use the same key string in your C++ and Python programs, the actual native shared memory names will differ, leading to cross-process access failure.
To bypass Qt's automatic key transformation, use the setNativeKey() method to specify the exact Windows shared memory name. On Windows, you can prefix the name with Global\\ for cross-user session access, or Local\\ for the current user session (default if no prefix).
C++ Implementation
#include <QSharedMemory> #include <QDebug> #include <cstring> int main(int argc, char** argv) { QSharedMemory memory; // Use a global native key for cross-process access memory.setNativeKey("Global\\StreamSharedMemory"); // Create or attach to shared memory (1MB size) if (!memory.create(1024 * 1024)) { if (memory.error() == QSharedMemory::AlreadyExists) { if (!memory.attach()) { qDebug() << "Attach failed:" << memory.errorString(); return 1; } qDebug() << "Attached to existing shared memory"; } else { qDebug() << "Create failed:" << memory.errorString(); return 1; } } else { qDebug() << "Created new shared memory"; } // Example: Write sample data to shared memory if (memory.isAttached()) { char* data = static_cast<char*>(memory.data()); const char* sample = "Data from C++ service"; std::strncpy(data, sample, memory.size()); } // Keep process running to test Python access qDebug() << "Press Enter to exit..."; std::getchar(); memory.detach(); return 0; }
Python Implementation
from PyQt5.QtCore import QSharedMemory import sys memory = QSharedMemory() # Match the same native key used in C++ memory.setNativeKey("Global\\StreamSharedMemory") if not memory.attach(): print(f"Attach failed: {memory.errorString()}") sys.exit(1) # Example: Read data from shared memory data_ptr = memory.data() if data_ptr: raw_data = data_ptr.toByteArray().data() message = raw_data.decode('utf-8').strip('\x00') print(f"Received data: {message}") memory.detach()
If you prefer using raw Windows API instead of Qt, here are cross-process compatible examples:
C++ with Windows API
#include <windows.h> #include <iostream> #include <cstring> int main() { const wchar_t* shm_name = L"Global\\WinAPISharedMemory"; const size_t shm_size = 1024 * 1024; // Create or open shared memory mapping HANDLE h_map = CreateFileMappingW( INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, shm_size, shm_name ); if (!h_map) { std::cout << "CreateFileMapping failed: " << GetLastError() << std::endl; return 1; } // Map view of the shared memory char* p_buf = static_cast<char*>(MapViewOfFile( h_map, FILE_MAP_ALL_ACCESS, 0, 0, shm_size )); if (!p_buf) { std::cout << "MapViewOfFile failed: " << GetLastError() << std::endl; CloseHandle(h_map); return 1; } // Write sample data const char* sample = "Data from Windows API C++"; std::strncpy(p_buf, sample, shm_size); std::cout << "Press Enter to exit..." << std::endl; std::getchar(); // Cleanup UnmapViewOfFile(p_buf); CloseHandle(h_map); return 0; }
Python with ctypes
import ctypes from ctypes import wintypes # Load Windows kernel32 library kernel32 = ctypes.WinDLL('kernel32', use_last_error=True) # Define API functions and types CreateFileMappingW = kernel32.CreateFileMappingW CreateFileMappingW.argtypes = [wintypes.HANDLE, wintypes.LPCVOID, wintypes.DWORD, wintypes.DWORD, wintypes.DWORD, wintypes.LPCWSTR] CreateFileMappingW.restype = wintypes.HANDLE MapViewOfFile = kernel32.MapViewOfFile MapViewOfFile.argtypes = [wintypes.HANDLE, wintypes.DWORD, wintypes.DWORD, wintypes.DWORD, wintypes.SIZE_T] MapViewOfFile.restype = wintypes.LPVOID UnmapViewOfFile = kernel32.UnmapViewOfFile UnmapViewOfFile.argtypes = [wintypes.LPCVOID] UnmapViewOfFile.restype = wintypes.BOOL CloseHandle = kernel32.CloseHandle CloseHandle.argtypes = [wintypes.HANDLE] CloseHandle.restype = wintypes.BOOL # Constants INVALID_HANDLE_VALUE = wintypes.HANDLE(-1).value PAGE_READWRITE = 0x04 FILE_MAP_ALL_ACCESS = 0x000F001F # Shared memory configuration shm_name = "Global\\WinAPISharedMemory" shm_size = 1024 * 1024 # Open shared memory h_map = CreateFileMappingW(INVALID_HANDLE_VALUE, None, PAGE_READWRITE, 0, shm_size, shm_name) if not h_map: print(f"CreateFileMapping failed: {ctypes.get_last_error()}") exit(1) # Map view to memory p_buf = MapViewOfFile(h_map, FILE_MAP_ALL_ACCESS, 0, 0, shm_size) if not p_buf: print(f"MapViewOfFile failed: {ctypes.get_last_error()}") CloseHandle(h_map) exit(1) # Read and print data raw_data = ctypes.string_at(p_buf) message = raw_data.decode('utf-8').strip('\x00') print(f"Received data: {message}") # Cleanup UnmapViewOfFile(p_buf) CloseHandle(h_map)
内容的提问来源于stack exchange,提问作者janetatomas11

