如何使用SWIG将python列表包装到结构内的结构数组?

时间:2019-06-05 07:49:49

标签: python c++ swig

我有一个无法修改的c ++库,它在另一个结构中有一个结构数组。我得到的相关代码如下:

  typedef int Landmark_Type[10];
  typedef int Rect_Type;
  typedef int Img_Num_Type;

  struct Rect{
    Rect_Type left;
    Rect_Type top;
    Rect_Type width;
    Rect_Type height;
  };
  struct Postion_Info{
    Landmark_Type landmark;
    Rect location;
  };

  struct Img_Array{
      Img_Num_Type imgNum;
      Postion_Info *imgInfo;
  };

  int get_postion(Postion_Info PosInfo) {
    printf("left:\t%d\n", PosInfo.location.left);
    printf("top:\t%d\n", PosInfo.location.top);
    printf("width:\t%d\n", PosInfo.location.width);
    printf("height:\t%d\n", PosInfo.location.height);

    for (int i = 0; i < 10; ++i) {
      printf("landmark %d:\t%d\n", i, PosInfo.landmark[i]);
    }
    return 0;
  }
  int get_img_array(Img_Array imgarray){
    printf("imgNum:\t%d\n", imgarray.imgNum);
    for (int i =0; i < imgarray.imgNum; i++) {
      get_postion(imgarray.imgInfo[i]);
    }
    return 0;
  }

如何通过SWIG将python列表传递给Img_Array.Postion_Info?

我尝试如下向.i文件添加类型映射:

%typemap(in) Postion_Info *(std::vector<Postion_Info> temp) {
  if (PyList_Check($input)) {
    const size_t size = PyList_Size($input);
    temp.resize(size);
    for (int i = 0; i < size; ++i) {
      void *argp = 0 ;
      const int res = SWIG_ConvertPtr(PyList_GetItem($input, i), &argp, $*1_descriptor, 0);
      if (!SWIG_IsOK(res)) {
        SWIG_exception_fail(SWIG_ArgError(res), "in method '" "$symname" "', argument " "$argnum"" of type '" "$1_type""'");
      }
      temp[i] = *reinterpret_cast<Postion_Info *>(argp);
    }
    $1 = &temp[0];
  }
  else {
    // Raise exception
    SWIG_exception_fail(SWIG_TypeError, "Expected list in $symname");
  }
}

和python文件为:

posinfo = Postion_Info()
posinfo.landmark = landmark
posinfo.location = location

posinfo2 = Postion_Info()
posinfo2.landmark = landmark2
posinfo2.location = location2

imgarray = Img_Array()
imgarray.imgNum = 2
imgarray.imgInfo = [posinfo,posinfo2]

但是出现了错误:

posinfo.landmark = landmark
TypeError: Expected list in Postion_Info_landmark_set
Exception ignored in: <built-in function delete_Postion_Info>
TypeError: Expected list in delete_Postion_Info

如何在Img_Array中键入映射​​Postion_Info *而不影响外部的Postion_Info?

--------更新19年6月10日------
谢谢@JensMunk的建议。
我修改了.i文件:

%inline %{
  Img_Array set_img_array(Img_Num_Type imgNum, Postion_Info *imgInfo){
    Img_Array img_array;
    img_array.imgNum = imgNum;
    img_array.imgInfo = imgInfo;
    return img_array;
  }
%}
%typemap(in) (Img_Num_Type imgNum, Postion_Info *imgInfo) {
  int i;
  if (!PyList_Check($input)) {
    PyErr_SetString(PyExc_ValueError, "Expecting a list");
    SWIG_fail;
  }
  $1 = PyList_Size($input);
  Postion_Info *temp = (Postion_Info *) malloc($1*sizeof(Postion_Info));
  for (i = 0; i < $1; i++) {
    void *argp = 0 ;
    const int res = SWIG_ConvertPtr(PyList_GetItem($input, i), &argp, $2_descriptor, 0);
    if (!SWIG_IsOK(res)) {
      SWIG_exception_fail(SWIG_ArgError(res), "in method '" "$symname" "', argument " "$argnum"" of type '" "$2_type""'");
    }
    temp[i] = *reinterpret_cast<Postion_Info *>(argp);
  }
  $2 = &temp[0];
}

%typemap(freearg) (Img_Num_Type imgNum, Postion_Info *imgInfo) {
  if ($2) free($2);
}

在python

imgarray = set_img_array([posinfo, posinfo2])
ret = get_img_array(imgarray)

但是我发现landmark[0]~[4]中的imgarray.imgInfo[0]已被更改,因为它们在%typemap之后仍然正确。看来该内存已在使用前释放。

0 个答案:

没有答案