如何将python字节对象传递给C ++扩展?

时间:2018-08-15 00:17:57

标签: python cpython python-extensions

我正在尝试将numpy数组传递给自定义的C ++扩展,但是不知何故出现了分段错误。在这里,我简化了代码。

在C ++方面,我只是使用“ s#”解析一个字节对象,将数据复制到opencv Mat中,然后将其写入png文件:

#include <Python.h>
#include <iostream>
#include <memory>
#include <opencv2/opencv.hpp>

static PyObject* renderer_savePNG(PyObject *self,PyObject *args,PyObject *keywds)
{
    const char *tex;
    int buf_size;
    int texSize=256;

    static char *kwlist[]={"tex",NULL};
    if(!PyArg_ParseTupleAndKeywords(args,keywds,"s#",kwlist,&tex,&buf_size)){
        assert(buf_size==tex_size*tex_size*3);
        std::cout<<"Parse failed"<<std::endl;
        return NULL;
    }
    cv::Mat texRGB;texRGB.create(texSize,texSize,CV_8UC3);
    memcpy(texRGB.data,tex,texSize*texSize*3*sizeof(char));

    cv::Mat texBGR; cv::cvtColor(texRGB,texBGR,CV_RGB2BGR);
    cv::imwrite("test.png",texBGR);

    Py_RETURN_NONE;
}

static PyMethodDef eglrendererMethods[]={
    {"save_png",(PyCFunction)renderer_savePNG,METH_VARARGS|METH_KEYWORDS,"save png"},
    {NULL,NULL,0,NULL}
};

static struct PyModuleDef eglrenderer_module={
    PyModuleDef_HEAD_INIT,
    "eglrenderer",
    NULL,-1,
    eglrendererMethods
};

extern "C"{
PyMODINIT_FUNC PyInit_eglrenderer()
{
    return PyModule_Create(&eglrenderer_module);
}
};

在python端,我首先读取图像,将其转换为numpy数组,然后转换为bytes对象。

from PIL import Image
import numpy as np
import eglrenderer

tex_size=256
tex=Image.open("tex.png")
tex=tex.resize((tex_size,tex_size))
tex=np.array(tex).tostring()
eglrenderer.save_png(tex=tex)

我能够使用distutils构建和安装此模块,而不会出现任何问题。但是,当我运行它时,出现了“分段错误(核心已转储)”。当我使用“ -ggdb”构建扩展并尝试使用gdb进行调试时,它在以下行中断:

Thread 1 "python" received signal SIGSEGV, Segmentation fault.
0x00007fffe6f37fcb in cv::cvtColor(cv::_InputArray const&, cv::_OutputArray const&, int, int) () from /usr/lib/x86_64-linux-gnu/libopencv_imgproc.so.2.4
(gdb) up
#1  0x00007fffe969acad in renderer_savePNG (self=<optimized out>, args=<optimized out>, keywds=<optimized out>) at renderer.cpp:61
61      cv::Mat texBGR; cv::cvtColor(texRGB,texBGR,CV_RGB2BGR);
(gdb)

但是,如果这是一个细微的内存问题,则来自gdb的此错误消息可能不会提供信息。

此代码有什么问题?任何想法如何找到问题?另外,将字节数组传递到C扩展模块的最佳实践是什么?任何建议表示赞赏。谢谢!

0 个答案:

没有答案