File: converter_functions.py

package info (click to toggle)
spring 103.0%2Bdfsg2-1
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 43,720 kB
  • ctags: 63,685
  • sloc: cpp: 368,283; ansic: 33,988; python: 12,417; java: 12,203; awk: 5,879; sh: 1,846; xml: 655; perl: 405; php: 211; objc: 194; makefile: 77; sed: 2
file content (144 lines) | stat: -rw-r--r-- 5,621 bytes parent folder | download | duplicates (9)
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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
"""
Generates simple converter functions that convert a single value from
python to C or C to python.  These can be useful in certain
specialized contexts, such as converting list elements.
"""

from typehandlers.base import ReverseWrapperBase, ForwardWrapperBase
from typehandlers import ctypeparser

class PythonToCConverter(ReverseWrapperBase):
    '''
    Utility function that converts a single Python object into a C
    value.  The generated function can be used as a 'converter
    function' with the O& converter of PyArg_ParseTuple*.
    '''
    NO_GIL_LOCKING = True

    def __init__(self, value_type, c_function_name):
        """
        value_type -- a ReturnValue object handling the value type;
        class_ -- the class (CppClass object)
        attribute_name -- name of attribute
        getter -- None, or name of a method of the class used to get the value
        """
        self.c_function_name = c_function_name

        if value_type.type_traits.type_is_reference:
            value_type.type_traits = ctypeparser.TypeTraits(str(value_type.type_traits.target))
        value_type.ctype = str(value_type.ctype)

        self.type_no_ref = str(value_type.type_traits.ctype_no_modifiers)
        super(PythonToCConverter, self).__init__(value_type, [], error_return="return 0;")

    def generate_python_call(self):
        pass

    def generate(self, code_sink, wrapper_name, dummy_decl_modifiers=('static',),
                 dummy_decl_post_modifiers=()):
        """
        code_sink -- a CodeSink instance that will receive the generated code
        """
        
        self.declarations.declare_variable('PyObject*', 'py_retval')
        self.before_call.write_code(
            'py_retval = Py_BuildValue((char *) "(O)", value);')
        self.before_call.add_cleanup_code('Py_DECREF(py_retval);')

        save_return_value_value = self.return_value.value
        save_return_value_REQUIRES_ASSIGNMENT_CONSTRUCTOR = self.return_value.REQUIRES_ASSIGNMENT_CONSTRUCTOR
        self.return_value.value = "*address"
        self.return_value.REQUIRES_ASSIGNMENT_CONSTRUCTOR = False
        try:
            self.return_value.convert_python_to_c(self)
        finally:
            self.return_value.value = save_return_value_value
            self.return_value.REQUIRES_ASSIGNMENT_CONSTRUCTOR = save_return_value_REQUIRES_ASSIGNMENT_CONSTRUCTOR

        parse_tuple_params = ['py_retval']
        params = self.parse_params.get_parameters()
        assert params[0][0] == '"'
        params[0] = '(char *) ' + params[0]
        parse_tuple_params.extend(params)
        self.before_call.write_error_check('!PyArg_ParseTuple(%s)' %
                                           (', '.join(parse_tuple_params),))

        ## cleanup and return
        self.after_call.write_cleanup()
        self.after_call.write_code('return 1;')

        ## now generate the function itself
        code_sink.writeln("int %s(PyObject *value, %s *address)"
                          % (wrapper_name, self.type_no_ref))
        code_sink.writeln('{')
        code_sink.indent()

        self.declarations.get_code_sink().flush_to(code_sink)
        code_sink.writeln()
        self.before_call.sink.flush_to(code_sink)
        self.after_call.sink.flush_to(code_sink)

        code_sink.unindent()
        code_sink.writeln('}')

    def get_prototype(self):
        return "int %s(PyObject *value, %s *address)" % (self.c_function_name, self.type_no_ref)



class CToPythonConverter(ForwardWrapperBase):
    '''
    Utility function that converts a C value to a PyObject*.
    '''

    def __init__(self, value_type, c_function_name):
        """
        value_type -- a ReturnValue object handling the value type;
        class_ -- the class (CppClass object)
        attribute_name -- name of attribute
        getter -- None, or name of a method of the class used to get the value
        """
        super(CToPythonConverter, self).__init__(value_type, [], parse_error_return="return 0;", error_return="return 0;",
                                                 no_c_retval=True)
        self.c_function_name = c_function_name
        self.unblock_threads = False

    def generate(self, code_sink):

        save_return_value_value = self.return_value.value
        self.return_value.value = "*cvalue"
        try:
            self.return_value.convert_c_to_python(self)
        finally:
            self.return_value.value = save_return_value_value

        code_sink.writeln(self.get_prototype())
        code_sink.writeln("{")
        code_sink.indent()


        params = self.build_params.get_parameters()
        if params:
            if params == ['""']:
                self.after_call.write_code('Py_INCREF(Py_None);')
                self.after_call.write_code('py_retval = Py_None;')
            else:
                assert params[0][0] == '"'
                params[0] = "(char *) " + params[0]
                self.after_call.write_code('py_retval = Py_BuildValue(%s);' %
                                           (', '.join(params),))

        ## cleanup and return
        self.after_call.write_cleanup()
        self.after_call.write_code('return py_retval;')

        self.declarations.get_code_sink().flush_to(code_sink)
        code_sink.writeln()
        self.before_parse.sink.flush_to(code_sink)
        self.before_call.sink.flush_to(code_sink)
        self.after_call.sink.flush_to(code_sink)
        code_sink.unindent()
        code_sink.writeln("}")

    def get_prototype(self):
        return "PyObject* %s(%s *cvalue)" % (self.c_function_name, self.return_value.ctype)