代码之家  ›  专栏  ›  技术社区  ›  Jake

python的swig类型映射:输入和输出数组

  •  4
  • Jake  · 技术社区  · 14 年前

    extern int convertAtoB( stateStruct *myStruct,
                            const double PointA[3],
                            double PointB[3]);
    

    使用SWIG,我想我需要定义一个typemap来转换两个点(PointA是输入,PointB是输出),以便Python可以使用它。在typemaps中似乎没有typemap,我不知道如何使用它,所以我必须定义一个。我在SWIG文档中似乎找不到数组的例子。

    我想这样使用这个库:

    s = externalStruct()
    point_a = [1, 2, 3]
    result, point_b = convertAtoB(s, point_a)
    print point_b
    "expect [4, 5, 6]"
    

    我该怎么做?谢谢

    3 回复  |  直到 14 年前
        1
  •  3
  •   kynan    13 年前

    你就快到了。要去掉python签名中的伪参数,需要进行更改 %typemap(in) PointB[3] %typemap(in,numinputs=0) 指示SWIG忽略该输入值(无论如何,您已经在复制它)。这将从python方法签名中删除伪参数。

    我不确定,但是,如果你需要复制整个 %类型映射(in) 为了专业化。也许有办法重用实际的typemap,但我不知道怎么做。否则你会得到一个额外的

    %typemap(in,numinputs=0) double PointB[3] (double temp[$1_dim0]) {
      int i;
      if (!PySequence_Check($input)) {
        PyErr_SetString(PyExc_ValueError,"Expected a sequence");
        return NULL;
      }
      if (PySequence_Length($input) != $1_dim0) {
        PyErr_SetString(PyExc_ValueError,"Size mismatch. Expected $1_dim0 elements");
        return NULL;
      }
      for (i = 0; i < $1_dim0; i++) {
        PyObject *o = PySequence_GetItem($input,i);
        if (PyNumber_Check(o)) {
          temp[i] = (double) PyFloat_AsDouble(o);
        } else {
          PyErr_SetString(PyExc_ValueError,"Sequence elements must be numbers");      
          return NULL;
        }
      }
      $1 = temp;
    }
    
        2
  •  2
  •   Jake    14 年前

    我找到了一个解决方案,但可能不是最好的:

    %typemap(in) double[ANY] (double temp[$1_dim0]) {
      int i;
      if (!PySequence_Check($input)) {
        PyErr_SetString(PyExc_ValueError,"Expected a sequence");
        return NULL;
      }
      if (PySequence_Length($input) != $1_dim0) {
        PyErr_SetString(PyExc_ValueError,"Size mismatch. Expected $1_dim0 elements");
        return NULL;
      }
      for (i = 0; i < $1_dim0; i++) {
        PyObject *o = PySequence_GetItem($input,i);
        if (PyNumber_Check(o)) {
          temp[i] = (double) PyFloat_AsDouble(o);
        } else {
          PyErr_SetString(PyExc_ValueError,"Sequence elements must be numbers");      
          return NULL;
        }
      }
      $1 = temp;
    }
    

    这是我最后遇到的文档中的一个例子,它将Python列表转换为数组。下一部分更难,拼凑几个示例,我可以将返回数组转换为python列表:

    %typemap(argout) double PointB[3]{
        PyObject *o = PyList_New(3);
        int i;
        for(i=0; i<3; i++)
        {
            PyList_SetItem(o, i, PyFloat_FromDouble($1[i]));
        }
        $result = o;
    }
    

    point_b = convertAtoB(s, point_a, dummy)
    

    有更好的办法吗?

        3
  •  1
  •   Jens Munk    11 年前

    专门针对上述情况

    %typemap(in, numinputs=0) double PointB[3] {
      double tmp[3];
      $1 = tmp;
    }
    
    %typemap(argout) double PointB[3] {
      PyObject *o = PyList_New(3);
      int i;
      for(i=0; i<3; i++)
      {
        PyList_SetItem(o, i, PyFloat_FromDouble($1[i]));
      }
      $result = o;
    }