1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
|
"""
The class that generates code to keep track of existing python
wrappers for a given root class.
"""
from typehandlers.base import NotSupportedError
class WrapperRegistry(object):
"""
Abstract base class for wrapepr registries.
"""
def __init__(self, base_name):
self.base_name = base_name
def generate_forward_declarations(self, code_sink, module):
raise NotImplementedError
def generate(self, code_sink, module, import_from_module):
raise NotImplementedError
def write_register_new_wrapper(self, code_block, wrapper_lvalue, object_rvalue):
raise NotImplementedError
def write_lookup_wrapper(self, code_block, wrapper_type, wrapper_lvalue, object_rvalue):
raise NotImplementedError
def write_unregister_wrapper(self, code_block, wrapper_lvalue, object_rvalue):
raise NotImplementedError
class NullWrapperRegistry(WrapperRegistry):
"""
A 'null' wrapper registry class. It produces no code, and does
not guarantee that more than one wrapper cannot be created for
each object. Use this class to disable wrapper registries entirely.
"""
def __init__(self, base_name):
super(NullWrapperRegistry, self).__init__(base_name)
def generate_forward_declarations(self, code_sink, module, import_from_module):
pass
def generate(self, code_sink, module):
pass
def generate_import(self, code_sink, module, import_from_module):
pass
def write_register_new_wrapper(self, code_block, wrapper_lvalue, object_rvalue):
pass
def write_lookup_wrapper(self, code_block, wrapper_type, wrapper_lvalue, object_rvalue):
raise NotSupportedError
def write_unregister_wrapper(self, code_block, wrapper_lvalue, object_rvalue):
pass
class StdMapWrapperRegistry(WrapperRegistry):
"""
A wrapper registry that uses std::map as implementation. Do not
use this if generating pure C wrapping code, else the code will
not compile.
"""
def __init__(self, base_name):
super(StdMapWrapperRegistry, self).__init__(base_name)
self.map_name = "%s_wrapper_registry" % base_name
def generate_forward_declarations(self, code_sink, module, import_from_module):
module.add_include("<map>")
module.add_include("<iostream>")
#code_sink.writeln("#include <map>")
#code_sink.writeln("#include <iostream>")
if import_from_module:
code_sink.writeln("extern std::map<void*, PyObject*> *_%s;" % self.map_name)
code_sink.writeln("#define %s (*_%s)" % (self.map_name, self.map_name))
else:
code_sink.writeln("extern std::map<void*, PyObject*> %s;" % self.map_name)
def generate(self, code_sink, module):
code_sink.writeln("std::map<void*, PyObject*> %s;" % self.map_name)
# register the map in the module namespace
module.after_init.write_code("PyModule_AddObject(m, (char *) \"_%s\", PyCObject_FromVoidPtr(&%s, NULL));"
% (self.map_name, self.map_name))
def generate_import(self, code_sink, code_block, module_pyobj_var):
code_sink.writeln("std::map<void*, PyObject*> *_%s;" % self.map_name)
code_block.write_code("PyObject *_cobj = PyObject_GetAttrString(%s, \"_%s\");"
% (module_pyobj_var, self.map_name))
code_block.write_code("if (_cobj == NULL) {\n"
" _%(MAP)s = NULL;\n"
" PyErr_Clear();\n"
"} else {\n"
" _%(MAP)s = reinterpret_cast< std::map<void*, PyObject*> *> (PyCObject_AsVoidPtr (_cobj));\n"
" Py_DECREF(_cobj);\n"
"}"
% dict(MAP=self.map_name))
def write_register_new_wrapper(self, code_block, wrapper_lvalue, object_rvalue):
code_block.write_code("%s[(void *) %s] = (PyObject *) %s;" % (self.map_name, object_rvalue, wrapper_lvalue))
#code_block.write_code('std::cerr << "Register Wrapper: obj=" <<(void *) %s << ", wrapper=" << %s << std::endl;'
# % (object_rvalue, wrapper_lvalue))
def write_lookup_wrapper(self, code_block, wrapper_type, wrapper_lvalue, object_rvalue):
iterator = code_block.declare_variable("std::map<void*, PyObject*>::const_iterator", "wrapper_lookup_iter")
#code_block.write_code('std::cerr << "Lookup Wrapper: obj=" <<(void *) %s << " map size: " << %s.size() << std::endl;'
# % (object_rvalue, self.map_name))
code_block.write_code("%s = %s.find((void *) %s);" % (iterator, self.map_name, object_rvalue))
code_block.write_code("if (%(ITER)s == %(MAP)s.end()) {\n"
" %(WRAPPER)s = NULL;\n"
"} else {\n"
" %(WRAPPER)s = (%(TYPE)s *) %(ITER)s->second;\n"
" Py_INCREF(%(WRAPPER)s);\n"
"}\n"
% dict(ITER=iterator, MAP=self.map_name, WRAPPER=wrapper_lvalue, TYPE=wrapper_type))
def write_unregister_wrapper(self, code_block, wrapper_lvalue, object_rvalue):
#code_block.write_code('std::cerr << "Erase Wrapper: obj=" <<(void *) %s << std::endl;'
# % (object_rvalue))
iterator = code_block.declare_variable("std::map<void*, PyObject*>::iterator", "wrapper_lookup_iter")
code_block.write_code("%(ITER)s = %(MAP)s.find((void *) %(WRAPPER)s->obj);\n"
"if (%(ITER)s != %(MAP)s.end()) {\n"
" %(MAP)s.erase(%(ITER)s);\n"
"}\n"
% dict(ITER=iterator, MAP=self.map_name, WRAPPER=wrapper_lvalue))
|