开发者社区> 问答> 正文

在C扩展模块中操作隐形指针

你有一个扩展模块需要处理C结构体中的指针, 但是你又不想暴露结构体中任何内部细节给Python。

展开
收起
哦哦喔 2020-04-17 18:11:26 2197 0
1 条回答
写回答
取消 提交回答
  • 隐形结构体可以很容易的通过将它们包装在胶囊对象中来处理。 考虑我们例子代码中的下列C代码片段:
    
    typedef struct Point {
        double x,y;
    } Point;
    
    extern double distance(Point *p1, Point *p2);
    下面是一个使用胶囊包装Point结构体和 distance() 函数的扩展代码实例:
    
    /* Destructor function for points */
    static void del_Point(PyObject *obj) {
      free(PyCapsule_GetPointer(obj,"Point"));
    }
    
    /* Utility functions */
    static Point *PyPoint_AsPoint(PyObject *obj) {
      return (Point *) PyCapsule_GetPointer(obj, "Point");
    }
    
    static PyObject *PyPoint_FromPoint(Point *p, int must_free) {
      return PyCapsule_New(p, "Point", must_free ? del_Point : NULL);
    }
    
    /* Create a new Point object */
    static PyObject *py_Point(PyObject *self, PyObject *args) {
    
      Point *p;
      double x,y;
      if (!PyArg_ParseTuple(args,"dd",&x,&y)) {
        return NULL;
      }
      p = (Point *) malloc(sizeof(Point));
      p->x = x;
      p->y = y;
      return PyPoint_FromPoint(p, 1);
    }
    
    static PyObject *py_distance(PyObject *self, PyObject *args) {
      Point *p1, *p2;
      PyObject *py_p1, *py_p2;
      double result;
    
      if (!PyArg_ParseTuple(args,"OO",&py_p1, &py_p2)) {
        return NULL;
      }
      if (!(p1 = PyPoint_AsPoint(py_p1))) {
        return NULL;
      }
      if (!(p2 = PyPoint_AsPoint(py_p2))) {
        return NULL;
      }
      result = distance(p1,p2);
      return Py_BuildValue("d", result);
    }
    在Python中可以像下面这样来使用这些函数:
    
    >>> import sample
    >>> p1 = sample.Point(2,3)
    >>> p2 = sample.Point(4,5)
    >>> p1
    <capsule object "Point" at 0x1004ea330>
    >>> p2
    <capsule object "Point" at 0x1005d1db0>
    >>> sample.distance(p1,p2)
    2.8284271247461903
    >>>
    
    2020-04-17 18:20:24
    赞同 展开评论 打赏
问答分类:
问答标签:
问答地址:
问答排行榜
最热
最新

相关电子书

更多
低代码开发师(初级)实战教程 立即下载
冬季实战营第三期:MySQL数据库进阶实战 立即下载
阿里巴巴DevOps 最佳实践手册 立即下载