python扩展模块的C API

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python扩展模块的C API相关的知识,希望对你有一定的参考价值。

  1. ==> sonmodule.h <==
  2. typedef struct {
  3. PyObject_HEAD
  4. PyObject *str;
  5. int num;
  6. } Son;
  7.  
  8. #define MAKE_SON_NEW(self, type, rt_error)
  9.   (self) = (Son *)(type)->tp_alloc((type), 0);
  10.   if ((self) == rt_error) { return rt_error; }
  11.   (self)->str = PyString_FromString("");
  12.   if ((self)->str == rt_error) {
  13.   Py_DECREF((self));
  14.   return rt_error;
  15.   }
  16.   (self)->num = 0
  17.  
  18. #ifdef __SON_MODULE
  19. /* ---------- inclue form sonmodule.c ---------- */
  20. static PyTypeObject SonType;
  21.  
  22. #else
  23. /* ---------- inclue form othere module to use api ---------- */
  24. /* store all api here */
  25. void **Son_API;
  26. /* set alias for easy call */
  27. #define SonType (*(PyTypeObject *)Son_API[0])
  28. #define Son_info (*(PyObject *(*) (Son *))Son_API[1])
  29.  
  30. static int _import_son(void)
  31. {
  32. PyObject *son = PyImport_ImportModule("son");
  33. PyObject *c_api = NULL;
  34. if (son == NULL){ return -1; }
  35.  
  36. /* load c api */
  37. c_api = PyObject_GetAttrString(son, "_Son_API");
  38. if (c_api == NULL) {Py_DECREF(son); return -1;}
  39. if (PyCObject_Check(c_api)) {
  40. Son_API = (void **)PyCObject_AsVoidPtr(c_api);
  41. }
  42. Py_DECREF(c_api);
  43. Py_DECREF(son);
  44. if (Son_API == NULL) return -1;
  45.  
  46. return 0;
  47. }
  48.  
  49. #define import_son()
  50.   {
  51.   if (_import_son() < 0) {
  52.   PyErr_Print();
  53.   PyErr_SetString( PyExc_ImportError,
  54. "son failed to import");
  55.   return;
  56.   }
  57.   }
  58.  
  59. #endif
  60. /* __SONMODULE */
  61.  
  62. ==> sonmodule.c <==
  63. #include <Python.h>
  64. #include "structmember.h"
  65.  
  66. #define __SON_MODULE
  67. #include "sonmodule.h"
  68. #undef __SON_MODULE
  69.  
  70. static void
  71. Son_dealloc(Son* self)
  72. {
  73. Py_XDECREF(self->str);
  74. self->ob_type->tp_free((PyObject*)self);
  75. }
  76.  
  77. static PyObject *
  78. Son_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
  79. {
  80. Son *self;
  81. MAKE_SON_NEW(self, type, NULL);
  82. return (PyObject *)self;
  83. }
  84.  
  85. static int
  86. Son_init(Son *self, PyObject *args, PyObject *kwds)
  87. {
  88. PyObject *str=NULL, *tmp;
  89.  
  90. static char *kwlist[] = {"str", "num", NULL};
  91.  
  92. if (! PyArg_ParseTupleAndKeywords(args, kwds, "|Si", kwlist,
  93. &str,
  94. &self->num)){
  95. return -1;
  96. }
  97.  
  98. if (str) {
  99. tmp = self->str;
  100. Py_INCREF(str);
  101. self->str = str;
  102. Py_DECREF(tmp);
  103. }
  104.  
  105. return 0;
  106. }
  107.  
  108. static PyMemberDef Son_members[] = {
  109. {"num", T_INT, offsetof(Son, num), 0, "Sone num"},
  110. {NULL} /* Sentinel */
  111. };
  112.  
  113. static PyObject *
  114. Son_getstr(Son *self, void *closure)
  115. {
  116. Py_INCREF(self->str);
  117. return self->str;
  118. }
  119.  
  120. static int
  121. Son_setstr(Son *self, PyObject *value, void *closure)
  122. {
  123. if (value == NULL) {
  124. PyErr_SetString(PyExc_TypeError, "Cannot delete the str attribute");
  125. return -1;
  126. }
  127.  
  128. if (! PyString_Check(value)) {
  129. PyErr_SetString(PyExc_TypeError,
  130. "The str attribute value must be a string");
  131. return -1;
  132. }
  133.  
  134. Py_DECREF(self->str);
  135. Py_INCREF(value);
  136. self->str = value;
  137.  
  138. return 0;
  139. }
  140.  
  141. static PyGetSetDef Son_getseters[] = {
  142. {"str", (getter)Son_getstr, (setter)Son_setstr, "str", NULL},
  143. {NULL} /* Sentinel */
  144. };
  145.  
  146. static PyObject *
  147. Son_info(Son *self)
  148. {
  149. PyObject *dic = PyDict_New();
  150. if (dic == NULL) {
  151. printf("creating dict failed ");
  152. return NULL;
  153. }
  154. Py_INCREF(self->str);
  155. PyDict_SetItemString(dic, "str", self->str);
  156. PyDict_SetItemString(dic, "num", PyLong_FromLong( self->num ));
  157. return dic;
  158. }
  159.  
  160. static PyMethodDef Son_methods[] = {
  161. {"info", (PyCFunction)Son_info, METH_NOARGS, "return info dic"},
  162. {NULL} /* Sentinel */
  163. };
  164.  
  165. static PyTypeObject SonType = {
  166. PyObject_HEAD_INIT(NULL)
  167. 0, /*ob_size*/
  168. "son.Son", /*tp_name*/
  169. sizeof(Son), /*tp_basicsize*/
  170. 0, /*tp_itemsize*/
  171. (destructor)Son_dealloc, /*tp_dealloc*/
  172. 0, /*tp_print*/
  173. 0, /*tp_getattr*/
  174. 0, /*tp_setattr*/
  175. 0, /*tp_compare*/
  176. 0, /*tp_repr*/
  177. 0, /*tp_as_number*/
  178. 0, /*tp_as_sequence*/
  179. 0, /*tp_as_mapping*/
  180. 0, /*tp_hash */
  181. 0, /*tp_call*/
  182. 0, /*tp_str*/
  183. 0, /*tp_getattro*/
  184. 0, /*tp_setattro*/
  185. 0, /*tp_as_buffer*/
  186. Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
  187. "Son objects", /* tp_doc */
  188. 0, /* tp_traverse */
  189. 0, /* tp_clear */
  190. 0, /* tp_richcompare */
  191. 0, /* tp_weaklistoffset */
  192. 0, /* tp_iter */
  193. 0, /* tp_iternext */
  194. Son_methods, /* tp_methods */
  195. Son_members, /* tp_members */
  196. Son_getseters, /* tp_getset */
  197. 0, /* tp_base */
  198. 0, /* tp_dict */
  199. 0, /* tp_descr_get */
  200. 0, /* tp_descr_set */
  201. 0, /* tp_dictoffset */
  202. (initproc)Son_init, /* tp_init */
  203. 0, /* tp_alloc */
  204. Son_new, /* tp_new */
  205. };
  206.  
  207. static PyMethodDef module_methods[] = {
  208. {NULL} /* Sentinel */
  209. };
  210.  
  211. /* ---------- insert object into api array ---------- */
  212. void *Son_API[] = {
  213. (void *) &SonType,
  214. (void *) Son_info,
  215. };
  216.  
  217. #ifndef PyMODINIT_FUNC /* declarations for DLL import/export */
  218. #define PyMODINIT_FUNC void
  219. #endif
  220. PyMODINIT_FUNC
  221. initson(void)
  222. {
  223. PyObject *m, *d;
  224. PyObject *c_api;
  225. if (PyType_Ready(&SonType) < 0){ return; }
  226.  
  227. m = Py_InitModule3("son", module_methods,
  228. "Son Class");
  229.  
  230. if (m == NULL){ goto err; }
  231.  
  232. Py_INCREF(&SonType);
  233. PyModule_AddObject(m, "Son", (PyObject *)&SonType);
  234.  
  235. /* ----- set api to module ----- */
  236. d = PyModule_GetDict(m);
  237. if (!d){ goto err; }
  238.  
  239. c_api = PyCObject_FromVoidPtr((void *)Son_API, NULL);
  240. if (c_api == NULL){ goto err; }
  241. PyDict_SetItemString(d, "_Son_API", c_api);
  242. Py_DECREF(c_api);
  243.  
  244. return;
  245.  
  246. err:
  247. if (!PyErr_Occurred()) {
  248. PyErr_SetString(PyExc_RuntimeError,
  249. "cannot load son module.");
  250. }
  251. return;
  252. }
  253.  
  254. ==> fathermodule.c <==
  255. #include <Python.h>
  256. #include "structmember.h"
  257.  
  258. #include "sonmodule.h"
  259.  
  260. typedef struct {
  261. PyObject_HEAD
  262. Son *son;
  263. } Father;
  264.  
  265. static void
  266. Father_dealloc(Father* self)
  267. {
  268. Py_XDECREF(self->son);
  269. self->ob_type->tp_free((PyObject*)self);
  270. }
  271.  
  272. static PyObject *
  273. Father_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
  274. {
  275. Father *self;
  276.  
  277. self = (Father *)type->tp_alloc(type, 0);
  278. if (self == NULL) { return NULL; }
  279.  
  280. MAKE_SON_NEW(self->son, &SonType, NULL);
  281.  
  282. return (PyObject *)self;
  283. }
  284.  
  285. static int
  286. Father_init(Father *self, PyObject *args, PyObject *kwds)
  287. {
  288. return 0;
  289. }
  290.  
  291. static PyMemberDef Father_members[] = {
  292. {NULL} /* Sentinel */
  293. };
  294.  
  295. static PyObject *
  296. Father_getson(Father *self, void *closure)
  297. {
  298. Py_INCREF(self->son);
  299. return (PyObject *)self->son;
  300. }
  301.  
  302. static int
  303. Father_setson(Father *self, PyObject *value, void *closure)
  304. {
  305. if (value == NULL) {
  306. PyErr_SetString(PyExc_TypeError, "Cannot delete the son attribute");
  307. return -1;
  308. }
  309.  
  310. if (! PyObject_TypeCheck(value, &SonType)) {/* SonType is from Son_API! */
  311. PyErr_SetString(PyExc_TypeError,
  312. "The str attribute value must be a Son");
  313. return -1;
  314. }
  315.  
  316. Py_DECREF(self->son);
  317. Py_INCREF(value);
  318. self->son = (Son *)value;
  319.  
  320. return 0;
  321. }
  322.  
  323. static PyGetSetDef Father_getseters[] = {
  324. {"son", (getter)Father_getson, (setter)Father_setson, "son", NULL},
  325. {NULL} /* Sentinel */
  326. };
  327.  
  328. static PyObject *
  329. Father_info(Father *self)
  330. {
  331. PyObject *dic = PyDict_New();
  332. if (dic == NULL) {
  333. printf("creating dict failed ");
  334. return NULL;
  335. }
  336. PyDict_SetItemString(dic, "son",
  337. Son_info(self->son));/* Son_info is from Son_API! */
  338. return dic;
  339. }
  340.  
  341. static PyMethodDef Father_methods[] = {
  342. {"info", (PyCFunction)Father_info, METH_NOARGS, "return info dic"},
  343. {NULL} /* Sentinel */
  344. };
  345.  
  346. static PyTypeObject FatherType = {
  347. PyObject_HEAD_INIT(NULL)
  348. 0, /*ob_size*/
  349. "father.Father", /*tp_name*/
  350. sizeof(Father), /*tp_basicsize*/
  351. 0, /*tp_itemsize*/
  352. (destructor)Father_dealloc, /*tp_dealloc*/
  353. 0, /*tp_print*/
  354. 0, /*tp_getattr*/
  355. 0, /*tp_setattr*/
  356. 0, /*tp_compare*/
  357. 0, /*tp_repr*/
  358. 0, /*tp_as_number*/
  359. 0, /*tp_as_sequence*/
  360. 0, /*tp_as_mapping*/
  361. 0, /*tp_hash */
  362. 0, /*tp_call*/
  363. 0, /*tp_str*/
  364. 0, /*tp_getattro*/
  365. 0, /*tp_setattro*/
  366. 0, /*tp_as_buffer*/
  367. Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
  368. "Father objects", /* tp_doc */
  369. 0, /* tp_traverse */
  370. 0, /* tp_clear */
  371. 0, /* tp_richcompare */
  372. 0, /* tp_weaklistoffset */
  373. 0, /* tp_iter */
  374. 0, /* tp_iternext */
  375. Father_methods, /* tp_methods */
  376. Father_members, /* tp_members */
  377. Father_getseters, /* tp_getset */
  378. 0, /* tp_base */
  379. 0, /* tp_dict */
  380. 0, /* tp_descr_get */
  381. 0, /* tp_descr_set */
  382. 0, /* tp_dictoffset */
  383. (initproc)Father_init, /* tp_init */
  384. 0, /* tp_alloc */
  385. Father_new, /* tp_new */
  386. };
  387.  
  388. static PyMethodDef module_methods[] = {
  389. {NULL} /* Sentinel */
  390. };
  391.  
  392. #ifndef PyMODINIT_FUNC /* declarations for DLL import/export */
  393. #define PyMODINIT_FUNC void
  394. #endif
  395. PyMODINIT_FUNC
  396. initfather(void)
  397. {
  398. PyObject* m;
  399. if (PyType_Ready(&FatherType) < 0){ return; }
  400.  
  401. m = Py_InitModule3("father", module_methods,
  402. "Father Class");
  403.  
  404. if (m == NULL){ return; }
  405.  
  406. Py_INCREF(&FatherType);
  407. PyModule_AddObject(m, "Father", (PyObject *)&FatherType);
  408.  
  409. import_son();
  410. }
  411.  
  412. ==> setup.py <==
  413. # python setup.py build build_ext --inplace
  414. import sys
  415. import os
  416. from distutils.core import setup, Extension
  417.  
  418. son_module = Extension(
  419. 'son',
  420. define_macros = [],
  421. include_dirs = [],
  422. libraries = [],
  423. library_dirs = [],
  424. extra_compile_args = [],
  425. sources = ['sonmodule.c'])
  426.  
  427. father_module = Extension(
  428. 'father',
  429. define_macros = [],
  430. include_dirs = [],
  431. libraries = [],
  432. library_dirs = [],
  433. extra_compile_args = [],
  434. sources = ['fathermodule.c'])
  435.  
  436. setup(
  437. name = 'storage',
  438. version = '1.0',
  439. description = '',
  440. ext_modules = [son_module, father_module] )
  441.  
  442. ==> test.txt <==
  443. >>> import son
  444. >>> sn = son.Son()
  445. >>> import father
  446. >>> fr = father.Father()
  447. >>> sn.num = 12
  448. >>> sn.str = "son str"
  449. >>> sn.info()
  450. {'num': 12L, 'str': 'son str'}
  451. >>> fr.son
  452. <son.Son object at 0xb7cd5070>
  453. >>> fr.son.info()
  454. {'num': 0L, 'str': ''}
  455. >>> fr.info()
  456. {'son': {'num': 0L, 'str': ''}}
  457. >>> fr.son = sn
  458. >>> fr.info()
  459. {'son': {'num': 12L, 'str': 'son str'}}

以上是关于python扩展模块的C API的主要内容,如果未能解决你的问题,请参考以下文章

扩展Python模块系列----异常和错误处理

快速实现python c扩展模块

Python 3.X 调用多线程C模块,并在C模块中回调python函数的示例

python 3.x C 扩展模块和子模块

如何构建 Python C 扩展,以便我可以从模块中导入它

尝试编译C扩展模块时缺少Python.h