2016-03-18 2 views
2

Я импортирую библиотеку общих объектов, написанную на C, и вызывая некоторые функции-оболочки. Я сделал эту работу с использованием библиотеки Python.h.Изменение переменной Python, переданной функции C

У меня есть функция со следующим прототипом:

PyObject *Cal_readFile(PyObject *self, PyObject *args); 

я разобрать следующие кортежи:

PyArg_ParseTuple(args, "sO", &filename, &result) 

От питона вызов выглядит следующим образом:

result = [] 
status = Cal.readFile(filename, result) 
print(result) 

It называется прекрасным, и функция определенно работает. Моя цель - изменить переменную result в вызываемой функции C. И это именно то, что я делаю. Я изменяю переменную результата внутри функции C и использую result = Py_BuildValue("[lO]", (long)comp, compList); для ввода новых данных.

Однако, когда я тогда print результат в Python У меня все еще есть тот же пустой список, с которого я начал.

Есть ли какой-то дополнительный шаг, который мне нужно сделать, чтобы изменить эту переменную python из функции C? Я не могу использовать его в return, поскольку вы уже видите, что я собираю возвращаемый статус оттуда (это возвращение работает).

Edit: Некоторый код из readCal, которые могут быть полезны:

PyObject *result = NULL; 
PyArg_ParseTuple(args, "sO", &filename, &result); 
//Some creating of data is done, and then I am trying to set the list to that data: 

result = Py_BuildValue("[lO]", (long)comp, compList); 
+0

Вы хотите, чтобы вы ** добавляли ** эти значения в список Python? Вы не можете ** заменить ** такую ​​переменную, как на Python, и вообще не возможно в C. –

+0

И, пожалуйста, предоставьте больше кода для 'Cal_readFile' –

+0

@AnttiHaapala. Да, возможно, добавление может быть правильным. Файл довольно большой, поэтому я не вставлял его. Я отредактирую некоторые фрагменты, которые могут иметь значение. – ComputerLocus

ответ

2

Вы не можете заменить result в целом, но вы можете указать append или удалить существующие значения и т. Д.Что-то вроде этого могло бы сделать то, что вам нужно:

if (!PyArg_ParseTuple(args, "sO", &filename, &result)) { 
    return NULL; 
} 

PyObject *l = PyLong_FromLong((long)comp); 
if (!l) { 
    return NULL; 
} 

int success = PyList_Append(result, l); 
Py_DECREF(l); 
if (! success) { 
    return NULL; 
} 

success = PyList_Append(result, complist); 
if (! success) { 
    return NULL; 
} 
+0

Или, возможно, используйте 'PyList_SetSlice' с кортеж, как сейчас, если второе приложение не работает, все равно останется 1 элемент, добавленный к списку –

+0

Хорошее предложение, но если оно не получило его, то, скорее всего, оба потерпели неудачу в любом случае. Первый длинный на самом деле просто сохраняет указатель C, а вторая часть - это некоторые управляемые данные из этого указательного адреса. – ComputerLocus

1

Когда вы делаете:

PyArg_ParseTuple(args, "sO", &filename, &result) 

вы присваиваете ссылку на экземпляр, как обработанный питоном в result указатель.

Затем, когда вы делаете:

result = Py_BuildValue("[lO]", (long)comp, compList); 

вы замены значение, на который ссылается указатель результата на новый. Это означает, что в вашем коде python переменная result по-прежнему указывает на прежний экземпляр.

Если вы хотите изменить экземпляр остроконечного списка, то вы должны использовать методы List в C, чтобы мутировать сам экземпляр, вместо создания нового экземпляра.

В принципе, то, что вы делаете в коде C, такое же, как следующий код питона:

>>> def foo(result): 
... result = [4,5,6] 
... 
>>> result = [1,2,3] 
>>> foo(result) 
>>> print(result) 
[1,2,3] 

то, что вы хотите это сделать - в питоне - это:

>>> def foo(result): 
... while len(result): 
...  result.pop() # or any operation that mutates the result instance 
... result += [4,5,6] 
... 
>>> result = [1,2,3] 
>>> foo(result) 
>>> print(result) 
[4,5,6] 

теперь я оставляю это до вас, чтобы сделать это с помощью C API ;-)

НТН