gen_ext.py

what?

Pythonのクラスからそれに対応するCの構造体とかを生成します。それだけ。

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