Esempio n. 1
0
 def __init__(self, method_name, wrapper_name, wrapper_body=None,
              flags=('METH_VARARGS', 'METH_KEYWORDS')):
     super(CustomCppMethodWrapper, self).__init__(method_name, ReturnValue.new('void'), [])
     self.wrapper_base_name = wrapper_name
     self.wrapper_actual_name = wrapper_name
     self.meth_flags = list(flags)
     self.wrapper_body = wrapper_body
Esempio n. 2
0
 def __init__(self, method_name, wrapper_name, wrapper_body=None,
              flags=('METH_VARARGS', 'METH_KEYWORDS'), docstring=None):
     super(CustomCppMethodWrapper, self).__init__(method_name, ReturnValue.new('void'), [], docstring=docstring)
     self.wrapper_base_name = wrapper_name
     self.wrapper_actual_name = wrapper_name
     self.meth_flags = list(flags)
     self.wrapper_body = wrapper_body
Esempio n. 3
0
 def try_wrapper(param, wrapper_number):
     if 'const' in param.ctype and direction&Parameter.DIRECTION_OUT:
         return
     wrapper = MyReverseWrapper(ReturnValue.new('void'), [param])
     try:
         wrapper.generate(code_out,
                          '_test_wrapper_number_%i' % (wrapper_number,),
                          ['static'])
     except NotImplementedError:
         print >> sys.stderr, ("ReverseWrapper void(%s) could not be generated: not implemented"
                               % (param.ctype))
     print
Esempio n. 4
0
 def try_wrapper(param, wrapper_number):
     if 'const' in param.ctype and direction&Parameter.DIRECTION_OUT:
         return
     wrapper = MyReverseWrapper(ReturnValue.new('void'), [param])
     try:
         wrapper.generate(code_out,
                          '_test_wrapper_number_%i' % (wrapper_number,),
                          ['static'])
     except NotImplementedError:
         print >> sys.stderr, ("ReverseWrapper void(%s) could not be generated: not implemented"
                               % (param.ctype))
     print
Esempio n. 5
0
 def try_wrapper(param, wrapper_number):
     if 'const' in param.ctype and direction&Parameter.DIRECTION_OUT:
         return
     code_out.writeln("/* Test %s (%s) param type  */" % (param_type, param_handler))
     wrapper = MyReverseWrapper(ReturnValue.new('void'), [param])
     try:
         wrapper.generate(code_out,
                          '_test_wrapper_number_%i' % (wrapper_number,),
                          ['static'])
     except NotImplementedError:
         sys.stderr.write("ReverseWrapper void(%s) could not be generated: not implemented"
                          % (param.ctype))
     sys.stdout.write("\n")
Esempio n. 6
0
 def try_wrapper(param, wrapper_number):
     if 'const' in param.ctype and direction&Parameter.DIRECTION_OUT:
         return
     code_out.writeln("/* Test %s (%s) param type  */" % (param_type, param_handler))
     wrapper = MyReverseWrapper(ReturnValue.new('void'), [param])
     try:
         wrapper.generate(code_out,
                          '_test_wrapper_number_%i' % (wrapper_number,),
                          ['static'])
     except NotImplementedError:
         sys.stderr.write("ReverseWrapper void(%s) could not be generated: not implemented"
                          % (param.ctype))
     sys.stdout.write("\n")
Esempio n. 7
0
 def __init__(self, function_name, wrapper_name, wrapper_body=None,
              flags=('METH_VARARGS', 'METH_KEYWORDS'), docstring=None):
     """
     :param function_name: name for function, Python side
     :param wrapper_name: name of the C wrapper function
     :param wrapper_body: if not None, the function wrapper is generated containing this parameter value as function body
     """
     super(CustomFunctionWrapper, self).__init__(function_name, ReturnValue.new('void'), [], docstring=docstring)
     self.wrapper_base_name = wrapper_name
     self.wrapper_actual_name = wrapper_name
     self.meth_flags = list(flags)
     self.wrapper_body = wrapper_body
     self.wrapper_args = ["PyObject *args", "PyObject *kwargs", "PyObject **return_exception"]
     self.wrapper_return = "PyObject *"
Esempio n. 8
0
 def __init__(self, function_name, wrapper_name, wrapper_body=None,
              flags=('METH_VARARGS', 'METH_KEYWORDS'), docstring=None):
     """
     :param function_name: name for function, Python side
     :param wrapper_name: name of the C wrapper function
     :param wrapper_body: if not None, the function wrapper is generated containing this parameter value as function body
     """
     super(CustomFunctionWrapper, self).__init__(function_name, ReturnValue.new('void'), [], docstring=docstring)
     self.wrapper_base_name = wrapper_name
     self.wrapper_actual_name = wrapper_name
     self.meth_flags = list(flags)
     self.wrapper_body = wrapper_body
     self.wrapper_args = ["PyObject *args", "PyObject *kwargs", "PyObject **return_exception"]
     self.wrapper_return = "PyObject *"
Esempio n. 9
0
    def __init__(self, method_name, return_value, parameters, is_static=False,
                 template_parameters=(), is_virtual=None, is_const=False,
                 unblock_threads=None, is_pure_virtual=False,
                 custom_template_method_name=None, visibility='public',
                 custom_name=None, deprecated=False, docstring=None, throw=()):
        """
        Create an object the generates code to wrap a C++ class method.

        :param return_value: the method return value
        :type  return_value: L{ReturnValue}

        :param method_name: name of the method

        :param parameters: the method parameters
        :type parameters: list of :class:`pybindgen.typehandlers.base.Parameter`

        :param is_static: whether it is a static method

        :param template_parameters: optional list of template parameters needed to invoke the method
        :type template_parameters: list of strings, each element a template parameter expression

        :param is_virtual: whether the method is virtual (pure or not)

        :param is_const: whether the method has a const modifier on it

        :param unblock_threads: whether to release the Python GIL
            around the method call or not.  If None or omitted, use
            global settings.  Releasing the GIL has a small
            performance penalty, but is recommended if the method is
            expected to take considerable time to complete, because
            otherwise no other Python thread is allowed to run until
            the method completes.

        :param is_pure_virtual: whether the method is defined as "pure
          virtual", i.e. virtual method with no default implementation
          in the class being wrapped.

        :param custom_name: alternate name to give to the method, in python side.

        :param custom_template_method_name: (deprecated) same as parameter 'custom_name'.

        :param visibility: visibility of the method within the C++ class
        :type visibility: a string (allowed values are 'public', 'protected', 'private')

        :param deprecated: deprecation state for this API:
          - False: Not deprecated
          - True: Deprecated
          - "message": Deprecated, and deprecation warning contains the given message

        :param throw: list of C++ exceptions that the function may throw
        :type throw: list of L{CppException}
        """
        self.stack_where_defined = traceback.extract_stack()

        ## backward compatibility check
        if isinstance(return_value, str) and isinstance(method_name, ReturnValue):
            warnings.warn("CppMethod has changed API; see the API documentation (but trying to correct...)",
                          DeprecationWarning, stacklevel=2)
            method_name, return_value = return_value, method_name

        # bug 399870
        if is_virtual is None:
            is_virtual = is_pure_virtual
            
        if return_value is None:
            return_value = ReturnValue.new('void')

        if unblock_threads is None:
            unblock_threads = settings.unblock_threads

        assert visibility in ['public', 'protected', 'private']
        self.visibility = visibility
        self.method_name = method_name
        self.is_static = is_static
        self.is_virtual = is_virtual
        self.is_pure_virtual = is_pure_virtual
        self.is_const = is_const
        self.template_parameters = template_parameters

        self.custom_name = (custom_name or custom_template_method_name)

        #self.static_decl = True
        self._class = None
        self._helper_class = None
        self.docstring = docstring
        self.wrapper_base_name = None
        self.wrapper_actual_name = None
        self.return_value = None
        self.parameters = None

        return_value = utils.eval_retval(return_value, self)
        parameters = [utils.eval_param(param, self) for param in parameters]

        super(CppMethod, self).__init__(
            return_value, parameters,
            "return NULL;", "return NULL;",
            unblock_threads=unblock_threads)
        self.deprecated = deprecated

        for t in throw:
            assert isinstance(t, CppException)
        self.throw = list(throw)

        self.custodians_and_wards = [] # list of (custodian, ward, postcall)
        from . import cppclass
        cppclass.scan_custodians_and_wards(self)
Esempio n. 10
0
    def __init__(self, method_name, return_value, parameters, is_static=False,
                 template_parameters=(), is_virtual=None, is_const=False,
                 unblock_threads=None, is_pure_virtual=False,
                 custom_template_method_name=None, visibility='public',
                 custom_name=None, deprecated=False, docstring=None, throw=()):
        """
        Create an object the generates code to wrap a C++ class method.

        :param return_value: the method return value
        :type  return_value: L{ReturnValue}

        :param method_name: name of the method

        :param parameters: the method parameters
        :type parameters: list of :class:`pybindgen.typehandlers.base.Parameter`

        :param is_static: whether it is a static method

        :param template_parameters: optional list of template parameters needed to invoke the method
        :type template_parameters: list of strings, each element a template parameter expression

        :param is_virtual: whether the method is virtual (pure or not)

        :param is_const: whether the method has a const modifier on it

        :param unblock_threads: whether to release the Python GIL
            around the method call or not.  If None or omitted, use
            global settings.  Releasing the GIL has a small
            performance penalty, but is recommended if the method is
            expected to take considerable time to complete, because
            otherwise no other Python thread is allowed to run until
            the method completes.

        :param is_pure_virtual: whether the method is defined as "pure
          virtual", i.e. virtual method with no default implementation
          in the class being wrapped.

        :param custom_name: alternate name to give to the method, in python side.

        :param custom_template_method_name: (deprecated) same as parameter 'custom_name'.

        :param visibility: visibility of the method within the C++ class
        :type visibility: a string (allowed values are 'public', 'protected', 'private')

        :param deprecated: deprecation state for this API:
          - False: Not deprecated
          - True: Deprecated
          - "message": Deprecated, and deprecation warning contains the given message

        :param throw: list of C++ exceptions that the function may throw
        :type throw: list of L{CppException}
        """
        self.stack_where_defined = traceback.extract_stack()

        ## backward compatibility check
        if isinstance(return_value, str) and isinstance(method_name, ReturnValue):
            warnings.warn("CppMethod has changed API; see the API documentation (but trying to correct...)",
                          DeprecationWarning, stacklevel=2)
            method_name, return_value = return_value, method_name

        # bug 399870
        if is_virtual is None:
            is_virtual = is_pure_virtual
            
        if return_value is None:
            return_value = ReturnValue.new('void')

        if unblock_threads is None:
            unblock_threads = settings.unblock_threads

        assert visibility in ['public', 'protected', 'private']
        self.visibility = visibility
        self.method_name = method_name
        self.is_static = is_static
        self.is_virtual = is_virtual
        self.is_pure_virtual = is_pure_virtual
        self.is_const = is_const
        self.template_parameters = template_parameters

        self.custom_name = (custom_name or custom_template_method_name)

        #self.static_decl = True
        self._class = None
        self._helper_class = None
        self.docstring = docstring
        self.wrapper_base_name = None
        self.wrapper_actual_name = None
        self.return_value = None
        self.parameters = None

        return_value = utils.eval_retval(return_value, self)
        parameters = [utils.eval_param(param, self) for param in parameters]

        super(CppMethod, self).__init__(
            return_value, parameters,
            "return NULL;", "return NULL;",
            unblock_threads=unblock_threads)
        self.deprecated = deprecated

        for t in throw:
            assert isinstance(t, CppException)
        self.throw = list(throw)

        self.custodians_and_wards = [] # list of (custodian, ward, postcall)
        from . import cppclass
        cppclass.scan_custodians_and_wards(self)
Esempio n. 11
0
    def __init__(self,
                 function_name,
                 return_value,
                 parameters,
                 docstring=None,
                 unblock_threads=None,
                 template_parameters=(),
                 custom_name=None,
                 deprecated=False,
                 foreign_cpp_namespace=None,
                 throw=()):
        """
        :param function_name: name of the C function
        :param return_value: the function return value
        :type return_value: L{ReturnValue}
        :param parameters: the function parameters
        :type parameters: list of L{Parameter}

        :param custom_name: an alternative name to give to this
           function at python-side; if omitted, the name of the
           function in the python module will be the same name as the
           function in C++ (minus namespace).

        :param deprecated: deprecation state for this API:
          - False: Not deprecated
          - True: Deprecated
          - "message": Deprecated, and deprecation warning contains the given message

        :param foreign_cpp_namespace: if set, the function is assumed
          to belong to the given C++ namespace, regardless of the C++
          namespace of the python module it will be added to.

        :param throw: list of C++ exceptions that the function may throw
        :type throw: list of L{CppException}
        """
        self.stack_where_defined = traceback.extract_stack()

        if unblock_threads is None:
            unblock_threads = settings.unblock_threads

        ## backward compatibility check
        if isinstance(return_value, string_types) and isinstance(
                function_name, ReturnValue):
            warnings.warn(
                "Function has changed API; see the API documentation (but trying to correct...)",
                DeprecationWarning,
                stacklevel=2)
            function_name, return_value = return_value, function_name

        if return_value is None:
            return_value = ReturnValue.new('void')

        return_value = utils.eval_retval(return_value, self)
        parameters = [utils.eval_param(param, self) for param in parameters]

        super(Function, self).__init__(return_value,
                                       parameters,
                                       parse_error_return="return NULL;",
                                       error_return="return NULL;",
                                       unblock_threads=unblock_threads)
        self.deprecated = deprecated
        self.foreign_cpp_namespace = foreign_cpp_namespace
        self._module = None
        function_name = utils.ascii(function_name)
        self.function_name = function_name
        self.wrapper_base_name = None
        self.wrapper_actual_name = None
        self.docstring = docstring
        self.self_parameter_pystruct = None
        self.template_parameters = template_parameters
        self.custom_name = custom_name
        for t in throw:
            assert isinstance(t, CppException)
        self.throw = list(throw)
        self.custodians_and_wards = []  # list of (custodian, ward, postcall)
        from pybindgen import cppclass
        cppclass.scan_custodians_and_wards(self)
Esempio n. 12
0
def test():
    code_out = codesink.FileCodeSink(sys.stdout)
    pybindgen.write_preamble(code_out)
    print
    print "#include <string>"
    print "#include <stdint.h>"
    print

    ## Declare a dummy class
    sys.stdout.write('''
class Foo
{
    std::string m_datum;
public:
    Foo () : m_datum ("")
        {}
    Foo (std::string datum) : m_datum (datum)
        {}
    std::string get_datum () const { return m_datum; }

    Foo (Foo const & other) : m_datum (other.get_datum ())
        {}
};
''')

    module = Module("foo")

    ## Register type handlers for the class
    Foo = cppclass.CppClass('Foo')
    Foo.module = module
    #Foo.full_name = Foo.name # normally adding the class to a module would take care of this
    Foo.generate_forward_declarations(code_out, module)

    wrapper_number = 0

    ## test return type handlers of reverse wrappers
    for return_type, return_handler in typehandlers.base.return_type_matcher.items(
    ):
        if os.name == 'nt':
            if stdint_rx.search(return_type):
                continue  # win32 does not support the u?int\d+_t types (defined in <stdint.h>)
        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, [])
                wrapper_number += 1
                try:
                    wrapper.generate(
                        code_out,
                        '_test_wrapper_number_%i' % (wrapper_number, ),
                        ['static'])
                except NotImplementedError:
                    print >> sys.stderr, \
                        ("ReverseWrapper %s(void) (caller_owns_return=%r)"
                         " could not be generated: not implemented"
                         % (retval.ctype, caller_owns_return))
                print
        else:
            retval = return_handler(return_type)
            try:
                wrapper = MyReverseWrapper(retval, [])
            except NotSupportedError:
                continue
            wrapper_number += 1
            try:
                wrapper.generate(
                    code_out, '_test_wrapper_number_%i' % (wrapper_number, ),
                    ['static'])
            except NotImplementedError:
                print >> sys.stderr, (
                    "ReverseWrapper %s(void) could not be generated: not implemented"
                    % (retval.ctype, ))
            print

    ## test parameter type handlers of reverse wrappers
    for param_type, param_handler in typehandlers.base.param_type_matcher.items(
    ):
        if os.name == 'nt':
            if stdint_rx.search(param_type):
                continue  # win32 does not support the u?int\d+_t types (defined in <stdint.h>)
        for direction in param_handler.DIRECTIONS:
            if direction == (Parameter.DIRECTION_IN):
                param_name = 'param'
            elif direction == (Parameter.DIRECTION_IN
                               | Parameter.DIRECTION_OUT):
                param_name = 'param_inout'
            elif direction == (Parameter.DIRECTION_OUT):
                param_name = 'param_out'

                def try_wrapper(param, wrapper_number):
                    if 'const' in param.ctype and direction & Parameter.DIRECTION_OUT:
                        return
                    wrapper = MyReverseWrapper(ReturnValue.new('void'),
                                               [param])
                    try:
                        wrapper.generate(
                            code_out,
                            '_test_wrapper_number_%i' % (wrapper_number, ),
                            ['static'])
                    except NotImplementedError:
                        print >> sys.stderr, (
                            "ReverseWrapper void(%s) could not be generated: not implemented"
                            % (param.ctype))
                    print

                if issubclass(param_handler,
                              (cppclass.CppClassPtrParameter,
                               typehandlers.pyobjecttype.PyObjectParam)):
                    for transfer_ownership in True, False:
                        try:
                            param = param_handler(
                                param_type,
                                param_name,
                                transfer_ownership=transfer_ownership)
                        except TypeError:
                            print >> sys.stderr, "ERROR -----> param_handler(param_type=%r, "\
                                "transfer_ownership=%r, is_const=%r)"\
                                % (param_type, transfer_ownership, is_const)
                        wrapper_number += 1
                        try_wrapper(param, wrapper_number)
                else:
                    param = param_handler(param_type, param_name, direction)
                    wrapper_number += 1
                    try_wrapper(param, wrapper_number)

    ## test generic forward wrappers, and module

    for return_type, return_handler in typehandlers.base.return_type_matcher.items(
    ):
        if os.name == 'nt':
            if stdint_rx.search(return_type):
                continue  # win32 does not support the u?int\d+_t types (defined in <stdint.h>)
        wrapper_number += 1
        function_name = 'foo_function_%i' % (wrapper_number, )
        ## declare a fake prototype
        print "%s %s(void);" % (return_type, function_name)
        print

        if issubclass(return_handler,
                      (cppclass.CppClassPtrReturnValue,
                       typehandlers.pyobjecttype.PyObjectReturnValue)):
            retval = return_handler(return_type, caller_owns_return=True)
        else:
            retval = return_handler(return_type)

        module.add_function(function_name, retval, [])

    for param_type, param_handler in typehandlers.base.param_type_matcher.items(
    ):
        if os.name == 'nt':
            if stdint_rx.search(param_type):
                continue  # win32 does not support the u?int\d+_t types (defined in <stdint.h>)

        for is_const in [True, False]:
            for direction in param_handler.DIRECTIONS:
                if direction == (Parameter.DIRECTION_IN):
                    param_name = 'param'
                elif direction == (Parameter.DIRECTION_IN
                                   | Parameter.DIRECTION_OUT):
                    param_name = 'param_inout'
                elif direction == (Parameter.DIRECTION_OUT):
                    param_name = 'param_out'

                if is_const and direction & Parameter.DIRECTION_OUT:
                    continue  # const and output parameter makes no sense

                if is_const:
                    if '&' in param_type:  # const references not allowed
                        continue
                    param_type_with_const = "const %s" % (param_type, )
                else:
                    param_type_with_const = param_type

                if issubclass(param_handler,
                              (cppclass.CppClassPtrParameter,
                               typehandlers.pyobjecttype.PyObjectParam)):
                    for transfer_ownership in True, False:
                        name = param_name + (transfer_ownership and '_transfer'
                                             or '_notransfer')
                        try:
                            param = param_handler(
                                param_type,
                                name,
                                transfer_ownership=transfer_ownership)
                        except TypeError:
                            print >> sys.stderr, "ERROR -----> param_handler(param_type=%r, "\
                                "name=%r, transfer_ownership=%r, is_const=%r)"\
                                % (param_type, name, transfer_ownership, is_const)
                        wrapper_number += 1
                        function_name = 'foo_function_%i' % (wrapper_number, )
                        ## declare a fake prototype
                        print "void %s(%s %s);" % (function_name,
                                                   param_type_with_const, name)
                        print
                        module.add_function(function_name,
                                            ReturnValue.new('void'), [param])
                else:
                    param = param_handler(param_type, param_name, direction)
                    wrapper_number += 1
                    function_name = 'foo_function_%i' % (wrapper_number, )
                    ## declare a fake prototype
                    print "void %s(%s);" % (function_name,
                                            param_type_with_const)
                    print
                    module.add_function(function_name, ReturnValue.new('void'),
                                        [param])

    module.generate(code_out)
Esempio n. 13
0
    def __init__(self, function_name, return_value, parameters, docstring=None, unblock_threads=None,
                 template_parameters=(), custom_name=None, deprecated=False, foreign_cpp_namespace=None,
                 throw=()):
        """
        :param function_name: name of the C function
        :param return_value: the function return value
        :type return_value: L{ReturnValue}
        :param parameters: the function parameters
        :type parameters: list of L{Parameter}

        :param custom_name: an alternative name to give to this
           function at python-side; if omitted, the name of the
           function in the python module will be the same name as the
           function in C++ (minus namespace).

        :param deprecated: deprecation state for this API:
          - False: Not deprecated
          - True: Deprecated
          - "message": Deprecated, and deprecation warning contains the given message

        :param foreign_cpp_namespace: if set, the function is assumed
          to belong to the given C++ namespace, regardless of the C++
          namespace of the python module it will be added to.

        :param throw: list of C++ exceptions that the function may throw
        :type throw: list of L{CppException}
        """
        self.stack_where_defined = traceback.extract_stack()

        if unblock_threads is None:
            unblock_threads = settings.unblock_threads
        
        ## backward compatibility check
        if isinstance(return_value, string_types) and isinstance(function_name, ReturnValue):
            warnings.warn("Function has changed API; see the API documentation (but trying to correct...)",
                          DeprecationWarning, stacklevel=2)
            function_name, return_value = return_value, function_name
            
        if return_value is None:
            return_value = ReturnValue.new('void')

        return_value = utils.eval_retval(return_value, self)
        parameters = [utils.eval_param(param, self) for param in parameters]

        super(Function, self).__init__(
            return_value, parameters,
            parse_error_return="return NULL;",
            error_return="return NULL;",
            unblock_threads=unblock_threads)
        self.deprecated = deprecated
        self.foreign_cpp_namespace = foreign_cpp_namespace
        self._module = None
        function_name = utils.ascii(function_name)
        self.function_name = function_name
        self.wrapper_base_name = None
        self.wrapper_actual_name = None
        self.docstring = docstring
        self.self_parameter_pystruct = None
        self.template_parameters = template_parameters
        self.custom_name = custom_name
        for t in throw:
            assert isinstance(t, CppException)
        self.throw = list(throw)
        self.custodians_and_wards = [] # list of (custodian, ward, postcall)
        from pybindgen import cppclass
        cppclass.scan_custodians_and_wards(self)
Esempio n. 14
0
def test():
    code_out = codesink.FileCodeSink(sys.stdout)
    pybindgen.write_preamble(code_out)
    sys.stdout.write("""
#include <string>
#include <stdint.h>
""")
    ## Declare a dummy class
    sys.stdout.write('''
class Foo
{
    std::string m_datum;
public:
    Foo () : m_datum ("")
        {}
    Foo (std::string datum) : m_datum (datum)
        {}
    std::string get_datum () const { return m_datum; }

    Foo (Foo const & other) : m_datum (other.get_datum ())
        {}
};
''')

    module = Module("foo")

    ## Register type handlers for the class
    Foo = cppclass.CppClass('Foo')
    Foo.module = module
    #Foo.full_name = Foo.name # normally adding the class to a module would take care of this
    Foo.generate_forward_declarations(code_out, module)

    wrapper_number = 0

    ## test return type handlers of reverse wrappers
    for return_type, return_handler in list(typehandlers.base.return_type_matcher.items()):
        if type_blacklisted(return_type):
            continue
        if os.name == 'nt':
            if stdint_rx.search(return_type):
                continue # win32 does not support the u?int\d+_t types (defined in <stdint.h>)

        code_out.writeln("/* Test %s (%s) return type  */" % (return_type, return_handler))
        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, [])
                wrapper_number += 1
                try:
                    wrapper.generate(code_out,
                                     '_test_wrapper_number_%i' % (wrapper_number,),
                                     ['static'])
                except NotImplementedError:
                    sys.stderr.write("ReverseWrapper %s(void) (caller_owns_return=%r)"
                                     " could not be generated: not implemented\n"
                                     % (retval.ctype, caller_owns_return))
                sys.stdout.write("\n")
        else:
            retval = return_handler(return_type)
            try:
                wrapper = MyReverseWrapper(retval, [])
            except NotSupportedError:
                continue
            except NotImplementedError:
                sys.stderr.write("ReverseWrapper %s(void) could not be generated: not implemented\n"
                                 % (retval.ctype))
                continue
            wrapper_number += 1
            memsink = codesink.MemoryCodeSink()
            try:
                wrapper.generate(memsink,
                                 '_test_wrapper_number_%i' % (wrapper_number,),
                                 ['static'])
            except NotImplementedError:
                sys.stderr.write("ReverseWrapper %s xxx (void) could not be generated: not implemented\n"
                                 % (retval.ctype,))
                continue
            except NotSupportedError:
                continue
            else:
                memsink.flush_to(code_out)
            sys.stdout.write("\n")


    ## test parameter type handlers of reverse wrappers
    for param_type, param_handler in list(typehandlers.base.param_type_matcher.items()):
        if type_blacklisted(param_type):
            continue
        if os.name == 'nt':
            if stdint_rx.search(param_type):
                continue # win32 does not support the u?int\d+_t types (defined in <stdint.h>)
        for direction in param_handler.DIRECTIONS:
            if direction == (Parameter.DIRECTION_IN):
                param_name = 'param'
            elif direction == (Parameter.DIRECTION_IN|Parameter.DIRECTION_OUT):
                param_name = 'param_inout'
            elif direction == (Parameter.DIRECTION_OUT):
                param_name = 'param_out'

                def try_wrapper(param, wrapper_number):
                    if 'const' in param.ctype and direction&Parameter.DIRECTION_OUT:
                        return
                    code_out.writeln("/* Test %s (%s) param type  */" % (param_type, param_handler))
                    wrapper = MyReverseWrapper(ReturnValue.new('void'), [param])
                    try:
                        wrapper.generate(code_out,
                                         '_test_wrapper_number_%i' % (wrapper_number,),
                                         ['static'])
                    except NotImplementedError:
                        sys.stderr.write("ReverseWrapper void(%s) could not be generated: not implemented"
                                         % (param.ctype))
                    sys.stdout.write("\n")

                if issubclass(param_handler, (cppclass.CppClassPtrParameter,
                                              typehandlers.pyobjecttype.PyObjectParam)):
                    for transfer_ownership in True, False:
                        try:
                            param = param_handler(param_type, param_name, transfer_ownership=transfer_ownership)
                        except TypeError:
                            sys.stderr.write("ERROR -----> param_handler(param_type=%r, "
                                             "transfer_ownership=%r, is_const=%r)\n"
                                             % (param_type, transfer_ownership, is_const))
                        wrapper_number += 1
                        try_wrapper(param, wrapper_number)
                else:
                    param = param_handler(param_type, param_name, direction)
                    wrapper_number += 1
                    try_wrapper(param, wrapper_number)

    
    ## test generic forward wrappers, and module

    for return_type, return_handler in list(typehandlers.base.return_type_matcher.items()):
        if type_blacklisted(return_type):
            continue
        if os.name == 'nt':
            if stdint_rx.search(return_type):
                continue # win32 does not support the u?int\d+_t types (defined in <stdint.h>)
        wrapper_number += 1
        function_name = 'foo_function_%i' % (wrapper_number,)
        ## declare a fake prototype
        sys.stdout.write("%s %s(void);\n\n" % (return_type, function_name))

        if issubclass(return_handler, (cppclass.CppClassPtrReturnValue,
                                       typehandlers.pyobjecttype.PyObjectReturnValue)):
            retval = return_handler(return_type, caller_owns_return=True)
        else:
            retval = return_handler(return_type)

        module.add_function(function_name, retval, [])
    
    for param_type, param_handler in list(typehandlers.base.param_type_matcher.items()):
        if type_blacklisted(param_type):
            continue
        if os.name == 'nt':
            if stdint_rx.search(param_type):
                continue # win32 does not support the u?int\d+_t types (defined in <stdint.h>)

        for is_const in [True, False]:
            for direction in param_handler.DIRECTIONS:
                if direction == (Parameter.DIRECTION_IN):
                    param_name = 'param'
                elif direction == (Parameter.DIRECTION_IN|Parameter.DIRECTION_OUT):
                    param_name = 'param_inout'
                elif direction == (Parameter.DIRECTION_OUT):
                    param_name = 'param_out'

                if is_const and direction & Parameter.DIRECTION_OUT:
                    continue # const and output parameter makes no sense

                if is_const:
                    if '&' in param_type: # const references not allowed
                        continue
                    param_type_with_const = "const %s" % (param_type,)
                else:
                    param_type_with_const = param_type

                if issubclass(param_handler, (cppclass.CppClassPtrParameter,
                                              typehandlers.pyobjecttype.PyObjectParam)):
                    for transfer_ownership in True, False:
                        name = param_name + (transfer_ownership and '_transfer' or '_notransfer')
                        try:
                            param = param_handler(param_type, name, transfer_ownership=transfer_ownership)
                        except TypeError:
                            sys.stderr.write("ERROR -----> param_handler(param_type=%r, "
                                             "name=%r, transfer_ownership=%r, is_const=%r)\n"
                                             % (param_type, name, transfer_ownership, is_const))
                        wrapper_number += 1
                        function_name = 'foo_function_%i' % (wrapper_number,)
                        ## declare a fake prototype
                        sys.stdout.write("void %s(%s %s);\n\n" % (function_name, param_type_with_const, name))
                        module.add_function(function_name, ReturnValue.new('void'), [param])
                else:
                    param = param_handler(param_type, param_name, direction)
                    wrapper_number += 1
                    function_name = 'foo_function_%i' % (wrapper_number,)
                    ## declare a fake prototype
                    sys.stdout.write("void %s(%s);\n\n" % (function_name, param_type_with_const))
                    module.add_function(function_name, ReturnValue.new('void'), [param])

    module.generate(code_out)
Esempio n. 15
0
def test():
    code_out = codesink.FileCodeSink(sys.stdout)
    pybindgen.write_preamble(code_out)
    print
    print "#include <string>"
    print "#include <stdint.h>"
    print

    ## Declare a dummy class
    sys.stdout.write(
        """
class Foo
{
    std::string m_datum;
public:
    Foo () : m_datum ("")
        {}
    Foo (std::string datum) : m_datum (datum)
        {}
    std::string get_datum () const { return m_datum; }

    Foo (Foo const & other) : m_datum (other.get_datum ())
        {}
};
"""
    )

    module = Module("foo")

    ## Register type handlers for the class
    Foo = cppclass.CppClass("Foo")
    Foo.module = module
    # Foo.full_name = Foo.name # normally adding the class to a module would take care of this
    Foo.generate_forward_declarations(code_out, module)

    wrapper_number = 0

    ## test return type handlers of reverse wrappers
    for return_type, return_handler in typehandlers.base.return_type_matcher.items():
        if os.name == "nt":
            if stdint_rx.search(return_type):
                continue  # win32 does not support the u?int\d+_t types (defined in <stdint.h>)
        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, [])
                wrapper_number += 1
                try:
                    wrapper.generate(code_out, "_test_wrapper_number_%i" % (wrapper_number,), ["static"])
                except NotImplementedError:
                    print >> sys.stderr, (
                        "ReverseWrapper %s(void) (caller_owns_return=%r)"
                        " could not be generated: not implemented" % (retval.ctype, caller_owns_return)
                    )
                print
        else:
            retval = return_handler(return_type)
            try:
                wrapper = MyReverseWrapper(retval, [])
            except NotSupportedError:
                continue
            wrapper_number += 1
            try:
                wrapper.generate(code_out, "_test_wrapper_number_%i" % (wrapper_number,), ["static"])
            except NotImplementedError:
                print >> sys.stderr, (
                    "ReverseWrapper %s(void) could not be generated: not implemented" % (retval.ctype,)
                )
            print

    ## test parameter type handlers of reverse wrappers
    for param_type, param_handler in typehandlers.base.param_type_matcher.items():
        if os.name == "nt":
            if stdint_rx.search(param_type):
                continue  # win32 does not support the u?int\d+_t types (defined in <stdint.h>)
        for direction in param_handler.DIRECTIONS:
            if direction == (Parameter.DIRECTION_IN):
                param_name = "param"
            elif direction == (Parameter.DIRECTION_IN | Parameter.DIRECTION_OUT):
                param_name = "param_inout"
            elif direction == (Parameter.DIRECTION_OUT):
                param_name = "param_out"
            param = param_handler(param_type, param_name, direction)

            if "const" in param.ctype and direction & Parameter.DIRECTION_OUT:
                continue

            wrapper = MyReverseWrapper(ReturnValue.new("void"), [param])
            wrapper_number += 1
            try:
                wrapper.generate(code_out, "_test_wrapper_number_%i" % (wrapper_number,), ["static"])
            except NotImplementedError:
                print >> sys.stderr, ("ReverseWrapper void(%s) could not be generated: not implemented" % (param.ctype))
            print

    ## test generic forward wrappers, and module

    for return_type, return_handler in typehandlers.base.return_type_matcher.items():
        if os.name == "nt":
            if stdint_rx.search(return_type):
                continue  # win32 does not support the u?int\d+_t types (defined in <stdint.h>)
        wrapper_number += 1
        function_name = "foo_function_%i" % (wrapper_number,)
        ## declare a fake prototype
        print "%s %s(void);" % (return_type, function_name)
        print

        if issubclass(return_handler, (cppclass.CppClassPtrReturnValue, typehandlers.pyobjecttype.PyObjectReturnValue)):
            retval = return_handler(return_type, caller_owns_return=True)
        else:
            retval = return_handler(return_type)

        module.add_function(function_name, retval, [])

    for param_type, param_handler in typehandlers.base.param_type_matcher.items():
        if os.name == "nt":
            if stdint_rx.search(param_type):
                continue  # win32 does not support the u?int\d+_t types (defined in <stdint.h>)

        for is_const in [True, False]:
            for direction in param_handler.DIRECTIONS:
                if direction == (Parameter.DIRECTION_IN):
                    param_name = "param"
                elif direction == (Parameter.DIRECTION_IN | Parameter.DIRECTION_OUT):
                    param_name = "param_inout"
                elif direction == (Parameter.DIRECTION_OUT):
                    param_name = "param_out"

                if is_const and direction & Parameter.DIRECTION_OUT:
                    continue  # const and output parameter makes no sense

                if is_const:
                    if "&" in param_type:  # const references not allowed
                        continue
                    param_type_with_const = "const %s" % (param_type,)
                else:
                    param_type_with_const = param_type

                if issubclass(param_handler, (cppclass.CppClassPtrParameter, typehandlers.pyobjecttype.PyObjectParam)):
                    for transfer_ownership in True, False:
                        name = param_name + (transfer_ownership and "_transfer" or "_notransfer")
                        try:
                            param = param_handler(param_type, name, transfer_ownership=transfer_ownership)
                        except TypeError:
                            print >> sys.stderr, "ERROR -----> param_handler(param_type=%r, " "name=%r, transfer_ownership=%r, is_const=%r)" % (
                                param_type,
                                name,
                                transfer_ownership,
                                is_const,
                            )
                        wrapper_number += 1
                        function_name = "foo_function_%i" % (wrapper_number,)
                        ## declare a fake prototype
                        print "void %s(%s %s);" % (function_name, param_type_with_const, name)
                        print
                        module.add_function(function_name, ReturnValue.new("void"), [param])
                else:
                    param = param_handler(param_type, param_name, direction)
                    wrapper_number += 1
                    function_name = "foo_function_%i" % (wrapper_number,)
                    ## declare a fake prototype
                    print "void %s(%s);" % (function_name, param_type_with_const)
                    print
                    module.add_function(function_name, ReturnValue.new("void"), [param])

    module.generate(code_out)