diff --git a/autowrap/CodeGenerator.py b/autowrap/CodeGenerator.py index b16a4e4..04aa7d2 100644 --- a/autowrap/CodeGenerator.py +++ b/autowrap/CodeGenerator.py @@ -2041,6 +2041,7 @@ def create_default_cimports(self): code.add( """ |from libcpp.memory cimport shared_ptr + |from libcpp.utility cimport move """ ) if self.include_numpy: diff --git a/autowrap/ConversionProvider.py b/autowrap/ConversionProvider.py index 7d7f689..bdbb7aa 100644 --- a/autowrap/ConversionProvider.py +++ b/autowrap/ConversionProvider.py @@ -1082,7 +1082,12 @@ def input_conversion( else: cleanup_code = "del %s" % temp_var - return code, "deref(%s)" % temp_var, cleanup_code + # Use move() for by-value parameters to avoid copying large maps + if cpp_type.is_ref: + call_as = "deref(%s)" % temp_var + else: + call_as = "move(deref(%s))" % temp_var + return code, call_as, cleanup_code def call_method(self, res_type: CppType, cy_call_str: str, with_const: bool = True) -> str: return "_r = %s" % cy_call_str @@ -1251,7 +1256,12 @@ def input_conversion( ) else: cleanup_code = "del %s" % temp_var - return code, "deref(%s)" % temp_var, cleanup_code + # Use move() for by-value parameters to avoid copying large sets + if cpp_type.topmost_is_ref: + call_as = "deref(%s)" % temp_var + else: + call_as = "move(deref(%s))" % temp_var + return code, call_as, cleanup_code elif tt.base_type in self.converters.names_of_wrapper_classes: base_type = tt.base_type @@ -1293,7 +1303,12 @@ def input_conversion( else: cleanup_code = "del %s" % temp_var - return code, "deref(%s)" % temp_var, cleanup_code + # Use move() for by-value parameters to avoid copying large sets + if cpp_type.is_ref: + call_as = "deref(%s)" % temp_var + else: + call_as = "move(deref(%s))" % temp_var + return code, call_as, cleanup_code else: inner = self.converters.cython_type(tt) # cython cares for conversion of stl containers with std types: @@ -1726,7 +1741,12 @@ def input_conversion( ) else: cleanup_code = "del %s" % temp_var - return code, "deref(%s)" % temp_var, cleanup_code + # Use move() for by-value parameters to avoid copying large vectors + if cpp_type.topmost_is_ref: + call_as = "deref(%s)" % temp_var + else: + call_as = "move(deref(%s))" % temp_var + return code, call_as, cleanup_code elif tt.base_type in self.converters.names_of_wrapper_classes: # Case 2: We wrap a std::vector<> with a base type we need to wrap @@ -1752,8 +1772,11 @@ def input_conversion( if cpp_type.is_ptr: call_fragment = temp_var - else: + elif cpp_type.topmost_is_ref: call_fragment = "deref(%s)" % temp_var + else: + # Use move() for by-value parameters to avoid copying large vectors + call_fragment = "move(deref(%s))" % temp_var return code, call_fragment, cleanup_code @@ -1802,7 +1825,12 @@ def input_conversion( locals(), ) - return code, "%s" % temp_var, cleanup_code + # Use move() for by-value parameters to avoid copying large vectors + if cpp_type.topmost_is_ref: + call_as = "%s" % temp_var + else: + call_as = "move(%s)" % temp_var + return code, call_as, cleanup_code elif inner_contains_classes_to_wrap and tt.base_type != "libcpp_vector": # Only if the template argument which is neither a class-to-wrap nor a std::vector @@ -1857,7 +1885,12 @@ def input_conversion( "Error: For recursion in std::vector to work, we need a ConverterRegistry instance at self.cr" ) - return code, "deref(%s)" % temp_var, cleanup_code + # Use move() for by-value parameters to avoid copying large vectors + if cpp_type.topmost_is_ref: + call_as = "deref(%s)" % temp_var + else: + call_as = "move(deref(%s))" % temp_var + return code, call_as, cleanup_code else: # Case 5: We wrap a regular type @@ -1879,7 +1912,12 @@ def input_conversion( locals(), ) - return code, "%s" % temp_var, cleanup_code + # Use move() for by-value parameters to avoid copying large vectors + if cpp_type.topmost_is_ref: + call_as = "%s" % temp_var + else: + call_as = "move(%s)" % temp_var + return code, call_as, cleanup_code def call_method(self, res_type: CppType, cy_call_str: str, with_const: bool = True) -> str: t = self.converters.cython_type(res_type) @@ -2354,7 +2392,12 @@ def input_conversion( else: cleanup_code = "del %s" % temp_var - return code, "deref(%s)" % temp_var, cleanup_code + # Use move() for by-value parameters to avoid copying large maps + if cpp_type.is_ref: + call_as = "deref(%s)" % temp_var + else: + call_as = "move(deref(%s))" % temp_var + return code, call_as, cleanup_code def call_method(self, res_type: CppType, cy_call_str: str, with_const: bool = True) -> str: return "_r = %s" % cy_call_str @@ -2543,7 +2586,12 @@ def input_conversion( ) else: cleanup_code = "del %s" % temp_var - return code, "deref(%s)" % temp_var, cleanup_code + # Use move() for by-value parameters to avoid copying large sets + if cpp_type.topmost_is_ref: + call_as = "deref(%s)" % temp_var + else: + call_as = "move(deref(%s))" % temp_var + return code, call_as, cleanup_code elif tt.base_type in self.converters.names_of_wrapper_classes: base_type = tt.base_type @@ -2579,7 +2627,12 @@ def input_conversion( ) else: cleanup_code = "del %s" % temp_var - return code, "deref(%s)" % temp_var, cleanup_code + # Use move() for by-value parameters to avoid copying large sets + if cpp_type.is_ref: + call_as = "deref(%s)" % temp_var + else: + call_as = "move(deref(%s))" % temp_var + return code, call_as, cleanup_code else: # Primitive types - need explicit iteration item = "item%d" % arg_num @@ -2607,7 +2660,12 @@ def input_conversion( ) else: cleanup_code = "del %s" % temp_var - return code, "deref(%s)" % temp_var, cleanup_code + # Use move() for by-value parameters to avoid copying large sets + if cpp_type.is_ref: + call_as = "deref(%s)" % temp_var + else: + call_as = "move(deref(%s))" % temp_var + return code, call_as, cleanup_code def call_method(self, res_type: CppType, cy_call_str: str, with_const: bool = True) -> str: return "_r = %s" % cy_call_str @@ -2745,7 +2803,12 @@ def input_conversion( ) else: cleanup_code = "del %s" % temp_var - return code, "deref(%s)" % temp_var, cleanup_code + # Use move() for by-value parameters to avoid copying large deques + if cpp_type.topmost_is_ref: + call_as = "deref(%s)" % temp_var + else: + call_as = "move(deref(%s))" % temp_var + return code, call_as, cleanup_code elif tt.base_type in self.converters.names_of_wrapper_classes: base_type = tt.base_type @@ -2762,7 +2825,12 @@ def input_conversion( locals(), ) cleanup_code = "del %s" % temp_var - return code, "deref(%s)" % temp_var, cleanup_code + # Use move() for by-value parameters to avoid copying large deques + if cpp_type.is_ref: + call_as = "deref(%s)" % temp_var + else: + call_as = "move(deref(%s))" % temp_var + return code, call_as, cleanup_code else: # Primitive types - need explicit iteration item = "item%d" % arg_num @@ -2913,7 +2981,12 @@ def input_conversion( ) else: cleanup_code = "del %s" % temp_var - return code, "deref(%s)" % temp_var, cleanup_code + # Use move() for by-value parameters to avoid copying large lists + if cpp_type.topmost_is_ref: + call_as = "deref(%s)" % temp_var + else: + call_as = "move(deref(%s))" % temp_var + return code, call_as, cleanup_code elif tt.base_type in self.converters.names_of_wrapper_classes: base_type = tt.base_type @@ -2930,7 +3003,12 @@ def input_conversion( locals(), ) cleanup_code = "del %s" % temp_var - return code, "deref(%s)" % temp_var, cleanup_code + # Use move() for by-value parameters to avoid copying large lists + if cpp_type.is_ref: + call_as = "deref(%s)" % temp_var + else: + call_as = "move(deref(%s))" % temp_var + return code, call_as, cleanup_code else: code = Code().add( """