本文共 13290 字,大约阅读时间需要 44 分钟。
// Firststatic PyObject *exfunc(PyObject *self, PyObject *args) { ... // Get parameters /* Return 0 means an exception has been raised, you need to stop your program and rreturn NULL According to the official: It returns NULL (the error indicator for functions returning object pointers) if an error is detected in the argument list */ if (!PyArgs_ParseTuple(args, "format_string", &the_addr_of_c_variables)) { return NULL; } /* In this area, if you fail to call an user-defined function, what you are expected to do is call Python Exception API such as PyErr_SetString(PyExc_Type, "Exc_Info") to put an Exception Object in the Exception Stack in Python. */ ...}// Second// This is `method table`static PyMethodDef exfunc[] = { /* {NULL, NULL, 0, NULL} is the symbol of the end of PyMethodDef array, Python Interpretor will stop walking this PyMethodDef array when meeting it. */ /* According to the official: When using only METH_VARARGS, the function should expect the Python-level parameters to be passed in as a tuple acceptable for parsing via PyArg_ParseTuple() */ {"MethodName", your_func_pointer, METH_VARGS or METH_VARGS | METH_KEYWORDS, "Documents here"}, {NULL, NULL, 0, NULL} };// Thirdstatic struct PyModuleDef exmodule = { PyMODULEDEF_HEAD_INIT "name", "doc", size, exfunc,};// Fourth/* Actually, what Python Interpretor will call is the PyInit_*() function, so that will be entry to your extensional C module*/PyMODINIT_FUNC PyInit_exmodule { // PyModule_Init("ModuleName", &module_def); PyObject *m; /* When create an module object, an array of methods is need, but this rest is the history, there are classes, exceptions and so on existing in a module, so if you want to add something into a module, just use PyModule_AddObject() API like `PyErr_NewException("spam.error", NULL, NULL);` this will create a base exception implementing Exception */ m = PyModule_Create(&the_addr_of_PyModuleDef_array); if (!m) { return NULL; }}/*******************************************************************************************************/// In Python 2.x, the third and fourth are different of Python3.x// ThirdPyMODINIT_FUNC initname { // Don't return, because PyMODINIT_FUNC is void which is PyObject * in Python 3.x // Use PyInit_Module("name", MethodDef); rather than PyModule_Create("name", ModuleDef) PyInit_Module("name", MethodDef);}
PyArg_ParseTuple() and friends, functions that return an integer status usually return a positive value or zero for success and -1 for failure
Py_INCREF(Py_None);return Py_None;
PyObject *arglist;arglist = P_BuildValue("(i, l)", 8, 8888888)
int PyArg_ParseTupleAndKeywords(PyObject *arg, PyObject *kwdict, const char *format, char *kwlist[], ...);arg: tuple对象kwdict: dict对象format: 字符串格式kwlist: 存放关键词参数的键, 最后为NULL表示结束NOTE!! 此函数只能借此keyword而不能解析位置参数了
Py_BuildValue("") NonePy_BuildValue("i", 123) 123Py_BuildValue("iii", 123, 456, 789) (123, 456, 789)Py_BuildValue("s", "hello") 'hello'Py_BuildValue("y", "hello") b'hello'Py_BuildValue("ss", "hello", "world") ('hello', 'world')Py_BuildValue("s#", "hello", 4) 'hell'Py_BuildValue("y#", "hello", 4) b'hell'Py_BuildValue("()") ()Py_BuildValue("(i)", 123) (123,)Py_BuildValue("(ii)", 123, 456) (123, 456)Py_BuildValue("(i,i)", 123, 456) (123, 456)Py_BuildValue("[i,i]", 123, 456) [123, 456]Py_BuildValue("{s:i,s:i}", "abc", 123, "def", 456) {'abc': 123, 'def': 456}Py_BuildValue("((ii)(ii)) (ii)", 1, 2, 3, 4, 5, 6) (((1, 2), (3, 4)), (5, 6))
This initializes the Custom type, filling in a number of members to the appropriate default values, including ob_type that we initially set to NULL.if (PyType_Ready(&CustomType) < 0) return; This adds the type to the module dictionary.PyModule_AddObject(m, "Custom", (PyObject *) &CustomType);
static PyTypeObject CustomType = { PyVarObject_HEAD_INIT(NULL, 0) .tp_name = "custom2.Custom", .tp_doc = "Custom objects", .tp_basicsize = sizeof(CustomObject), .tp_itemsize = 0, .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, .tp_new = Custom_new, // __new__ 1 .tp_init = (initproc) Custom_init, // __init__ 2 .tp_dealloc = (destructor) Custom_dealloc, // __del__ 3 .tp_traverse = (traverseproc) Custom_traverse, // GC will call it .tp_clear = (inquiry) Custom_clear, // GC will call it .tp_members = Custom_members, // Is the PyMemberDef table .tp_methods = Custom_methods, // Is the PyMethodDef table .tp_getset = Custom_getsetters, // Setter and getter methods are special, so part them with tp_methods};// About the traverse and clearstatic intCustom_traverse(CustomObject *self, visitproc visit, void *arg){ Py_VISIT(self->first); Py_VISIT(self->last); return 0;}static intCustom_clear(CustomObject *self){ Py_CLEAR(self->first); Py_CLEAR(self->last); return 0;}
#includetypedef struct { PyListObject list; int state;} SubListObject;static PyObject *SubList_increment(SubListObject *self, PyObject *unused){ self->state++; return PyLong_FromLong(self->state);}static PyMethodDef SubList_methods[] = { {"increment", (PyCFunction) SubList_increment, METH_NOARGS, PyDoc_STR("increment state counter")}, {NULL},};static intSubList_init(SubListObject *self, PyObject *args, PyObject *kwds){ if (PyList_Type.tp_init((PyObject *) self, args, kwds) < 0) return -1; self->state = 0; return 0;}static PyTypeObject SubListType = { PyVarObject_HEAD_INIT(NULL, 0) .tp_name = "sublist.SubList", .tp_doc = "SubList objects", .tp_basicsize = sizeof(SubListObject), .tp_itemsize = 0, .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, .tp_init = (initproc) SubList_init, .tp_methods = SubList_methods,};static PyModuleDef sublistmodule = { PyModuleDef_HEAD_INIT, .m_name = "sublist", .m_doc = "Example module that creates an extension type.", .m_size = -1,};PyMODINIT_FUNCPyInit_sublist(void){ PyObject *m; SubListType.tp_base = &PyList_Type; if (PyType_Ready(&SubListType) < 0) return NULL; m = PyModule_Create(&sublistmodule); if (m == NULL) return NULL; Py_INCREF(&SubListType); PyModule_AddObject(m, "SubList", (PyObject *) &SubListType); return m;}
#include#include "structmember.h"typedef struct { PyObject_HEAD PyObject *first; /* first name */ PyObject *last; /* last name */ int number;} CustomObject;static voidCustom_dealloc(CustomObject *self){ Py_XDECREF(self->first); Py_XDECREF(self->last); Py_TYPE(self)->tp_free((PyObject *) self);}static PyObject *Custom_new(PyTypeObject *type, PyObject *args, PyObject *kwds){ CustomObject *self; self = (CustomObject *) type->tp_alloc(type, 0); if (self != NULL) { self->first = PyUnicode_FromString(""); if (self->first == NULL) { Py_DECREF(self); return NULL; } self->last = PyUnicode_FromString(""); if (self->last == NULL) { Py_DECREF(self); return NULL; } self->number = 0; } return (PyObject *) self;}static intCustom_init(CustomObject *self, PyObject *args, PyObject *kwds){ static char *kwlist[] = {"first", "last", "number", NULL}; PyObject *first = NULL, *last = NULL, *tmp; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|UUi", kwlist, &first, &last, &self->number)) return -1; if (first) { tmp = self->first; Py_INCREF(first); self->first = first; Py_DECREF(tmp); } if (last) { tmp = self->last; Py_INCREF(last); self->last = last; Py_DECREF(tmp); } return 0;}static PyMemberDef Custom_members[] = { {"number", T_INT, offsetof(CustomObject, number), 0, "custom number"}, {NULL} /* Sentinel */};static PyObject *Custom_getfirst(CustomObject *self, void *closure){ Py_INCREF(self->first); return self->first;}static intCustom_setfirst(CustomObject *self, PyObject *value, void *closure){ PyObject *tmp; if (value == NULL) { PyErr_SetString(PyExc_TypeError, "Cannot delete the first attribute"); return -1; } if (!PyUnicode_Check(value)) { PyErr_SetString(PyExc_TypeError, "The first attribute value must be a string"); return -1; } tmp = self->first; Py_INCREF(value); self->first = value; Py_DECREF(tmp); return 0;}static PyObject *Custom_getlast(CustomObject *self, void *closure){ Py_INCREF(self->last); return self->last;}static intCustom_setlast(CustomObject *self, PyObject *value, void *closure){ PyObject *tmp; if (value == NULL) { PyErr_SetString(PyExc_TypeError, "Cannot delete the last attribute"); return -1; } if (!PyUnicode_Check(value)) { PyErr_SetString(PyExc_TypeError, "The last attribute value must be a string"); return -1; } tmp = self->last; Py_INCREF(value); self->last = value; Py_DECREF(tmp); return 0;}static PyGetSetDef Custom_getsetters[] = { {"first", (getter) Custom_getfirst, (setter) Custom_setfirst, "first name", NULL}, {"last", (getter) Custom_getlast, (setter) Custom_setlast, "last name", NULL}, {NULL} /* Sentinel */};static PyObject *Custom_name(CustomObject *self, PyObject *Py_UNUSED(ignored)){ return PyUnicode_FromFormat("%S %S", self->first, self->last);}static PyMethodDef Custom_methods[] = { {"name", (PyCFunction) Custom_name, METH_NOARGS, "Return the name, combining the first and last name" }, {NULL} /* Sentinel */};static PyTypeObject CustomType = { PyVarObject_HEAD_INIT(NULL, 0) .tp_name = "custom3.Custom", .tp_doc = "Custom objects", .tp_basicsize = sizeof(CustomObject), .tp_itemsize = 0, .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, .tp_new = Custom_new, .tp_init = (initproc) Custom_init, .tp_dealloc = (destructor) Custom_dealloc, .tp_members = Custom_members, .tp_methods = Custom_methods, .tp_getset = Custom_getsetters,};static PyModuleDef custommodule = { PyModuleDef_HEAD_INIT, .m_name = "custom3", .m_doc = "Example module that creates an extension type.", .m_size = -1,};PyMODINIT_FUNCPyInit_custom3(void){ PyObject *m; if (PyType_Ready(&CustomType) < 0) return NULL; m = PyModule_Create(&custommodule); if (m == NULL) return NULL; Py_INCREF(&CustomType); PyModule_AddObject(m, "Custom", (PyObject *) &CustomType); return m;}
转载地址:http://klizo.baihongyu.com/