File: wrapper_registry.py

package info (click to toggle)
spring 106.0%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 55,260 kB
  • sloc: cpp: 543,946; ansic: 44,800; python: 12,575; java: 12,201; awk: 5,889; sh: 1,796; asm: 1,546; xml: 655; perl: 405; php: 211; objc: 194; makefile: 76; sed: 2
file content (130 lines) | stat: -rw-r--r-- 5,975 bytes parent folder | download | duplicates (7)
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))