Python C API: проблемы с вызовом python c метода в c - PullRequest
3 голосов
/ 27 апреля 2020

В моем модуле есть метод, который берет список python и делит его на двойной

static PyObject *st_div_r(PyObject *self, PyObject *args){
  PyObject *pList;

  Py_ssize_t n;
  double x;
  int i;

  if (!PyArg_ParseTuple(args, "O!d", &PyList_Type, &pList, &x)) {
    PyErr_SetString(PyExc_TypeError, "parameters are wrong.");
    return NULL;
    }



  n = PyList_Size(pList);
  for(i=0;i<n;i++)
  {
    PyList_SetItem(pList,i,Py_BuildValue("d",PyFloat_AsDouble(PyList_GetItem(pList,i))/x));
        };
  Py_INCREF(pList);
  return pList;
}

Он работает так

my_mod.st_div_r([1,2,3],0.5)
[2,4,6]

Я хотел бы используйте st_div_r в другом методе моего модуля, который берет список списков, делит первый элемент на двойное и возвращает его

static PyObject *det(PyObject *self, PyObject *args){ 
  PyObject *pList;
  double d = 2.0;

  if (!PyArg_ParseTuple(args, "O!", &PyList_Type, &pList)) {
    PyErr_SetString(PyExc_TypeError, "parameters are  wrong.");
    return NULL;
    }


  PyList_SetItem(pList,0,st_div_r(pList,(PyList_GetItem(pList,0),Py_BuildValue("d",d))));

  Py_INCREF(pList);


  return pList;
}

Он должен работать так:

my_mod.det([[1,2],[3,4]])
[[0.5,1],[3,4]]

Но это не работает

 TypeError: parameters are wrong

Итак, вопрос в том, как вызвать st_div_r внутри det и что передать как self. Буду признателен за любую помощь. Спасибо

1 Ответ

3 голосов
/ 30 апреля 2020

Вы должны создать PyTuple в качестве второго аргумента вашей собственной функции (st_div_r)!

Есть два основных способа сделать это!

Первый путь

PyObject *first_list = PyList_GetItem(pList, 0)
//PyObject *divider = Py_BuildValue("d", d)

//PyObject *tuple_with_list_and_divider = Py_BuildValue("(Od)", first_list, divider);

PyObject *tuple_with_list_and_divider = Py_BuildValue("(Od)", first_list, d);

PyObject *list_after_division = st_div_r(pList, tuple_with_list_and_divider)

PyList_SetItem(pList , 0, list_after_division);

Second Way

PyObject *first_list = PyList_GetItem(pList, 0)
PyObject *divider = Py_BuildValue("d", d)

PyObject *tuple_with_list_and_divider = PyTuple_New(2);

PyTuple_SetItem(tuple_with_list_and_divider, 0, first_list);
PyTuple_SetItem(tuple_with_list_and_divider, 1, divider);

PyObject *list_after_division = st_div_r(pList, tuple_with_list_and_divider)

PyList_SetItem(pList , 0, list_after_division);

В первом примере я забыл, что Py_BuildValue преобразует d в Py_Double.

Извините за мой плохой английский sh!

...