Python 如何在PyBindGen中编写自定义类型处理程序?

Python 如何在PyBindGen中编写自定义类型处理程序?,python,c++,extending,pybindgen,Python,C++,Extending,Pybindgen,PyBindGen的文档说,为自己的数据类型编写自定义类型处理程序很容易。然而,我没有找到任何好的例子来写它们。pybindgen提供的示例太基础,无法理解细节,遗憾的是,文档几乎不存在。 我需要的是: 我需要使用哪个类作为转换器的基础 我必须重载哪些方法来扩展或替换绑定代码的特定部分 我应该使用什么方法来处理常量和非常量参数 是否有任何完整且有详细文档记录的向pybindgen添加自定义typehandler的示例?可能是有人为你自己的项目做了这件事,并且可能分享了一种方法 这是我当前绑定

PyBindGen的文档说,为自己的数据类型编写自定义类型处理程序很容易。然而,我没有找到任何好的例子来写它们。pybindgen提供的示例太基础,无法理解细节,遗憾的是,文档几乎不存在。 我需要的是:

  • 我需要使用哪个类作为转换器的基础
  • 我必须重载哪些方法来扩展或替换绑定代码的特定部分
  • 我应该使用什么方法来处理常量和非常量参数
是否有任何完整且有详细文档记录的向pybindgen添加自定义typehandler的示例?可能是有人为你自己的项目做了这件事,并且可能分享了一种方法

这是我当前绑定的一个示例,可以更好地理解我需要什么。当前已使用Boost.python完成:

PyObject* System_getXYZ(System* s, int ind, int fr){
  CREATE_PYARRAY_1D(p,3)
  MAP_EIGEN_TO_PYARRAY(v,Vector3f,p)
  v = s->XYZ(ind,fr);
  return boost::python::incref(p);
}   

...
class_<System, boost::noncopyable>("System", init<>())
  ...
  .def("getXYZ", &System_getXYZ)
  ...
;
PyObject*System\u getXYZ(System*s,int-ind,int-fr){
创建数组(p,3)
将本征映射到阵列(v,向量3f,p)
v=s->XYZ(ind,fr);
返回boost::python::incremf(p);
}   
...
类(“系统”,init())
...
.def(“getXYZ”和System_getXYZ)
...
;
方法System::XYZ()返回一个特征::Vector3f对象。必须将其转换为numpy数组,而不复制其数据。这很重要,因为整个想法都是关于效率的。 目前,它是通过丑陋的宏来完成的:

#define MAP_EIGEN_TO_PYARRAY(_matr,_T,_obj_ptr) \
    if(!PyArray_Check(_obj_ptr)) throw pteros::Pteros_error("NumPy array expected!"); \
    if(PyArray_TYPE(_obj_ptr)!=PyArray_FLOAT) throw pteros::Pteros_error("float NumPy array expected!"); \
    Eigen::Map<_T> _matr((float*) PyArray_DATA(_obj_ptr), \
            (PyArray_DIM((PyArrayObject*)_obj_ptr,0)==PyArray_Size(_obj_ptr)) ? PyArray_DIM(
            (PyArray_DIM((PyArrayObject*)_obj_ptr,0)==PyArray_Size(_obj_ptr)) ? 1 : PyArray_


#define CREATE_PYARRAY_1D(_ptr_obj, _dim1) \
    PyObject* _ptr_obj; \
    { \
        npy_intp _sz_dim1[1];\
        _sz_dim1[0] = _dim1; \
        _ptr_obj = PyArray_SimpleNew(1, _sz_dim1, PyArray_FLOAT); \
    }
#定义映射到PYARRAY(_matr,_T,_obj_ptr)\
如果(!PyArray_Check(_obj_ptr))抛出pteros::pteros_错误(“应为NumPy数组!”)\
if(PyArray_TYPE(_obj_ptr)!=PyArray_FLOAT)抛出pteros::pteros_错误(“应为FLOAT NumPy数组!”)\
特征::映射数据((浮点*)PyArray数据(_obj_ptr)\
(PyArray_DIM((PyArrayObject*)_obj_ptr,0)=PyArray_Size(_obj_ptr))?PyArray_DIM(
(PyArray_DIM((PyArrayObject*)_obj_ptr,0)=PyArray_Size(_obj_ptr))?1:PyArray_
#定义CREATE_PYARRAY_1D(_ptr_obj,_dim1)\
PyObject*_ptr_obj\
{ \
npy_intp_sz_dim1[1]\
_sz_dim1[0]=_dim1\
_ptr_obj=PyArray_SimpleNew(1,_sz_dim1,PyArray_FLOAT)\
}
这是可行的,但我需要为每个方法编写一个包装函数,它使用特征对象,这是一个需要维护的噩梦。这就是为什么我想尝试PyBindGen并在那里创建一个转换器,它会自动添加这些宏中的所有样板代码


顺便说一句,boost.python转换器在这里没有帮助,因为它们强制复制数据。

您可能有兴趣使用,以避免直接与c-api混淆。实际上,我现在使用的是boost.python,我正在寻找替代方法。问题是boost.python自定义转换器太有限了,它们总是意味着复制data,我不想对重型对象执行此操作。也没有用于引用参数(out params)的自定义转换器,仅用于常量引用。结果可能是,c-api不允许更好的转换,因为引擎的内部工作方式为(referenced)对象。我现在有一个工作解决方案,但是它需要为每种方法编写一个C++包装器函数,它得到自定义类型的参数。它很难看,而且很难维护。如何把你所拥有的样本放在一起,并提出一些想法使它更好?这可能会给你更好的结果。