import inspect, re def generate( obj ): name = obj.__name__ inst = obj() members = {} methods = {} matcher = re.compile( '^__.*__$' ) for i in inspect.getmembers(inst): str = i[0] val = i[1] if matcher.match(str) == None: if inspect.ismethod(val): methods[str] = val else: members[str] = val print 'typedef struct {\n\tPyObject_HEAD' for key in members: print "\tPyObject *" + key + ";" print '} ' + name + ";\n\n" typename = name+'Type' dealloc_name = name+'_dealloc' new_name = name+'_new' init_name = name+'_init' members_name = name + '_members' methods_name = name + '_methods' if obj.__doc__: docstr = obj.__doc__ else: docstr = '' print 'static PyObject *' print new_name + '( PyTypeObject *type, PyObject *args, PyObject *kwds )' print '{' print '\t' + name + ' *self;' print '\tself = (' + name + ' *)type->tp_alloc(type, 0);' print '\treturn (PyObject *)self;' print '}\n\n' print 'static int' print init_name + '( ' + name + ' *self, PyObject *args )' print '{\n\treturn 0;\n}\n\n' print 'static void' print dealloc_name + '( ' + name + ' *self )' print '{\n}\n\n' for method in methods: print 'static PyObject *' print name + '_' + method + '( ' + name + ' *self, PyObject *args )' print '{\n}\n\n\n' print 'static PyMethodDef ' + methods_name + '[] = {' for method in methods: if methods[method].__doc__: mdocstr = methods[method].__doc__ else: mdocstr = '' print "\t{\"" + method + '", (PyCFunction)' + name + '_' + method + ', METH_VARARGS, "' + mdocstr + '"},' print "\t{NULL}" print "};\n\n" print 'static PyMemberDef ' + members_name + '[] = {' for mem in members: if methods[method].__doc__: mdocstr = methods[method].__doc__ else: mdocstr = '' print '\t{"' + mem + '", T_OBJECT_EX, offsetof(' + name + ', ' + mem + '), 0, "' + mdocstr +'"},' print "\t{NULL}" print "};\n\n" print 'PyTypeObject '+typename + ' = {' print "\tPyObject_HEAD_INIT(0)" print "\t0,\t\t\t/*ob_size*/" print "\t\""+name+'",\t\t/*tp_name*/' print "\tsizeof(" + name + '),' print "\t0,\t\t\t/*tp_itemsize*/" print "\t(destructor)"+dealloc_name+",\t\t/*tp_dealloc*/" l = ['tp_print', 'tp_getattr', 'tp_setattr', 'tp_compare', 'tp_repr', 'tp_as_number', 'tp_as_sequence', 'tp_as_mapping', 'tp_hash ', 'tp_call', 'tp_str', 'tp_getattro', 'tp_setattro', 'tp_as_buffer'] for i in l: print "\t0,\t\t\t/*"+i+"*/" print "\tPy_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,\t/*tp_flags*/" print "\t\""+docstr+"\",\t\t\t/*tp_doc*/" l = ['tp_traverse', 'tp_clear', 'tp_richcompare', 'tp_weaklistoffset', 'tp_iter', 'tp_iternext'] for i in l: print "\t0,\t\t\t/*"+i+"*/" print "\t"+methods_name+"," print "\t"+members_name+"," l = ['tp_getset', 'tp_base', 'tp_dict', 'tp_descr_get', 'tp_descr_set', 'tp_dictoffset'] for i in l: print "\t0,\t\t\t/*"+i+"*/" print "\t(initproc)"+init_name+',' print "\t0, /* tp_alloc */" print "\t"+new_name print "};"
import gen_ext class Nanika: def __init__(self): self.x = 4 self.y = 40 def nanikaMethod(self): pass gen_ext.generate(Nanika)
こーいうのが、
typedef struct { PyObject_HEAD PyObject *y; PyObject *x; } Nanika; static PyObject * Nanika_new( PyTypeObject *type, PyObject *args, PyObject *kwds ) { Nanika *self; self = (Nanika *)type->tp_alloc(type, 0); return (PyObject *)self; } static int Nanika_init( Nanika *self, PyObject *args ) { return 0; } static void Nanika_dealloc( Nanika *self ) { } static PyObject * Nanika_nanika_method( Nanika *self, PyObject *args ) { } static PyMethodDef Nanika_methods[] = { {"nanika_method", (PyCFunction)Nanika_nanika_method, METH_VARARGS, ""}, {NULL} }; static PyMemberDef Nanika_members[] = { {"y", T_OBJECT_EX, offsetof(Nanika, y), 0, ""}, {"x", T_OBJECT_EX, offsetof(Nanika, x), 0, ""}, {NULL} }; PyTypeObject NanikaType = { PyObject_HEAD_INIT(0) 0, /*ob_size*/ "Nanika", /*tp_name*/ sizeof(Nanika), 0, /*tp_itemsize*/ (destructor)Nanika_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*/ "", /*tp_doc*/ 0, /*tp_traverse*/ 0, /*tp_clear*/ 0, /*tp_richcompare*/ 0, /*tp_weaklistoffset*/ 0, /*tp_iter*/ 0, /*tp_iternext*/ Nanika_methods, Nanika_members, 0, /*tp_getset*/ 0, /*tp_base*/ 0, /*tp_dict*/ 0, /*tp_descr_get*/ 0, /*tp_descr_set*/ 0, /*tp_dictoffset*/ (initproc)Nanika_init, 0, /* tp_alloc */ Nanika_new };
こーなる
wo