Support C++ instance attributes through getter/setter methods (Bug #136993)

This commit is contained in:
Gustavo J. A. M. Carneiro committed 2007-09-08 23:29:59 +01:00
1 parent 7fdd88415d
commit 5b7ae2645d
4 files changed
+44 -9

No files matched your search

+3
View File
@@ -114,6 +114,9 @@ def my_module_gen(out_file):
SomeObject = CppClass('SomeObject', allow_subclassing=True)
mod.add_class(SomeObject)
SomeObject.add_instance_attribute(ReturnValue.new('Foo'), 'foo',
getter='get_foo_value',
setter='set_foo_value')
SomeObject.add_instance_attribute(ReturnValue.new('std::string'), 'm_prefix')
SomeObject.add_static_attribute(ReturnValue.new('std::string'), 'staticData')
+7
View File
@@ -536,6 +536,13 @@ class TestFoo(unittest.TestCase):
prefix = t.get_prefix_with_foo_ptr(foo1)
self.assertEqual(prefix, "123zbr456zbr")
def test_attribute_with_getset(self):
obj = foo.SomeObject("")
f1 = foo.Foo("hello")
obj.foo = f1
f2 = obj.foo
self.assertEqual(f2.get_datum(), "hello")
if __name__ == '__main__':
unittest.main()
+25 -4
View File
@@ -30,19 +30,24 @@ class CppInstanceAttributeGetter(PyGetter):
'''
A getter for a C++ instance attribute.
'''
def __init__(self, value_type, class_, attribute_name):
def __init__(self, value_type, class_, attribute_name, getter=None):
"""
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(CppInstanceAttributeGetter, self).__init__(
value_type, [], "return NULL;", "return NULL;", no_c_retval=True)
self.class_ = class_
self.attribute_name = attribute_name
self.getter = getter
self.c_function_name = "_wrap_%s__get_%s" % (self.class_.pystruct,
self.attribute_name)
value_type.value = "self->obj->%s" % self.attribute_name
if self.getter is None:
value_type.value = "self->obj->%s" % self.attribute_name
else:
value_type.value = "self->obj->%s()" % self.getter
def generate_call(self):
"virtual method implementation; do not call"
@@ -104,19 +109,20 @@ class CppInstanceAttributeSetter(PySetter):
'''
A setter for a C++ instance attribute.
'''
def __init__(self, value_type, class_, attribute_name):
def __init__(self, value_type, class_, attribute_name, setter=None):
"""
value_type -- a ReturnValue object handling the value type;
class_ -- the class (CppClass object)
attribute_name -- name of attribute
setter -- None, or name of a method of the class used to set the value
"""
super(CppInstanceAttributeSetter, self).__init__(
value_type, [], "return -1;")
self.class_ = class_
self.attribute_name = attribute_name
self.setter = setter
self.c_function_name = "_wrap_%s__set_%s" % (self.class_.pystruct,
self.attribute_name)
value_type.value = "self->obj->%s" % self.attribute_name
def generate(self, code_sink):
"""
@@ -127,11 +133,26 @@ class CppInstanceAttributeSetter(PySetter):
self.before_call.write_code(
'py_retval = Py_BuildValue("(O)", value);')
self.before_call.add_cleanup_code('Py_DECREF(py_retval);')
if self.setter is not None:
## if we have a setter method, redirect the value to a temporary variable
value_var = self.declarations.declare_variable(self.return_value.ctype, 'tmp_value')
self.return_value.value = value_var
else:
## else the value is written directly to a C++ instance attribute
self.return_value.value = "self->obj->%s" % self.attribute_name
self.return_value.convert_python_to_c(self)
parse_tuple_params = ['py_retval']
parse_tuple_params.extend(self.parse_params.get_parameters())
self.before_call.write_error_check('!PyArg_ParseTuple(%s)' %
(', '.join(parse_tuple_params),))
if self.setter is not None:
## if we have a setter method, now is the time to call it
self.after_call.write_code("self->obj->%s(%s);" % (self.setter, value_var))
## cleanup and return
self.after_call.write_cleanup()
self.after_call.write_code('return 0;')
+9 -5
View File
@@ -472,19 +472,23 @@ public:
setter = CppStaticAttributeSetter(value_type, self, name)
self.static_attributes.add_attribute(name, getter, setter)
def add_instance_attribute(self, value_type, name, is_const=False):
def add_instance_attribute(self, value_type, name, is_const=False,
getter=None, setter=None):
"""
value_type -- a ReturnValue object
name -- attribute name (i.e. the name of the class member variable)
is_const -- True if the attribute is const, i.e. cannot be modified
getter -- None, or name of a method of this class used to get the value
setter -- None, or name of a method of this class used to set the value
"""
assert isinstance(value_type, ReturnValue)
getter = CppInstanceAttributeGetter(value_type, self, name)
getter_wrapper = CppInstanceAttributeGetter(value_type, self, name, getter=getter)
if is_const:
setter = None
setter_wrapper = None
assert setter is None
else:
setter = CppInstanceAttributeSetter(value_type, self, name)
self.instance_attributes.add_attribute(name, getter, setter)
setter_wrapper = CppInstanceAttributeSetter(value_type, self, name, setter=setter)
self.instance_attributes.add_attribute(name, getter_wrapper, setter_wrapper)
def generate_forward_declarations(self, code_sink):
"""Generates forward declarations for the instance and type