diff --git a/pybindgen/cppclass.py b/pybindgen/cppclass.py index d962b2f..4329912 100644 --- a/pybindgen/cppclass.py +++ b/pybindgen/cppclass.py @@ -1,5 +1,4 @@ -""" -Wrap C++ classes and methods + C++ classes and methods """ import warnings diff --git a/pybindgen/typehandlers/__init__.py b/pybindgen/typehandlers/__init__.py index c196c98..2f0f7dd 100644 --- a/pybindgen/typehandlers/__init__.py +++ b/pybindgen/typehandlers/__init__.py @@ -6,5 +6,6 @@ import inttype import stringtype import booltype import doubletype +import pyobjecttype diff --git a/pybindgen/typehandlers/pyobjecttype.py b/pybindgen/typehandlers/pyobjecttype.py new file mode 100644 index 0000000..fe783a3 --- /dev/null +++ b/pybindgen/typehandlers/pyobjecttype.py @@ -0,0 +1,65 @@ +# docstrings not neede here (the type handler doubleerfaces are fully +# documented in base.py) pylint: disable-msg=C0111 + +from base import ReturnValue, Parameter, \ + ReverseWrapperBase, ForwardWrapperBase + + +class PyObjectParam(Parameter): + + DIRECTIONS = [Parameter.DIRECTION_IN] + CTYPES = ['PyObject*'] + + def __init__(self, ctype, name, transfer_ownership): + """ + ctype -- C type, normally 'PyObject*' + name -- parameter name + transfer_ownership -- this parameter transfer the ownership of + the pointed-to object to the called + function + """ + super(PyObjectParam, self).__init__( + ctype, name, direction=Parameter.DIRECTION_IN) + self.transfer_ownership = transfer_ownership + + def convert_c_to_python(self, wrapper): + assert isinstance(wrapper, ReverseWrapperBase) + if self.transfer_ownership: + wrapper.build_params.add_parameter('N', [self.value]) + else: + wrapper.build_params.add_parameter('O', [self.value]) + + def convert_python_to_c(self, wrapper): + assert isinstance(wrapper, ForwardWrapperBase) + name = wrapper.declarations.declare_variable(self.ctype, self.name) + wrapper.parse_params.add_parameter('O', ['&'+name]) + wrapper.call_params.append(name) + if self.transfer_ownership: + wrapper.before_call.write_code("Py_INCREF(%s);" % name) + + +class PyObjectReturnValue(ReturnValue): + + CTYPES = ['PyObject*'] + + def __init__(self, ctype, caller_owns_return): + """ + ctype -- C type, normally 'MyClass*' + caller_owns_return -- if true, ownership of the object pointer + is transferred to the caller + """ + super(PyObjectReturnValue, self).__init__(ctype) + self.caller_owns_return = caller_owns_return + + def get_c_error_return(self): + return "return NULL;" + + def convert_python_to_c(self, wrapper): + wrapper.parse_params.add_parameter("O", ["&"+self.value], prepend=True) + if self.caller_owns_return: + wrapper.after_call.write_code("Py_INCREF(%s);" % self.value) + + def convert_c_to_python(self, wrapper): + wrapper.build_params.add_parameter( + (self.caller_owns_return and "N" or "O"), + [self.value], prepend=True) diff --git a/tests/test-generation.py b/tests/test-generation.py index 8a1e15a..e622379 100755 --- a/tests/test-generation.py +++ b/tests/test-generation.py @@ -56,7 +56,8 @@ public: ## test return type handlers of reverse wrappers for return_type, return_handler in typehandlers.base.return_type_matcher.items(): - if issubclass(return_handler, cppclass.CppClassPtrReturnValue): + if issubclass(return_handler, (cppclass.CppClassPtrReturnValue, + typehandlers.pyobjecttype.PyObjectReturnValue)): for caller_owns_return in True, False: retval = return_handler(return_type, caller_owns_return=caller_owns_return) wrapper = MyReverseWrapper(retval, []) @@ -116,7 +117,8 @@ public: print "%s %s(void);" % (return_type, function_name) print - if issubclass(return_handler, cppclass.CppClassPtrReturnValue): + if issubclass(return_handler, (cppclass.CppClassPtrReturnValue, + typehandlers.pyobjecttype.PyObjectReturnValue)): retval = return_handler(return_type, caller_owns_return=True) else: retval = return_handler(return_type) @@ -133,7 +135,8 @@ public: elif direction == (Parameter.DIRECTION_OUT): param_name = 'param_out' - if issubclass(param_handler, cppclass.CppClassPtrParameter): + if issubclass(param_handler, (cppclass.CppClassPtrParameter, + typehandlers.pyobjecttype.PyObjectParam)): for transfer_ownership in True, False: name = param_name + (transfer_ownership and '_transfer' or '_notransfer') param = param_handler(param_type, name , transfer_ownership=transfer_ownership)