在Python扩展中操作来自SWIG的共享指针
我正在尝试通过一个 Python 3.4 的扩展来访问一个已经存在的 C++ 对象。这个对象是通过 SWIG 绑定从 C++ 传过来的。现在我想建立一个 C++ 的 Python 扩展,以便能够访问这个对象。
我这样做的原因是,因为创建这个对象的库是一个外部库。所以我使用 Python 的绑定来生成对象,现在我需要在 C++ 中访问这个对象。
更具体一点,我使用的对象是 Magick::Image
(来自 ImageMagick++),我想把这个对象传递给一个 Python 扩展,然后把图像转换成一个 numpy 的 ndarray。
这里的难点在于,我是通过一个共享指针来访问 Magick::Image
对象。
在 Python 中,我有这样的代码:
img = get_my_magick_image()
print(img)
<Swig Object of type 'std::tr1::shared_ptr< Magick::Image > *' at 0x7f32f6ecdd80>
这是我写的 C++ 扩展,目的是能够访问 Magick::Image
的方法,但我只能访问 shared_ptr
的方法……当我尝试访问 Magick::Image
的方法时,程序崩溃了。我在 Python 中使用 readimg(img)
来调用它。
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;
}
相关的输出是:
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
有没有人知道为什么我无法访问 Magick::Image
的方法?
1 个回答
1
我不是专家,但看起来img
没有正确初始化。你有没有看到文档中的以下内容?:
其他对象
O (object) [PyObject *] 在C语言的对象指针中存储一个Python对象(不进行任何转换)。这样,C程序就能接收到实际传入的对象。对象的引用计数不会增加。存储的指针不是NULL。
这个函数存储的是原始C指针,所以我猜它和共享指针不兼容。如果你需要一个共享指针,我建议你可以尝试这样的方式:
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);