Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Connecting a C++ program to a Python script with shared memory

I'm trying to connect a C++ program to python using shared memory but I don't know how to pass the name of the memory segment to python.

Here is my C++ code:

key_t key = ftok("address", 1);
int shm_o;
char* msg = "hello there";
int len = strlen(msg) + 1;
void* addr;

shm_o = shmget(key, 20, IPC_CREAT | 0600);
if(shm_o == -1)
{
    std::cout << "Failed: shmget.\n";
    return 1;
}

addr = shmat(shm_o, NULL, 0);
if(addr == (void*) -1)
{
    std::cout << "Failed: shmat.\n";
    return 1;
}

std::cout << "Shared memory segment created successfully with id: " << shm_o;
memcpy(addr, msg, len);

getchar();
return 0;

I'm trying to get python to read from the shared memory segment like so:

shm_a = shared_memory.SharedMemory(name="address", create=False, size=20)

print(bytes(shm_a.buf[:11]))

but it throws an exception saying there is no file or directory called 'address'.

Am I going about this correctly or is there another way to attach python to the shared memory segment?

Any help would be much appreciated.

like image 620
kasra Avatar asked May 31 '26 10:05

kasra


1 Answers

Taking the liberty to post a working example here for POSIX shared memory segments, which will work across C/C++ and Python on Linux/UNIX-like systems. This will not work on Windows.

C++ code to create and write data into a shared memory segment (name provided on command line):

#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>

#include <iostream>
#include <string>

int main(int argc, char * argv[])
{
    if (argc != 2) {
         std::cerr << "Argument <shmem_name> required" << std::endl;
         return 1;
    }
    const char * shmem_name = argv[1];
    size_t shm_size = 4096;
    int shmem_fd = shm_open(shmem_name, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
    if (shmem_fd == -1) {
         perror("shm_open");
         return 1;
    }
    std::cout << "Shared Memory segment created with fd " << shmem_fd << std::endl;
    if (ftruncate(shmem_fd, shm_size) == -1) {
        perror("ftruncate");
        return 1;
    }
    std::cout << "Shared Memory segment resized to " << shm_size << std::endl;
    void * addr = mmap(0, shm_size, PROT_WRITE, MAP_SHARED, shmem_fd, 0);
    if (addr == MAP_FAILED) {
        perror("mmap");
        return 1;
    }
    std::cout << "Please enter some text to write to shared memory segment\n";
    std::string text;
    std::getline(std::cin, text);
    while (! text.empty()) {
        strncpy((char *)addr, text.data(), shm_size);
        std::cout << "Written '" << text << "' to shared memory segment\n";
        std::getline(std::cin, text);
    }
    std::cout << "Unlinking shared memory segment." << std::endl;
    shm_unlink(shmem_name) ;
}

Python code to read any string from the beginning of the shared memory segment:

import sys
from multiprocessing import shared_memory, resource_tracker

if len(sys.argv) != 2:
    print("Argument <shmem_name> required")
    sys.exit(1)

shm_seg = shared_memory.SharedMemory(name=sys.argv[1])
print(bytes(shm_seg.buf).strip(b'\x00').decode('ascii'))
shm_seg.close()
# Manually remove segment from resource_tracker, otherwise shmem segment
# will be unlinked upon program exit
resource_tracker.unregister(shm_seg._name, "shared_memory")
like image 166
treuss Avatar answered Jun 01 '26 22:06

treuss



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!