使用SWIG在带有c ++ Python包装类的二进制数据中填充char *

时间:2015-05-19 19:31:21

标签: python c++ swig binary-data

我已经用swig包装了一个用于python的c ++类。我的班级是这样的:

public class DataHolder
{
public:
     char* BinaryData;
     long Length;
}

public class MyProcessor
{
public:
    int process(DataHolder& holder)
    {
          holder.BinaryData = assign some binary data;
          holder.Length = 1024;
    }
}

我想从python中得到的是这样的:

import Module
from Module import *

proc = MyProcessor();
holder = DataHolder();

proc.process(holder);

#use holder.BinaryData to, for example, print

非常感谢任何帮助,非常感谢!

1 个答案:

答案 0 :(得分:1)

您的示例C ++代码不太合法(它看起来更像Java!),但是一旦我修复了它并为process添加了一些真实的东西,我就可以按照您的希望进行包装。

与我的previous answer相比,主要的变化是从类内部读取长度,而不是在容器上调用方法的结果。这有点难看,因为我必须硬编码C ++'this'对象的名称,$self引用Python对象。由于我制作的类型图仅适用于我们确定其合法且正确的受限情况。

所以我的最终界面文件最终看起来像:

%module test

%typemap(out) char *DataHolder::BinaryData {
  Py_buffer *buf=(Py_buffer*)malloc(sizeof *buf);
  if (PyBuffer_FillInfo(buf, NULL, $1, arg1->Length, true, PyBUF_ND)) {
    // Error, handle
  }
  $result = PyMemoryView_FromBuffer(buf);
}

%inline %{
class DataHolder
{
public:
     char* BinaryData;
     long Length;
};

class MyProcessor
{
public:
    int process(DataHolder& holder)
    {
          static char val[] = "Hello\0Binary\0World\n!";
          holder.BinaryData = val;
          holder.Length = sizeof val;
          return 0;
    }
};
%}

我测试的是:

from test import *
proc = MyProcessor()
holder = DataHolder()

proc.process(holder)

data = holder.BinaryData
print(repr(data))
print(data.tobytes())

我在这里针对Python3,但完全相同的代码应该适用于Python 2.7。编译并运行时,这给出了:

swig2.0 -c++ -Wall -py3 -python test.i
g++ -Wall  -shared -o _test.so test_wrap.cxx -I/usr/include/python3.4
python3 run.py
<memory at 0xb7271f9c>
b'Hello\x00Binary\x00World\n!\x00'