Python和C ++共享相同的内存资源

时间:2018-02-13 22:15:37

标签: python c++ memory

我们假设我们正在使用 Python 并调用一些用 C ++ 编写的 DLL 库。我们在Python中打开一个非常大的数据集,然后我们想调用一个用C ++编写的库,并添加一个打开数据作为参数的数组。库可以对该数组执行某些操作,然后将其返回给Python代码。

所以问题是:是否可以使用相同的内存位置?  因为在这种情况下,我们不需要两次复制大量数据。

2 个答案:

答案 0 :(得分:3)

这一切都取决于您如何在内存中加载数据以及它是什么类型的数据。

如果是数字数据并且您使用例如一个numpy数组,它已经存储了一个可以从C或C ++代码中使用的内存布局。很容易获得数据块的地址(require())并通过ctypes将其传递给C ++代码。你可以看到一个很好的例子here。在这方面,图像数据类似(PIL图像采用简单的存储格式,并且可以容易地获得指向其数据的指针)。

另一方面,如果您的数据是常规的“本机”Python结构(例如常规列表或常规对象),那么情况就更棘手了。你可以直接将它们传递给C ++代码,但它的代码必须知道Python数据结构 - 所以,特别为此目的编写,使用numpy.ndarray.ctypes.data并处理非平凡的Python API 。

答案 1 :(得分:1)

这可以使用内存映射文件进行。我不以任何方式要求高速或高效。这些只是为了展示它工作的示例。

 $ python --version
 Python 3.7.9

 $ g++ --version
 g++ (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0

C ++端仅监视其所需的值。 Python端仅提供值。

注意:文件名“ pods.txt”在C ++和python代码中必须相同。

#include <sys/mman.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
 
int main(void)
  {
  // assume file exists
  int fd = -1;
  if ((fd = open("pods.txt", O_RDWR, 0)) == -1)
     {
     printf("unable to open pods.txt\n");
     return 0;
     }
  // open the file in shared memory
  char* shared = (char*) mmap(NULL, 8, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

  // periodically read the file contents
  while (true)
      {
      printf("0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X\n", shared[0], shared[1], shared[2], shared[3], shared[4], shared[5],           shared[6], shared[7]);
      sleep(1);
      }

   return 0;
   }

python端:

import mmap
import os
import time
 
fname = './pods.txt'
if not os.path.isfile(fname):
    # create initial file
    with open(fname, "w+b") as fd:
         fd.write(b'\x01\x00\x00\x00\x00\x00\x00\x00')

# at this point, file exists, so memory map it
with open(fname, "r+b") as fd:
    mm = mmap.mmap(fd.fileno(), 8, access=mmap.ACCESS_WRITE, offset=0)

    # set one of the pods to true (== 0x01) all the rest to false
    posn = 0
    while True:
         print(f'writing posn:{posn}')

         # reset to the start of the file
         mm.seek(0)
 
         # write the true/false values, only one is true
         for count in range(8):
             curr = b'\x01' if count == posn else b'\x00'
             mm.write(curr)

         # admire the view
         time.sleep(2)

         # set up for the next position in the next loop
        posn = (posn + 1) % 8

    mm.close()
    fd.close()

要在终端#1中运行它,

 a.out  # or whatever you called the C++ executable
 0x00 0x00 0x00 0x00 0x01 0x00 0x00 0x00
 0x00 0x00 0x00 0x00 0x01 0x00 0x00 0x00
 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00
 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00
 0x00 0x01 0x00 0x00 0x00 0x00 0x00 0x00
 0x00 0x01 0x00 0x00 0x00 0x00 0x00 0x00
 0x00 0x00 0x01 0x00 0x00 0x00 0x00 0x00
 0x00 0x00 0x01 0x00 0x00 0x00 0x00 0x00
 0x00 0x00 0x00 0x01 0x00 0x00 0x00 0x00

即由于C ++代码中的sleep(2),您应该看到0x01每隔几秒钟移动一次。

在2号航站楼:

python my.py  # or whatever you called the python file
writing posn:0
writing posn:1
writing posn:2

即您应该会看到位置从0到7再次变回0。