Как обернуть список Python в массив структур в структуре с SWIG? - PullRequest
0 голосов
/ 05 июня 2019

У меня есть библиотека 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;
  }

Как передать список Python в Img_Array.Postion_Info с помощью SWIG?

Я попытался добавить карту типов в файл .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

Как мне напечатать Postion_Info * в Img_Array, не затрагивая Postion_Info снаружи?

-------- обновление 10 июня '19 ------
Спасибо за предложения @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.Похоже, что память была освобождена перед использованием.

...