避免 C 编写的 Python 库的垃圾收集
Avoid garbage collection of C written Python library
我正在为我用 C 语言编写的 Python 库苦苦挣扎。该代码旨在在 cp210x 中写入一个寄存器以控制中继卡。该代码有效,但是 Python 以某种方式清除了对象。
换句话说,C变量ttyPort在结束一个函数后被清除。
这是 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);
}
python代码例如:
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()
或者如何正确存储变量?
一个可能的修复方法是在 PyArg_ParseTuple(args, "s", &ttyPort)
中使用 'es' 格式说明符而不是 's'。来自文档:
In general, when a format sets a pointer to a buffer, the buffer is managed by the corresponding Python object, and the buffer shares the lifetime of this object
除非你使用 'es'。但是,您必须手动释放内存。
我正在为我用 C 语言编写的 Python 库苦苦挣扎。该代码旨在在 cp210x 中写入一个寄存器以控制中继卡。该代码有效,但是 Python 以某种方式清除了对象。
换句话说,C变量ttyPort在结束一个函数后被清除。
这是 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);
}
python代码例如:
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()
或者如何正确存储变量?
一个可能的修复方法是在 PyArg_ParseTuple(args, "s", &ttyPort)
中使用 'es' 格式说明符而不是 's'。来自文档:
In general, when a format sets a pointer to a buffer, the buffer is managed by the corresponding Python object, and the buffer shares the lifetime of this object
除非你使用 'es'。但是,您必须手动释放内存。