Posted By

tkf on 09/18/08


Tagged

python c api extension PythonC


Versions (?)

Who likes this?

1 person have marked this snippet as a favorite

gartenstuhl


C API for a python extension module


 / Published in: C
 

URL: http://arataka.wordpress.com/2008/09/18/python%e3%81%aec%e6%8b%a1%e5%bc%b5%e3%81%a7api%e3%82%92%e5%85%ac%e9%96%8b%e3%81%99%e3%82%8b%e6%96%b9%e6%b3%95/

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

Report this snippet  

You need to login to post a comment.