python扩展模块的C API
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python扩展模块的C API相关的知识,希望对你有一定的参考价值。
==> sonmodule.h <== typedef struct { PyObject_HEAD PyObject *str; int num; } Son; #define MAKE_SON_NEW(self, type, rt_error) (self) = (Son *)(type)->tp_alloc((type), 0); if ((self) == rt_error) { return rt_error; } (self)->str = PyString_FromString(""); if ((self)->str == rt_error) { Py_DECREF((self)); return rt_error; } (self)->num = 0 #ifdef __SON_MODULE /* ---------- inclue form sonmodule.c ---------- */ static PyTypeObject SonType; #else /* ---------- inclue form othere module to use api ---------- */ /* store all api here */ void **Son_API; /* set alias for easy call */ #define SonType (*(PyTypeObject *)Son_API[0]) #define Son_info (*(PyObject *(*) (Son *))Son_API[1]) static int _import_son(void) { PyObject *son = PyImport_ImportModule("son"); PyObject *c_api = NULL; if (son == NULL){ return -1; } /* load c api */ c_api = PyObject_GetAttrString(son, "_Son_API"); if (c_api == NULL) {Py_DECREF(son); return -1;} if (PyCObject_Check(c_api)) { Son_API = (void **)PyCObject_AsVoidPtr(c_api); } Py_DECREF(c_api); Py_DECREF(son); if (Son_API == NULL) return -1; return 0; } #define import_son() { if (_import_son() < 0) { PyErr_Print(); PyErr_SetString( PyExc_ImportError, "son failed to import"); return; } } #endif /* __SONMODULE */ ==> sonmodule.c <== #include <Python.h> #include "structmember.h" #define __SON_MODULE #include "sonmodule.h" #undef __SON_MODULE static void Son_dealloc(Son* self) { Py_XDECREF(self->str); self->ob_type->tp_free((PyObject*)self); } static PyObject * Son_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { Son *self; MAKE_SON_NEW(self, type, NULL); return (PyObject *)self; } static int Son_init(Son *self, PyObject *args, PyObject *kwds) { PyObject *str=NULL, *tmp; static char *kwlist[] = {"str", "num", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "|Si", kwlist, &str, &self->num)){ return -1; } if (str) { tmp = self->str; Py_INCREF(str); self->str = str; Py_DECREF(tmp); } return 0; } static PyMemberDef Son_members[] = { {NULL} /* Sentinel */ }; static PyObject * Son_getstr(Son *self, void *closure) { Py_INCREF(self->str); return self->str; } static int Son_setstr(Son *self, PyObject *value, void *closure) { if (value == NULL) { PyErr_SetString(PyExc_TypeError, "Cannot delete the str attribute"); return -1; } if (! PyString_Check(value)) { PyErr_SetString(PyExc_TypeError, "The str attribute value must be a string"); return -1; } Py_DECREF(self->str); Py_INCREF(value); self->str = value; return 0; } static PyGetSetDef Son_getseters[] = { {"str", (getter)Son_getstr, (setter)Son_setstr, "str", NULL}, {NULL} /* Sentinel */ }; static PyObject * Son_info(Son *self) { PyObject *dic = PyDict_New(); if (dic == NULL) { return NULL; } Py_INCREF(self->str); PyDict_SetItemString(dic, "str", self->str); PyDict_SetItemString(dic, "num", PyLong_FromLong( self->num )); return dic; } static PyMethodDef Son_methods[] = { {"info", (PyCFunction)Son_info, METH_NOARGS, "return info dic"}, {NULL} /* Sentinel */ }; static PyTypeObject SonType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "son.Son", /*tp_name*/ sizeof(Son), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Son_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ "Son objects", /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Son_methods, /* tp_methods */ Son_members, /* tp_members */ Son_getseters, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc)Son_init, /* tp_init */ 0, /* tp_alloc */ Son_new, /* tp_new */ }; static PyMethodDef module_methods[] = { {NULL} /* Sentinel */ }; /* ---------- insert object into api array ---------- */ void *Son_API[] = { (void *) &SonType, (void *) Son_info, }; #ifndef PyMODINIT_FUNC /* declarations for DLL import/export */ #define PyMODINIT_FUNC void #endif PyMODINIT_FUNC initson(void) { PyObject *m, *d; PyObject *c_api; if (PyType_Ready(&SonType) < 0){ return; } m = Py_InitModule3("son", module_methods, "Son Class"); if (m == NULL){ goto err; } Py_INCREF(&SonType); PyModule_AddObject(m, "Son", (PyObject *)&SonType); /* ----- set api to module ----- */ d = PyModule_GetDict(m); if (!d){ goto err; } c_api = PyCObject_FromVoidPtr((void *)Son_API, NULL); if (c_api == NULL){ goto err; } PyDict_SetItemString(d, "_Son_API", c_api); Py_DECREF(c_api); return; err: if (!PyErr_Occurred()) { PyErr_SetString(PyExc_RuntimeError, "cannot load son module."); } return; } ==> fathermodule.c <== #include <Python.h> #include "structmember.h" #include "sonmodule.h" typedef struct { PyObject_HEAD Son *son; } Father; static void Father_dealloc(Father* self) { Py_XDECREF(self->son); self->ob_type->tp_free((PyObject*)self); } static PyObject * Father_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { Father *self; self = (Father *)type->tp_alloc(type, 0); if (self == NULL) { return NULL; } MAKE_SON_NEW(self->son, &SonType, NULL); return (PyObject *)self; } static int Father_init(Father *self, PyObject *args, PyObject *kwds) { return 0; } static PyMemberDef Father_members[] = { {NULL} /* Sentinel */ }; static PyObject * Father_getson(Father *self, void *closure) { Py_INCREF(self->son); return (PyObject *)self->son; } static int Father_setson(Father *self, PyObject *value, void *closure) { if (value == NULL) { PyErr_SetString(PyExc_TypeError, "Cannot delete the son attribute"); return -1; } if (! PyObject_TypeCheck(value, &SonType)) {/* SonType is from Son_API! */ PyErr_SetString(PyExc_TypeError, "The str attribute value must be a Son"); return -1; } Py_DECREF(self->son); Py_INCREF(value); self->son = (Son *)value; return 0; } static PyGetSetDef Father_getseters[] = { {"son", (getter)Father_getson, (setter)Father_setson, "son", NULL}, {NULL} /* Sentinel */ }; static PyObject * Father_info(Father *self) { PyObject *dic = PyDict_New(); if (dic == NULL) { return NULL; } PyDict_SetItemString(dic, "son", Son_info(self->son));/* Son_info is from Son_API! */ return dic; } static PyMethodDef Father_methods[] = { {"info", (PyCFunction)Father_info, METH_NOARGS, "return info dic"}, {NULL} /* Sentinel */ }; static PyTypeObject FatherType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "father.Father", /*tp_name*/ sizeof(Father), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Father_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ "Father objects", /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Father_methods, /* tp_methods */ Father_members, /* tp_members */ Father_getseters, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc)Father_init, /* tp_init */ 0, /* tp_alloc */ Father_new, /* tp_new */ }; static PyMethodDef module_methods[] = { {NULL} /* Sentinel */ }; #ifndef PyMODINIT_FUNC /* declarations for DLL import/export */ #define PyMODINIT_FUNC void #endif PyMODINIT_FUNC initfather(void) { PyObject* m; if (PyType_Ready(&FatherType) < 0){ return; } m = Py_InitModule3("father", module_methods, "Father Class"); if (m == NULL){ return; } Py_INCREF(&FatherType); PyModule_AddObject(m, "Father", (PyObject *)&FatherType); import_son(); } ==> setup.py <== # python setup.py build build_ext --inplace import sys import os from distutils.core import setup, Extension son_module = Extension( 'son', define_macros = [], include_dirs = [], libraries = [], library_dirs = [], extra_compile_args = [], sources = ['sonmodule.c']) father_module = Extension( 'father', define_macros = [], include_dirs = [], libraries = [], library_dirs = [], extra_compile_args = [], sources = ['fathermodule.c']) setup( name = 'storage', version = '1.0', description = '', ext_modules = [son_module, father_module] ) ==> test.txt <== >>> import son >>> sn = son.Son() >>> import father >>> fr = father.Father() >>> sn.num = 12 >>> sn.str = "son str" >>> sn.info() {'num': 12L, 'str': 'son str'} >>> fr.son <son.Son object at 0xb7cd5070> >>> fr.son.info() {'num': 0L, 'str': ''} >>> fr.info() {'son': {'num': 0L, 'str': ''}} >>> fr.son = sn >>> fr.info() {'son': {'num': 12L, 'str': 'son str'}}
以上是关于python扩展模块的C API的主要内容,如果未能解决你的问题,请参考以下文章