generate code for Boost.NumPy[1] to accelerate c 1D array handling

Upstream: https://sourceforge.net/p/pygccxml/patches/2/

Index: pyplusplus/code_creators/__init__.py
===================================================================
--- pyplusplus/code_creators/__init__.py.orig
+++ pyplusplus/code_creators/__init__.py
@@ -110,6 +110,8 @@ from member_variable import bit_field_t
 from member_variable import bit_field_wrapper_t
 from member_variable import array_mv_t
 from member_variable import array_mv_wrapper_t
+from member_variable import array_numpy_t
+from member_variable import array_numpy_wrapper_t
 from member_variable import mem_var_ref_t
 from member_variable import mem_var_ref_wrapper_t
 from member_variable import member_variable_addressof_t
Index: pyplusplus/code_creators/code_creator.py
===================================================================
--- pyplusplus/code_creators/code_creator.py.orig
+++ pyplusplus/code_creators/code_creator.py
@@ -126,6 +126,7 @@ class code_creator_t(object):
         files = []
         if self.code_generator == self.CODE_GENERATOR_TYPES.BOOST_PYTHON:
             files.append( "boost/python.hpp" )
+            files.append( "boost/numpy.hpp" )
             files.append( code_repository.named_tuple.file_name )
         else:
             files.append( code_repository.ctypes_utils.file_name )
Index: pyplusplus/code_creators/member_variable.py
===================================================================
--- pyplusplus/code_creators/member_variable.py.orig
+++ pyplusplus/code_creators/member_variable.py
@@ -507,7 +507,95 @@ class array_mv_wrapper_t( code_creator.c
     def _get_system_files_impl( self ):
         return [code_repository.array_1.file_name]
 
+class array_numpy_t( member_variable_base_t ):
+    """
+    Creates boost.python code that exposes array member variable via boost.numpy.
+    """
+    def __init__(self, variable, wrapper ):
+        member_variable_base_t.__init__( self, variable=variable, wrapper=wrapper )
+        self.works_on_instance = False
+
+    def _create_body( self ):
+        answer = []
+        doc = ''
+        if self.declaration.type_qualifiers.has_static:
+            answer.append( self.parent.class_var_name + '.add_static_property' )
+        else:
+            if self.documentation:
+                doc = self.documentation
+            answer.append( self.parent.class_var_name + '.add_property' )
+        answer.append('( "%s", &%s );' % (self.declaration.name, self.wrapper.wrapper_creator_full_name ))
+        if doc:
+            answer.append( os.linesep )
+            answer.append( self.PARAM_SEPARATOR )
+            answer.append( doc )
+        return ''.join( answer )
+
+    def _create_impl( self ):
+        answer = []
+        answer.append( '{ //%s, type=%s' % ( self.declaration, self.declaration.type ) )
+        answer.append( os.linesep )
+        answer.append( self.indent( self._create_body() ) )
+        answer.append( os.linesep )
+        answer.append( '}' )
+        return ''.join( answer )
+
+    def _get_system_files_impl( self ):
+        return []
 
+class array_numpy_wrapper_t( code_creator.code_creator_t
+                          , declaration_based.declaration_based_t ):
+    """registers array class"""
+    def __init__(self, variable ):
+        code_creator.code_creator_t.__init__( self )
+        declaration_based.declaration_based_t.__init__( self, declaration=variable)
+        self.py_class_type = declarations.reference_t(declarations.const_t(declarations.dummy_type_t( "bp::object" )))
+
+    @property
+    def wrapped_class_type( self ):
+        wrapped_cls_type = declarations.declarated_t( self.declaration.parent )
+        if declarations.is_const( self.declaration.type ):
+            wrapped_cls_type = declarations.const_t( wrapped_cls_type )
+        return declarations.reference_t( wrapped_cls_type )
+            
+    @property
+    def wrapper_creator_name(self):
+        return '_'.join( ['pyplusplus', self.declaration.name, 'wrapper'] )
+
+    @property
+    def wrapper_creator_full_name(self):
+        return '::'.join( [self.parent.full_name, self.wrapper_creator_name] )
+
+    def _create_impl( self ):        
+        if self.declaration.type_qualifiers.has_static:
+            tmpl = [ "static %(wrapper_type)s %(wrapper_creator_name)s( ){" ]
+            tmpl.append( self.indent( "return bn::from_data( %(parent_class_type)s::%(mem_var_ref)s," ) )
+        else:
+            tmpl = [ "static %(wrapper_type)s %(wrapper_creator_name)s( %(py_class_type)s inst ){" ]
+            tmpl.append( self.indent( "return bn::from_data(bp::extract< %(wrapped_class_type)s >(inst)().%(mem_var_ref)s," ) )
+        owner = "bp::object()"
+
+        tmpl.append( self.indent(self.indent("bn::dtype::get_builtin< %(item_type)s >(), bp::make_tuple(%(array_size)s),")) )
+        tmpl.append( self.indent(self.indent("bp::make_tuple(sizeof(%(item_type)s)), %(owner)s);")) )
+        tmpl.append( "}" )
+        
+        tmpl = os.linesep.join( tmpl )
+        
+        return tmpl % {
+                'wrapper_type' : "bn::ndarray"
+              , 'parent_class_type' : self.parent.declaration.partial_decl_string
+              , 'wrapper_creator_name' : self.wrapper_creator_name
+              , 'wrapped_class_type' : self.wrapped_class_type.decl_string
+              , 'mem_var_ref' : self.declaration.name
+              , 'py_class_type' : self.py_class_type.decl_string
+              , 'item_type' : declarations.array_item_type( self.declaration.type ).decl_string
+              , 'array_size': declarations.array_size( self.declaration.type )
+              , 'owner': owner
+            }
+
+    def _get_system_files_impl( self ):
+        return []
+        
 class mem_var_ref_t( member_variable_base_t ):
     """
     creates get/set accessors for class member variable, that has type reference.
Index: pyplusplus/code_creators/module_body.py
===================================================================
--- pyplusplus/code_creators/module_body.py.orig
+++ pyplusplus/code_creators/module_body.py
@@ -18,6 +18,7 @@ class module_body_t(compound.compound_t)
     def _create_impl(self):
         result = []
         result.append( "BOOST_PYTHON_MODULE(%s){" % self.name )
+        result.append( "bn::initialize();" )
         result.append( compound.compound_t.create_internal_code( self.creators ) )
         result.append( "}" )
         return os.linesep.join( result )
Index: pyplusplus/creators_factory/bpcreator.py
===================================================================
--- pyplusplus/creators_factory/bpcreator.py.orig
+++ pyplusplus/creators_factory/bpcreator.py
@@ -76,10 +76,14 @@ class bpcreator_t( declarations.decl_vis
         global_ns = declarations.get_global_namespace(decls)
 
         self.__extmodule = code_creators.bpmodule_t( global_ns )
-        if boost_python_ns_name:
-            bp_ns_alias = code_creators.namespace_alias_t( alias=boost_python_ns_name
-                                                           , full_namespace_name='::boost::python' )
-            self.__extmodule.adopt_creator( bp_ns_alias )
+
+        # alias of boost::numpy is hard-coded here, as it  will be merged into boost::python.
+        for ns_name, full_ns_name in {boost_python_ns_name: '::boost::python'
+                                    , 'bn': '::boost::numpy'}.iteritems():
+            if ns_name:
+                ns_alias = code_creators.namespace_alias_t( alias=ns_name
+                                                          , full_namespace_name=full_ns_name )
+                self.__extmodule.adopt_creator( ns_alias )
 
         self.__module_body = code_creators.module_body_t( name=module_name )
 
@@ -723,8 +727,12 @@ class bpcreator_t( declarations.decl_vis
                 wrapper = code_creators.bit_field_wrapper_t( variable=self.curr_decl )
                 maker = code_creators.bit_field_t( variable=self.curr_decl, wrapper=wrapper )
             elif declarations.is_array( self.curr_decl.type ):
-                wrapper = code_creators.array_mv_wrapper_t( variable=self.curr_decl )
-                maker = code_creators.array_mv_t( variable=self.curr_decl, wrapper=wrapper )
+                if declarations.is_arithmetic(declarations.array_item_type( self.curr_decl.type )):
+                    wrapper = code_creators.array_numpy_wrapper_t( variable=self.curr_decl )
+                    maker = code_creators.array_numpy_t( variable=self.curr_decl, wrapper=wrapper )
+                else:
+                    wrapper = code_creators.array_mv_wrapper_t( variable=self.curr_decl )
+                    maker = code_creators.array_mv_t( variable=self.curr_decl, wrapper=wrapper )
             elif declarations.is_pointer( self.curr_decl.type ):
                 wrapper = code_creators.member_variable_wrapper_t( variable=self.curr_decl )
                 maker = code_creators.member_variable_t( variable=self.curr_decl, wrapper=wrapper )