2017-01-18 2 views
0

Я борюсь с моей C письменной библиотекой Python. Код предназначен для записи регистра в cp210x для управления картой Relay. Код работает, однако Python каким-то образом очищает объект.Избегайте сбора мусора из C письменной библиотеки Python

Другими словами, переменная ttyPort C сбрасывается после завершения функции.

Вот код C:

#include <Python.h> 
#include <fcntl.h> 
#include <stropts.h> 

// C variable that holds the tty address (e.g. /dev/ttyUSB0) 
const char* ttyPort; 

int setRelay(int action, int relayNumber) 
{ 
    /* more magic over here */ 
    printf("Port :: %s\n", ttyPort); 

} 
// All python wrappers below 

static PyObject*setPort(PyObject* self, PyObject* args) 
{ 
    Py_INCREF(self) 
    // Copy python argument to ttyPort 
    if (!PyArg_ParseTuple(args, "s", &ttyPort)) 
     return NULL; 

    printf("RelayModule :: Port set (%s)\n", ttyPort); 

    Py_RETURN_NONE; 
} 

static PyObject*fanOff(PyObject* self, PyObject* args) 
{ 
    //fanMode = 0; 
    printf("RelayModule :: Fan off %s\n",ttyPort); 
    if (setRelay(RELAY_OFF, 0) == 1){ 
     // more magic 
    } 
    Py_RETURN_NONE; 
} 
/* more functions over here */ 
static PyMethodDef RelayMethods[] = 
{ 
    {"setPort", setPort, METH_VARARGS, "Set tty port."}, 
    {"fanOff", fanOff, METH_NOARGS, "Fan off."}, 
    {"fanHalf", fanHalf, METH_NOARGS, "Fan half speed."}, 
    {"fanFull", fanFull, METH_NOARGS, "Fan full on."}, 
    {"pumpOn", pumpOn, METH_NOARGS, "Pump on."}, 
    {"pumpOff", pumpOff, METH_NOARGS, "Pump off."}, 
    {"isPumpOn", isPumpOn, METH_NOARGS, "Check if pump is on."}, 
    {"getFanMode", getFanMode, METH_NOARGS, "Get fan mode."}, 
    {NULL, NULL, 0, NULL} 
}; 

static struct PyModuleDef RelayDefs = { 
    PyModuleDef_HEAD_INIT,"RelayModule","A Python module that controls the Conrad 4ch relay card.", -1, RelayMethods 
}; 


PyMODINIT_FUNC PyInit_Relay(void) 
{ 
    Py_Initialize(); 
    return PyModule_Create(&RelayDefs); 
} 

Питон код, например:

import Relay 

def settty(): 
    Relay.setPort("/dev/ttyUSB0") 

def gettty(): 
    Relay.fanOff() 

def doAll(): 
    Relay.setPort("/dev/ttyUSB0") 
    Relay.fanOff() 

settty() 
gettty() #Error, prints 'Port :: [garbage]' 
doAll() #works! 

Как я могу как-то объявить объект? На других языках я бы сделал: RelayObj = new Relay()

Или как я могу сохранить переменную правильно?

+0

Вставить его в объект и выполнить функции функций-членов. – wildplasser

+0

Я думаю, что одним из главных вопросов было то, как я это сделал – Kramer

+0

С вашей текущей реализацией попробуйте сохранить возвращаемое значение 'PyModule_Create' в статическом var. Я подозреваю, что сразу же его можно заставить оптимизатора немедленно удалить его (или отключить оптимизацию компилятора, чтобы увидеть, действительно ли это мешает). – daragua

ответ

0

Одним из возможных исправлений является использование спецификатора формата «es» в PyArg_ParseTuple(args, "s", &ttyPort) вместо «s». Из документации:

В общем, когда формат устанавливает указатель на буфер, буфер управляется с помощью соответствующего объекта Python, и буферные разделяет срок службы этого объекта

если вы не используете «эс». Однако вам придется освобождать память вручную.

+0

Похоже, что это решило мою проблему, однако мне также нужно было добавить такую ​​кодировку: 'if (! PyArg_ParseTuple (args," es "," utf-8 ", & ttyPort))' – Kramer

Смежные вопросы