[C++-sig] how to return arbitrary (python-)objects from boost?
Joerg Kurlbaum
jkur at informatik.uni-bremen.de
Wed Apr 23 16:52:21 CEST 2008
On Wed, Apr 23, 2008 at 08:26:29AM -0400, Stefan Seefeld wrote:
> Joerg,
>
> I'm not sure I completely understand what you are trying to do, or
> whether that's actually needed...
Hm, i supected that.
> If you mean by 'arbitrary objects' python objects, you can certainly
> pass those. In C++ they are spelled boost::python::object, and you can
> pass them as function arguments or return values as any other type.
> Conversion from C++ types to boost::python::object is implicit as long
> as there are registered converters.
Okay. I've read about converters. But the noddy example isn't very
helpful. The problem is, i think, that all the types i want to use are
already there. I have the QImage in C++ and in Python. I want to create
a QImage in the wrapper code from the image data and return that to the
python program.
> For a more specific answer it might be best if you show some code...
You are right. In the boost wrapper i derive from the class that does
all the camera-specific handling in C/C++. I'm adding another function
to convert from the uchar array with the image data to a numpy array
(get_image_as_array). This code works. The actual handling of the RGB
values is not important and can be ignored.
Now i want to have a function that does not return a numpy array but a
QImage, which is available in C++ and with pyqt4 in python as well.
The function get_image_as_qimage() would be my naive approach to do
that, but this code doesn't even compile, because the cast from
python::object to QImage does not work and several other problems.
And that makes sense if there isn't some information for boost::python
what a QImage actually is. But maybe you can get an idea of what i
wanted to do.
Do i have to write a complete type description (like in the noddy
example) for QImage? I would think that this description is already
existent, because PyQt4 uses the QImage derived from the C++ library.
#include <boost/python.hpp>
#include <num_util.h>
#include <QtGui/QImage>
#include "camera.h"
class Camera_wrap : public Camera
{
public:
// THIS CODE WORKS
virtual numeric::array get_image_asarray()
{
int* size = reinterpret_cast<int*>(&rgbframe->size[0]);
boost::python::object obj(boost::python::handle<>(PyArray_FromDims(2, size, NPY_UINT32)));
void *arr_data = PyArray_DATA((PyArrayObject*) obj.ptr());
uint32_t* dest = static_cast<uint32_t*>(arr_data);
unsigned char* src = rgbframe->image;
unsigned char R,G,B,A;
for ( uint32_t y = 0; y < rgbframe->size[1]; ++y)
{
for ( uint32_t x = 0; x < rgbframe->size[0]; ++x)
{
R = *src++;
G = *src++;
B = *src++;
A = 255;
unsigned char* pixel = reinterpret_cast<unsigned char*>( &(dest[x*size[1]+y]) );
*pixel++ = B;
*pixel++ = G;
*pixel++ = R;
*pixel = A;
}
}
return boost::python::extract<boost::python::numeric::array>(obj);
}
// THIS IS ONLY HOW I THINK I COULD LOOK LIKE
virtual QImage get_image_qimage()
{
unsigned int nx = rgbframe->size[0];
unsigned int ny = rgbframe->size[1];
boost::python::object obj(boost::python::handle<>( new QImage(nx, ny, QImage::Format_ARGB32)));
for (int j = 0; j < ny; ++j)
{
uint8_t* line = static_cast<uint8_t*>( reinterpret_cast<QImage*>(obj.ptr())->scanLine(j) );
uint8_t* data = rgbframe->image + j*nx*3;
for (int i=0; i<nx; i++)
{
*line++ = *data++;
*line++ = *data++;
*line++ = *data++;
*line++ = 255;
}
}
return obj;
}
// ...
}
BOOST_PYTHON_MODULE(camera1394)
{
import_array();
numeric::array::set_module_and_type("numpy", "ndarray");
class_<Camera_wrap>("Camera", init<Camera_Configuration>())
.def("capture", &Camera_wrap::capture)
.def("capture_end", &Camera_wrap::capture_end)
.def("get_image_asarray", &Camera_wrap::get_image_asarray )
.def("get_image_qimage", &Camera_wrap::get_image_qimage )
.def("image_size", &Camera_wrap::get_size_wrap )
;
// ...
}
Another approach i tried, is to create the QImage in python and pass it as
an argument to a function in the wrapper, store the image data in the
scanLines and return it (or as in the code modify a reference)
void get_image_as_qimage2(boost::python::object obj)
{
QImage& img = extract<QImage&>(obj);
// do some image stuff
// ...
}
And in python:
from camera1394 import *
from PyQt4 import Qt, QtGui
def main():
conf = Camera_Configuration()
c = Camera(conf)
c.capture()
qimage = QtGui.QImage(640, 480, Qt.QImage.Format_ARGB32)
c.get_image_as_qimage(qimage)
c.capture_end()
But here i get a type error:
TypeError: No registered converter was able to extract a C++
reference to type QImage from this Python object of type QImage
Okay. Now i would be in the situation to write a converter. There is an
example in the FAQ with some custom_string class but as far i can see
all this conversion does is breaking a custom string down to a char*
which is then implicitly converted to a python string. This seems very
different to what i'm trying.
I hope i could make it a bit more clear what my problem is. Somehow i
think this is more or less a standard/newbie problem when using
boost::python but i haven't found suitable documentation.
Greetings,
Jörg :-)
--
Jörg Kurlbaum (jkur at informatik.uni-bremen.de) Cartesium 00.056
GPG-ID: CAC40EA9 Enrique Schmidt Str. 5
T: 0421/218-64201 Universität Bremen
More information about the Cplusplus-sig
mailing list