简体   繁体   中英

Fill char* with binary data in a c++ Python wrapped class with SWIG

I have wrapped a c++ class with swig for python use. My class is something like:

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;
    }
}

What i want from python is something like this:

import Module
from Module import *

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

proc.process(holder);

#use holder.BinaryData to, for example, print

Any help will be very appreciated, thanks a lot!

Your example C++ code isn't quite legal (it looks more like Java!), but once I fixed that and added something real for process to do I was able to wrap it as you hoped.

Compared to my previous answer the main change is that the length gets read from inside the class, rather than being the result of calling a method on a container. This is kind of ugly, because I had to hardcode the name of the C++ 'this' object, $self referred to the Python object. Due to that I made the typemap only get applied in restricted circumstances where we're sure it's legal and correct.

So my final interface file ended up looking like:

%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;
    }
};
%}

Which I tested with:

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

proc.process(holder)

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

I targeted Python3 here, but the exact same code should work for Python 2.7. When compiled and run this gave:

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'

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM