Example of Communication Between Qt C++ and Python Using Shared Memory

Below is a complete example of implementing communication between Qt C++ and Python using shared memory. This example consists of two parts: a Qt C++ application as the writer and a Python script as the reader.

Qt C++ Writer (SharedMemoryWriter)

// main.cpp#include <QCoreApplication>#include <QSharedMemory>#include <QBuffer>#include <QDataStream>#include <QDebug>#include <QThread>
int main(int argc, char *argv[]){    QCoreApplication a(argc, argv);
    // Create shared memory object    QSharedMemory sharedMemory("QtPythonSharedMemory");
    // If shared memory already exists, detach it first    if (sharedMemory.isAttached()) {        if (!sharedMemory.detach()) {            qDebug() << "Unable to detach from shared memory";            return 1;        }    }
    // Prepare data to share    QBuffer buffer;    buffer.open(QBuffer::ReadWrite);    QDataStream out(&buffer);
    // Write some example data    out << QString("Hello from Qt C++!");    out << QDateTime::currentDateTime();    out << 42;
    int size = buffer.size();
    // Create shared memory segment    if (!sharedMemory.create(size)) {        qDebug() << "Unable to create shared memory segment:" << sharedMemory.errorString();        return 1;    }
    // Lock shared memory and write data    sharedMemory.lock();    char *to = (char*)sharedMemory.data();    const char *from = buffer.data().data();    memcpy(to, from, qMin(sharedMemory.size(), size));    sharedMemory.unlock();
    qDebug() << "Data written to shared memory, size:" << size << "bytes";    qDebug() << "Shared memory key:" << sharedMemory.nativeKey();
    // Keep the program running for a while to allow Python to read    QThread::sleep(10);
    // Cleanup    if (sharedMemory.isAttached()) {        sharedMemory.detach();    }
    return 0;}

CMakeLists.txt (for Qt C++ project):

cmake_minimum_required(VERSION 3.16)project(SharedMemoryWriter)
set(CMAKE_CXX_STANDARD 17)set(CMAKE_AUTOMOC ON)set(CMAKE_AUTORCC ON)set(CMAKE_AUTOUIC ON)
find_package(Qt6 REQUIRED COMPONENTS Core)
add_executable(SharedMemoryWriter main.cpp)
target_link_libraries(SharedMemoryWriter Qt6::Core)

Python Reader (SharedMemoryReader.py)

import sysimport structfrom datetime import datetimefrom PySide6.QtCore import QSharedMemory, QDataStream, QByteArray, QIODevice# You can also use PyQt6 instead of PySide6
def read_shared_memory():    # Create shared memory object    shared_memory = QSharedMemory("QtPythonSharedMemory")
    # Try to attach to the shared memory segment    if not shared_memory.attach(QSharedMemory.ReadOnly):        print("Unable to attach to shared memory segment")        return False
    # Lock shared memory for reading    if not shared_memory.lock():        print("Unable to lock shared memory")        return False
    try:        # Create data stream to read data from shared memory        data = QByteArray()        data.resize(shared_memory.size())        data = bytearray(shared_memory.data())[:shared_memory.size()]
        buffer = QByteArray(data)        stream = QDataStream(buffer, QIODevice.ReadOnly)
        # Read data in the order it was written        message = stream.readQString()        timestamp = stream.readQVariant()        number = stream.readInt32()
        print(f"Received message: {message}")        print(f"Timestamp: {timestamp}")        print(f"Number: {number}")        return True    except Exception as e:        print(f"Error reading data: {e}")        return False    finally:        # Unlock and detach shared memory        shared_memory.unlock()        shared_memory.detach()
if __name__ == "__main__":    if not read_shared_memory():        sys.exit(1)

Usage Instructions

  1. First run the Qt C++ writer:

# Compile and run C++ programmkdir build && cd buildcmake .. && make./SharedMemoryWriter

2. Then run the Python reader (in another terminal):

pip install PySide6  # If not already installedpython SharedMemoryReader.py

Alternative: Use Native System Shared Memory

If you prefer not to rely on Qt’s Python bindings, you can implement it using Python’s standard library:

Python Reader Alternative (using posix_ipc or mmap):

import posix_ipc  # Requires installation: pip install posix_ipcimport sysimport jsonfrom datetime import datetime
def read_shared_memory_native():    try:        # Open existing shared memory        memory = posix_ipc.SharedMemory("QtPythonSharedMemory", posix_ipc.O_CREAT)
        # Read data        data = memory.read()        memory.close()
        # Parse data (assuming data is in JSON format)        decoded_data = json.loads(data.decode('utf-8'))
        print(f"Received message: {decoded_data['message']}")        print(f"Timestamp: {datetime.fromisoformat(decoded_data['timestamp'])}")        print(f"Number: {decoded_data['number']}")        return True    except Exception as e:        print(f"Error reading shared memory: {e}")        return False
if __name__ == "__main__":    if not read_shared_memory_native():        sys.exit(1)

The corresponding Qt C++ code needs to be modified to use the native shared memory API and write data in JSON format.

Notes

  1. Ensure both programs use the same shared memory key

  2. Consider consistency of data serialization format

  3. Handle synchronization issues for concurrent access

  4. Properly handle errors and exceptions

  5. Ensure shared memory resources are correctly released after use

This example demonstrates how to perform basic communication between Qt C++ and Python through shared memory. Depending on actual requirements, you may need to adjust the data format or add more complex synchronization mechanisms.

Leave a Comment