1

I am trying to access to an existing C++ object from a python 3.4 extension. So I have the object coming from C++ with a SWIG binding. Then I am trying to build a C++ python extension where I would like to access to that object.

The reason I do that with python is because the library who create the object is an external library. So I use the python binding to generate objects and now I need to access to that object in C++.

To be more clear the object I use is Magick::Image (from ImageMagick++) and I am trying to pass this object to a python extension and then convert the image to a numpy ndarray.

The difficulty here, it's I access to Magick::Image object by a shared pointer.

So in python I have this:

img = get_my_magick_image()
print(img)

<Swig Object of type 'std::tr1::shared_ptr< Magick::Image > *' at 0x7f32f6ecdd80>

Here is the C++ extension I wrote to be able to access to Magick::Image methods but I can only access to shard_ptr methods... I got a segfault when I try to access to Magick::Image methods. I use readimg(img) in python to call it.

PyObject* readimg(PyObject* self, PyObject* args) {
    std::tr1::shared_ptr< Magick::Image > * img;

    if (!PyArg_ParseTuple(args, "O", &img)) {
         PyErr_SetString(PyExc_TypeError, "error with parameters");
         return 0;
    }

    std::cout << "img : " << img << std::endl;
    std::cout << "&img : " << &img << std::endl;
    std::cout << "typeid(img).name() : " << typeid(img).name() << std::endl;
    std::cout << "typeid((*img)).name() : " << typeid((*img)).name() << std::endl;
    std::cout << "img->use_count()" << img->use_count() << std::endl;
    std::cout << "img->unique()" << img->unique() << std::endl;
    std::cout << "img->get()" << img->get() << std::endl;
    std::cout << "(*img).use_count()" << (*img).use_count() << std::endl;
    std::cout << "(*img)" << (*img) << std::endl;

    Magick::Geometry size = (*img)->size(); // SEGFAULT HERE
    unsigned h = size.height();
    std::cout << h << std::endl;
}

And the related output :

img : 0x7f32f6ecdd80
&img : 0x7fff280fbad8
typeid(img).name() : PNSt3tr110shared_ptrIN6Magick5ImageEEE
typeid((*img)).name() : NSt3tr110shared_ptrIN6Magick5ImageEEE
img->use_count() : 10296384
img->unique() : 0
img->get() : 0x2
(*img).use_count() : 10296384
(*img) : 0x2
Segmentation fault

Any idea why I can't access to Magick::Image methods ?

hadim
  • 636
  • 1
  • 7
  • 16

1 Answers1

1

I'm not an expert but it looks like img is not properly initialized. Did you see the following in documentation?:

Other objects

O (object) [PyObject *] Store a Python object (without any conversion) in a C object pointer. The C program thus receives the actual object that was passed. The object’s reference count is not increased. The pointer stored is not NULL.

The function stores raw C pointer so I suppose it's not compatible with shared pointers. If you need a shared pointer, then I would propose something like this:

Magick::Image* _img = NULL;
if (!PyArg_ParseTuple(args, "O", &_img)) {
     PyErr_SetString(PyExc_TypeError, "error with parameters");
     return 0;
}
std::tr1::shared_ptr< Magick::Image > img(_img);
  • Thank you but the thing is in python I only have access to a shared pointer of Magick::Image. I saw the doc and tried several parse argumments without success. Do you think I could use O& and make a kind of conversion ? – hadim Jun 03 '14 at 11:23
  • Ah I see, it returns PyObject*. Probably O& is the way. Something like this: http://stackoverflow.com/questions/19282054/parsing-user-defined-types-using-pyarg-parsetuple – Pawel Tomulik Jun 03 '14 at 22:50