我有一个yec.c文件,它定义了一个包含两个函数的结构:
#include <python2.7/Python.h>
struct mec
{
int age;
int number;
};
static PyObject* nopoint(PyObject* self, PyObject* args)
{
struct mec m;
int n1, n2;
if (!PyArg_ParseTuple(args, "ii", &n1, &n2))
return NULL;
printf("nopoint(c) nombres: %d et %d!\n", n1, n2);
m.age = n1;
m.number = n2;
printf("nopoint(c) age nb: %d et %d!\n", m.age, m.number);
return Py_BuildValue("i", n1 + n2);
}
static PyObject* viapoint(PyObject* self, PyObject* args)
{
struct mec *m;
if (!PyArg_ParseTuple(args, "o", &m))
return NULL;
printf("viapoint av(c) age nb: %d et %d!\n", m->age, m->number);
m->age = 10;
m->number = 1;
printf("viapoint ap(c) age nb: %d et %d!\n", m->age, m->number);
return Py_BuildValue("i", m->age + m->number);
}
static PyMethodDef MyYecMethods[] = {
{"nopoint", nopoint, METH_VARARGS, "Description de fune"},
{"viapoint", viapoint, METH_VARARGS, "Description de fdeux"},
{NULL, NULL, 0, NULL}
};
PyMODINIT_FUNC
inityec(void)
{
(void) Py_InitModule("yec", MyYecMethods);
}
我把yec.c文件编译成是的,所以在下面的设置中使用python setup_yec.py build
命令_是的文件:
我可以使用Python下编译的库,nopoint()函数可以工作:
import yec
yec.nopoint(3, 4)
我想使用我的库的第二个函数viapoint(),它应该接受Python中定义相关ctypes.结构公司名称:
from ctypes import *
class Mec(Structure):
_fields_ = [("age", c_int),
("number", c_int)]
m = Mec(1, 2)
print "py mec class", m.age, m.number
yec.viapoint(byref(m))
当然,它不起作用:
Traceback (most recent call last):
File "testyec.py", line 18, in <module>
yec.viapoint(byref(m))
TypeError: must be impossible<bad format char>, not CArgObject
如果有人知道如何修改viapoint()函数,以便能够通过PyArg_ParseTuple()解析结构指针,以及如何在python中传递python结构指针(使用byref?),那将是一个很大的帮助。在
谢谢。在
您需要使用Python脚本中的
ctypes.addressof
,而不是ctypes.byref
(这是与C指针不同的对象),然后在yec.c
中,将输入值解析为long
(如果是32位,则为int
),并将其分配给“struct mec*”。在请参见下面的工作示例:
在Python中:
^{pr2}$运行它,我得到:
您可以将
Structure
解析为读写缓冲区("w#"
)。通过将其作为参数传递,您可以放心它是一个被引用的对象。它还确保传入的缓冲区是大小正确的可写内存。崩溃Python是不可接受的。你应该在Python中得到异常。如果您的Python代码使得对解释器的segfault变得微不足道,那么您的做法就大错特错了。在Python:
^{pr2}$如果你只是接受一个地址作为参数,你的函数可能会在一个无效的指针上出错,或者只是返回垃圾或修改内存,这将使你的程序以一种难以理解的方式崩溃。此外,通过解析地址,您需要有条件地定义是在预处理器中解析为},这取决于{}与{}相比的大小。例如,在Win64上,
long
还是{long
是32位的,将指针解析为long
会截断它。最后,一个要求您首先在Python中调用addressof
的API是一个低效的kludge。在相关问题 更多 >
编程相关推荐