diff --git a/autowrap/CodeGenerator.py b/autowrap/CodeGenerator.py index 5b2059a9..f67e48bd 100644 --- a/autowrap/CodeGenerator.py +++ b/autowrap/CodeGenerator.py @@ -1621,6 +1621,7 @@ def create_default_cimports(self): |from libcpp.vector cimport vector as libcpp_vector |from libcpp.pair cimport pair as libcpp_pair |from libcpp.map cimport map as libcpp_map + |from libcpp.unordered_map cimport unordered_map as libcpp_unordered_map |from libcpp cimport bool |from libc.string cimport const_char |from cython.operator cimport dereference as deref, diff --git a/autowrap/ConversionProvider.py b/autowrap/ConversionProvider.py index a0f303b4..0bdb8598 100644 --- a/autowrap/ConversionProvider.py +++ b/autowrap/ConversionProvider.py @@ -1023,6 +1023,289 @@ def output_conversion(self, cpp_type, input_cpp_var, output_py_var): """, locals()) return code +class StdUnorderedMapConverter(TypeConverterBase): + + def get_base_types(self): + return "libcpp_unordered_map", + + def matches(self, cpp_type): + return True + + def matching_python_type(self, cpp_type): + return "dict" + + def matching_python_type_full(self, cpp_type): + tt_key, tt_value = cpp_type.template_args + inner_conv_1 = self.converters.get(tt_key) + inner_conv_2 = self.converters.get(tt_value) + # We use typing.Dict to be backwards compatible with py <= 3.8 + return "Dict[%s, %s]" % (inner_conv_1.matching_python_type_full(tt_key), + inner_conv_2.matching_python_type_full(tt_value)) + + def type_check_expression(self, cpp_type, arg_var): + tt_key, tt_value = cpp_type.template_args + inner_conv_1 = self.converters.get(tt_key) + inner_conv_2 = self.converters.get(tt_value) + assert inner_conv_1 is not None, "arg type %s not supported" % tt_key + assert inner_conv_2 is not None, "arg type %s not supported" % tt_value + + inner_check_1 = inner_conv_1.type_check_expression(tt_key, "k") + inner_check_2 = inner_conv_2.type_check_expression(tt_value, "v") + + return Code().add(""" + |isinstance($arg_var, dict) + + and all($inner_check_1 for k in $arg_var.keys()) + + and all($inner_check_2 for v in $arg_var.values()) + """, locals()).render() + + def input_conversion(self, cpp_type, argument_var, arg_num): + tt_key, tt_value = cpp_type.template_args + temp_var = "v%d" % arg_num + + code = Code() + + cy_tt_key = self.converters.cython_type(tt_key) + cy_tt_value = self.converters.cython_type(tt_value) + + py_tt_key = tt_key + + value_conv_code = "" + value_conv_cleanup = "" + key_conv_code = "" + key_conv_cleanup = "" + + if cy_tt_value.is_enum: + value_conv = "<%s> value" % cy_tt_value + elif tt_value.base_type in self.converters.names_of_wrapper_classes: + value_conv = "deref((<%s>value).inst.get())" % tt_value.base_type + elif tt_value.template_args is not None and tt_value.base_type == "libcpp_vector": + # Special case: the value type is a std::vector< X >, maybe something we can convert? + + # code_top = """ + value_var = "value" + tt, = tt_value.template_args + vtemp_var = "svec%s" % arg_num + inner = self.converters.cython_type(tt) + + # Check whether the inner vector has any classes we need to wrap (we cannot do that) + contains_classes_to_wrap = tt.template_args is not None and \ + len(set(self.converters.names_of_wrapper_classes).intersection( + set(tt.all_occuring_base_types()))) > 0 + + if self.converters.cython_type(tt).is_enum: + # Case 1: We wrap a std::vector<> with an enum base type + raise Exception("Not Implemented") + 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 + raise Exception("Not Implemented") + elif tt.template_args is not None and tt.base_type == "shared_ptr" \ + and len(set(tt.template_args[0].all_occuring_base_types())) == 1: + # Case 3: We wrap a std::vector< shared_ptr > where X needs to be a type that is easy to wrap + raise Exception("Not Implemented") + elif tt.template_args is not None and tt.base_type != "libcpp_vector" and \ + len(set(self.converters.names_of_wrapper_classes).intersection( + set(tt.all_occuring_base_types()))) > 0: + # Only if the std::vector contains a class that we need to wrap somewhere, + # we cannot do it ... + raise Exception( + "Recursion in std::vector is not implemented for other STL methods and wrapped template arguments") + elif tt.template_args is not None and tt.base_type == "libcpp_vector" and contains_classes_to_wrap: + # Case 4: We wrap a std::vector<> with a base type that contains + # further nested std::vector<> inside + # -> deal with recursion + raise Exception("Not Implemented") + else: + # Case 5: We wrap a regular type + inner = self.converters.cython_type(tt) + # cython cares for conversion of stl containers with std types, + # but we need to add the definition to the top + code = Code().add(""" + |cdef libcpp_vector[$inner] $vtemp_var + """, locals()) + + value_conv_cleanup = Code().add("") + value_conv_code = Code().add("$vtemp_var = $value_var", locals()) + value_conv = "%s" % vtemp_var + if cpp_type.topmost_is_ref and not cpp_type.topmost_is_const: + cleanup_code = Code().add(""" + |$value_var[:] = $vtemp_var + """, locals()) + + elif tt_value in self.converters: + value_conv_code, value_conv, value_conv_cleanup = \ + self.converters.get(tt_value).input_conversion(tt_value, "value", 0) + else: + value_conv = "<%s> value" % cy_tt_value + + if cy_tt_key.is_enum: + key_conv = "<%s> key" % cy_tt_key + elif tt_key.base_type in self.converters.names_of_wrapper_classes: + key_conv = "deref(<%s *> (<%s> key).inst.get())" % (cy_tt_key, py_tt_key) + elif tt_key in self.converters: + key_conv_code, key_conv, key_conv_cleanup = \ + self.converters.get(tt_key).input_conversion(tt_key, "key", 0) + else: + key_conv = "<%s> key" % cy_tt_key + + code.add(""" + |cdef libcpp_unordered_map[$cy_tt_key, $cy_tt_value] * $temp_var = new + + libcpp_unordered_map[$cy_tt_key, $cy_tt_value]() + |for key, value in $argument_var.items(): + """, locals()) + + code.add(key_conv_code) + code.add(value_conv_code) + code.add(""" deref($temp_var)[ $key_conv ] = $value_conv + """, locals()) + code.add(key_conv_cleanup) + code.add(value_conv_cleanup) + + if cpp_type.is_ref and not cpp_type.is_const: + it = mangle("it_" + argument_var) + + key_conv = "<%s> deref(%s).first" % (cy_tt_key, it) + + ## add code for key that is wrapped + if tt_key.base_type in self.converters.names_of_wrapper_classes \ + and not tt_value.base_type in self.converters.names_of_wrapper_classes: + value_conv = "<%s> deref(%s).second" % (cy_tt_value, it) + cy_tt = tt_value.base_type + item = mangle("item_" + argument_var) + item_key = mangle("itemk_" + argument_var) + cleanup_code = Code().add(""" + |replace = dict() + |cdef libcpp_unordered_map[$cy_tt_key, $cy_tt_value].iterator $it = $temp_var.begin() + |cdef $py_tt_key $item_key + |while $it != $temp_var.end(): + | $item_key = $py_tt_key.__new__($py_tt_key) + | $item_key.inst = shared_ptr[$cy_tt_key](new $cy_tt_key((deref($it)).first)) + | replace[$item_key] = $value_conv + | inc($it) + |$argument_var.clear() + |$argument_var.update(replace) + |del $temp_var + """, locals()) + ## add code for value that is wrapped + elif not cy_tt_value.is_enum and tt_value.base_type in self.converters.names_of_wrapper_classes\ + and not tt_key.base_type in self.converters.names_of_wrapper_classes: + cy_tt = tt_value.base_type + item = mangle("item_" + argument_var) + cleanup_code = Code().add(""" + |replace = dict() + |cdef libcpp_unordered_map[$cy_tt_key, $cy_tt_value].iterator $it = $temp_var.begin() + |cdef $cy_tt $item + |while $it != $temp_var.end(): + | $item = $cy_tt.__new__($cy_tt) + | $item.inst = shared_ptr[$cy_tt_value](new $cy_tt_value((deref($it)).second)) + | replace[$key_conv] = $item + | inc($it) + |$argument_var.clear() + |$argument_var.update(replace) + |del $temp_var + """, locals()) + ## add code for value AND key that is wrapped + elif not cy_tt_value.is_enum and tt_value.base_type in self.converters.names_of_wrapper_classes\ + and tt_key.base_type in self.converters.names_of_wrapper_classes: + value_conv = "<%s> deref(%s).second" % (cy_tt_value, it) + cy_tt = tt_value.base_type + item_val = mangle("itemv_" + argument_var) + item_key = mangle("itemk_" + argument_var) + cleanup_code = Code().add(""" + |replace = dict() + |cdef libcpp_unordered_map[$cy_tt_key, $cy_tt_value].iterator $it = $temp_var.begin() + |cdef $py_tt_key $item_key + |cdef $cy_tt $item_val + |while $it != $temp_var.end(): + | $item_key = $py_tt_key.__new__($py_tt_key) + | $item_key.inst = shared_ptr[$cy_tt_key](new $cy_tt_key((deref($it)).first)) + | $item_val = $cy_tt.__new__($cy_tt) + | $item_val.inst = shared_ptr[$cy_tt_value](new $cy_tt_value((deref($it)).second)) + | replace[$item_key] = $item_val + | inc($it) + |$argument_var.clear() + |$argument_var.update(replace) + |del $temp_var + """, locals()) + else: + value_conv = "<%s> deref(%s).second" % (cy_tt_value, it) + cleanup_code = Code().add(""" + |replace = dict() + |cdef libcpp_unordered_map[$cy_tt_key, $cy_tt_value].iterator $it = $temp_var.begin() + |while $it != $temp_var.end(): + | replace[$key_conv] = $value_conv + | inc($it) + |$argument_var.clear() + |$argument_var.update(replace) + |del $temp_var + """, locals()) + else: + cleanup_code = "del %s" % temp_var + + return code, "deref(%s)" % temp_var, cleanup_code + + def call_method(self, res_type, cy_call_str): + return "_r = %s" % (cy_call_str) + + def output_conversion(self, cpp_type, input_cpp_var, output_py_var): + + assert not cpp_type.is_ptr + + tt_key, tt_value = cpp_type.template_args + cy_tt_key = self.converters.cython_type(tt_key) + cy_tt_value = self.converters.cython_type(tt_value) + py_tt_key = tt_key + + it = mangle("it_" + input_cpp_var) + + if (not cy_tt_value.is_enum and tt_value.base_type in self.converters.names_of_wrapper_classes) \ + and (not cy_tt_key.is_enum and tt_key.base_type in self.converters.names_of_wrapper_classes): + raise Exception("Converter can not handle wrapped classes as keys and values in unordered_map") + + elif not cy_tt_key.is_enum and tt_key.base_type in self.converters.names_of_wrapper_classes: + key_conv = "deref(<%s *> (<%s> key).inst.get())" % (cy_tt_key, py_tt_key) + else: + key_conv = "<%s>(deref(%s).first)" % (cy_tt_key, it) + + if not cy_tt_value.is_enum and tt_value.base_type in self.converters.names_of_wrapper_classes: + cy_tt = tt_value.base_type + item = mangle("item_" + output_py_var) + code = Code().add(""" + |$output_py_var = dict() + |cdef libcpp_unordered_map[$cy_tt_key, $cy_tt_value].iterator $it = $input_cpp_var.begin() + |cdef $cy_tt $item + |while $it != $input_cpp_var.end(): + | $item = $cy_tt.__new__($cy_tt) + | $item.inst = shared_ptr[$cy_tt_value](new $cy_tt_value((deref($it)).second)) + | $output_py_var[$key_conv] = $item + | inc($it) + """, locals()) + return code + elif not cy_tt_key.is_enum and tt_key.base_type in self.converters.names_of_wrapper_classes: + value_conv = "<%s>(deref(%s).second)" % (cy_tt_value, it) + item_key = mangle("itemk_" + output_py_var) + code = Code().add(""" + |$output_py_var = dict() + |cdef libcpp_unordered_map[$cy_tt_key, $cy_tt_value].iterator $it = $input_cpp_var.begin() + |cdef $py_tt_key $item_key + |while $it != $input_cpp_var.end(): + | #$output_py_var[$key_conv] = $value_conv + | $item_key = $py_tt_key.__new__($py_tt_key) + | $item_key.inst = shared_ptr[$cy_tt_key](new $cy_tt_key((deref($it)).first)) + | # $output_py_var[$key_conv] = $value_conv + | $output_py_var[$item_key] = $value_conv + | inc($it) + """, locals()) + return code + else: + value_conv = "<%s>(deref(%s).second)" % (cy_tt_value, it) + code = Code().add(""" + |$output_py_var = dict() + |cdef libcpp_unordered_map[$cy_tt_key, $cy_tt_value].iterator $it = $input_cpp_var.begin() + |while $it != $input_cpp_var.end(): + | $output_py_var[$key_conv] = $value_conv + | inc($it) + """, locals()) + return code class StdSetConverter(TypeConverterBase): @@ -1801,6 +2084,7 @@ def setup_converter_registry(classes_to_wrap, enums_to_wrap, instance_map): converters.register(StdVectorConverter()) converters.register(StdSetConverter()) converters.register(StdMapConverter()) + converters.register(StdUnorderedMapConverter()) converters.register(StdPairConverter()) converters.register(VoidConverter()) converters.register(SharedPtrConverter()) diff --git a/autowrap/Utils.py b/autowrap/Utils.py index dc65afc5..84225793 100644 --- a/autowrap/Utils.py +++ b/autowrap/Utils.py @@ -91,7 +91,7 @@ def compile_and_import(name, source_files, include_dirs=None, **kws): link_args = [] if sys.platform == "darwin": - compile_args += ["-stdlib=libc++","-std=c++11"] + compile_args += ["-stdlib=libc++", "-std=c++11"] link_args += ["-stdlib=libc++"] if sys.platform == "linux" or sys.platform == "linux2": diff --git a/tests/test_code_generator_libcpp.py b/tests/test_code_generator_libcpp.py index 4d633836..7f7bd07c 100644 --- a/tests/test_code_generator_libcpp.py +++ b/tests/test_code_generator_libcpp.py @@ -380,6 +380,52 @@ def test_libcpp(): assert i1.get() == 1 assert i2.get() == 4 + out = t.process41(1, 2.0) + assert list(out.items()) == [(1, 2.0)] + + out = t.process42(libcpp.EEE.A, 2) + assert list(out.items()) == [(libcpp.EEE.A, 2)] + + out = t.process43(libcpp.EEE.A, 3) + assert list(out.items()) == [(3, libcpp.EEE.A)] + + out = t.process44(12) + (k, v), = out.items() + assert k == 12 + assert v.gett() == 12 + + assert t.process45({42: 2.0, 12: 1.0}) == 2.0 + + assert t.process46({libcpp.EEE.A: 2.0, libcpp.EEE.B: 1.0}) == 2.0 + + assert t.process47({23: t, 12: t2}) == t.gett() + + dd = dict() + t.process48(dd) + assert len(dd) == 1 + assert list(dd.keys()) == [23] + assert list(dd.values())[0].gett() == 12 + + dd = dict() + t.process49(dd) + assert list(dd.items()) == [(23, 42.0)] + + d1 = dict() + t.process50(d1, {42: 11}) + assert d1.get(1) == 11 + + d1 = dict() + t.process501(d1, {b"42": [11, 6]}) + assert d1.get(1) == 11 + + d2 = dict() + t.process502(d2, {b"42": [ [11, 6], [2] , [8] ]}) + assert d2.get(1) == 11 + + d3 = dict() + t.process504(d3, {b"42": [ [11, 6], [2, 8] ]}) + assert d3.get(1) == 11 + # Testing unsafe call i1 = libcpp.ABS_Impl1(__createUnsafeObject__=True) i2 = libcpp.ABS_Impl2(__createUnsafeObject__=True) diff --git a/tests/test_code_generator_stllibcpp.py b/tests/test_code_generator_stllibcpp.py index 7e84222f..2753eeea 100644 --- a/tests/test_code_generator_stllibcpp.py +++ b/tests/test_code_generator_stllibcpp.py @@ -74,6 +74,15 @@ def test_stl_libcpp(): assert len(m1.map_) == 1 assert len(m2.map_) == 2 + u1 = libcpp_stl.UnorderedMapWrapper() + u1.un_map_ = {3 : 8.0} + u2 = libcpp_stl.UnorderedMapWrapper(u1) + u2.un_map_ = {3 : 8.0, 7 : 9.0} + + assert len(u1.un_map_) == 1 + assert len(u2.un_map_) == 2 + + # Test wrapping of operator[] vec_wrapper = libcpp_stl.IntVecWrapper() vec_wrapper.push_back(5) @@ -206,3 +215,63 @@ def test_stl_libcpp(): assert len(map_inp) == 1 assert list(map_inp.values())[0][0] == 6 + 10 assert list(map_inp.values())[0][1] == 2 + + # Part 9 + # Test std::unordered_map< Widget, int > + i1 = libcpp_stl.IntWrapper(1) + i2 = libcpp_stl.IntWrapper(2) + un_map_inp = {i2 : 5} + assert t.process_15_unordered_map(un_map_inp) == 2 + assert len(un_map_inp) == 1 + assert list(un_map_inp.values())[0] == 5 + 10 + + # res = t.process_16_unordered_map(5) + # assert len(res) == 1 + # assert list(res.keys())[0].i_ == 5 + # assert list(res.values())[0] == 5 + 10 + + # Part 10 + # Test std::unordered_map< int, Widget > + i1 = libcpp_stl.IntWrapper(1) + i2 = libcpp_stl.IntWrapper(2) + un_map_inp = { 5: i2 } + assert t.process_17_unordered_map(un_map_inp) == 5 + assert len(un_map_inp) == 1 + assert list(un_map_inp.values())[0].i_ == 2 + 10 + + res = t.process_18_unordered_map(5) + assert len(res) == 1 + assert list(res.values())[0].i_ == 5 + assert list(res.keys())[0] == 5 + 10 + + # Part 11 + # Test std::unordered_map< string, IntWrapper > + i1 = libcpp_stl.IntWrapper(1) + i2 = libcpp_stl.IntWrapper(2) + un_map_inp = { b"test" : i2 } + assert t.process_19_unordered_map(un_map_inp) == 2 + 10 + assert len(un_map_inp) == 1 + assert list(un_map_inp.values())[0].i_ == 2 + 10 + + # Part 12 + # Test std::unordered_map< Widget, vector > + i1 = libcpp_stl.IntWrapper(1) + i2 = libcpp_stl.IntWrapper(2) + un_map_inp = { i2 : [6, 2] } + assert t.process_20_unordered_map(un_map_inp) == 2 + assert len(un_map_inp) == 1 + assert list(un_map_inp.values())[0][0] == 6 + 10 + assert list(un_map_inp.values())[0][1] == 2 + + # Part 13 + # Test std::unordered_map< Widget, Widget2 > + vec_wrapper = libcpp_stl.IntVecWrapper() + vec_wrapper.push_back(6) + vec_wrapper.push_back(2) + i1 = libcpp_stl.IntWrapper(1) + i2 = libcpp_stl.IntWrapper(2) + un_map_inp = { i2 : vec_wrapper } + assert t.process_21_unordered_map(un_map_inp) == 2 + assert len(un_map_inp) == 1 + assert list(un_map_inp.values())[0][0] == 6 + 10 + assert list(un_map_inp.values())[0][1] == 2 diff --git a/tests/test_files/libcpp_stl_test.hpp b/tests/test_files/libcpp_stl_test.hpp index b97c3666..48512908 100644 --- a/tests/test_files/libcpp_stl_test.hpp +++ b/tests/test_files/libcpp_stl_test.hpp @@ -2,6 +2,8 @@ #include #include #include +#include +#include #include class IntWrapper { @@ -54,6 +56,18 @@ class MapWrapper { } }; +class UnorderedMapWrapper { + + public: + std::unordered_map un_map_; + + UnorderedMapWrapper() {} + UnorderedMapWrapper(const UnorderedMapWrapper& other) + { + un_map_ = other.un_map_; + } +}; + class LibCppSTLVector { std::vector m_list; @@ -207,4 +221,69 @@ class LibCppSTLTest { } return -1; } + int process_15_unordered_map(std::unordered_map& in) + { + if (!in.empty() ) + { + in.begin()->second += 10; + return in.begin()->first.i_; + } + return -1; + } + + // std::unordered_map process_16_unordered_map(int in_) + // { + // std::unordered_map res; + // IntWrapper wr(in_); + // res[wr] = in_ + 10; + // return res; + // } + + int process_17_unordered_map(std::unordered_map& in) + { + if (!in.empty() ) + { + in.begin()->second.i_ += 10; + return in.begin()->first; + } + return -1; + } + + std::unordered_map process_18_unordered_map(int in_) + { + std::unordered_map res; + IntWrapper wr(in_); + res[in_ + 10] = wr; + return res; + } + + int process_19_unordered_map(std::unordered_map& in) + { + if (!in.empty()) + { + in.begin()->second.i_ += 10; + return in.begin()->second.i_; + } + return -1; + } + + int process_20_unordered_map(std::unordered_map >& in) + { + if (!in.empty() && !in.begin()->second.empty()) + { + in.begin()->second[0] += 10; + return in.begin()->first.i_; + } + return -1; + } + + int process_21_unordered_map(std::unordered_map& in) + { + if (!in.empty() && !in.begin()->second.iv_.empty()) + { + in.begin()->second.iv_[0] += 10; + return in.begin()->first.i_; + } + return -1; + } }; diff --git a/tests/test_files/libcpp_stl_test.pxd b/tests/test_files/libcpp_stl_test.pxd index 934b0528..83249720 100644 --- a/tests/test_files/libcpp_stl_test.pxd +++ b/tests/test_files/libcpp_stl_test.pxd @@ -4,6 +4,7 @@ from libcpp.set cimport set as libcpp_set from libcpp.vector cimport vector as libcpp_vector from libcpp.pair cimport pair as libcpp_pair from libcpp.map cimport map as libcpp_map +from libcpp.unordered_map cimport unordered_map as libcpp_unordered_map from smart_ptr cimport shared_ptr cdef extern from "libcpp_stl_test.hpp": @@ -26,6 +27,11 @@ cdef extern from "libcpp_stl_test.hpp": MapWrapper() MapWrapper(MapWrapper&) + cdef cppclass UnorderedMapWrapper: + libcpp_unordered_map[int, double] un_map_ + UnorderedMapWrapper() + UnorderedMapWrapper(UnorderedMapWrapper&) + cdef cppclass LibCppSTLVector: LibCppSTLVector() @@ -58,3 +64,14 @@ cdef extern from "libcpp_stl_test.hpp": int process_13_map(libcpp_map[IntWrapper, libcpp_vector[int] ]& in_) int process_14_map(libcpp_map[IntWrapper, IntVecWrapper]& in_) + + int process_15_unordered_map(libcpp_unordered_map[IntWrapper, int] & in_) + # libcpp_unordered_map[IntWrapper, int] process_16_unordered_map(int in_) + + int process_17_unordered_map(libcpp_unordered_map[int, IntWrapper] & in_) + libcpp_unordered_map[int, IntWrapper] process_18_unordered_map(int in_) + + int process_19_unordered_map(libcpp_unordered_map[libcpp_string, IntWrapper ]& in_) + int process_20_unordered_map(libcpp_unordered_map[IntWrapper, libcpp_vector[int] ]& in_) + + int process_21_unordered_map(libcpp_unordered_map[IntWrapper, IntVecWrapper]& in_) diff --git a/tests/test_files/libcpp_test.hpp b/tests/test_files/libcpp_test.hpp index e1a3da32..60b0b361 100644 --- a/tests/test_files/libcpp_test.hpp +++ b/tests/test_files/libcpp_test.hpp @@ -2,6 +2,8 @@ #include #include #include +#include +#include #include @@ -397,4 +399,88 @@ class LibCppTest { { return in->get(); } + + std::unordered_map process41(int i, float f) + { + std::unordered_map un_map; + un_map[i] = f; + return un_map; + } + + std::unordered_map process42(EEE e, int i) + { + std::unordered_map un_map; + un_map[e] = i; + return un_map; + } + + std::unordered_map process43(EEE e, int i) + { + std::unordered_map un_map; + un_map[i] = e; + return un_map; + } + + std::unordered_map process44(int i) + { + std::unordered_map un_map; + un_map[i] = LibCppTest(i); + return un_map; + } + + float process45(std::unordered_map in) + { + return in[42]; + + } + float process46(std::unordered_map in) + { + return in[A]; + + } + + int process47(std::unordered_map in) + { + return in[23].get(); + } + + void process48(std::unordered_map & in) + { + LibCppTest v(12); + in[23] = v; + } + + void process49(std::unordered_map & in) + { + in[23] = 42.0; + } + + void process50(std::unordered_map & in, std::unordered_map & arg2) + { + in[1] = (float) arg2[42]; + } + + void process501(std::unordered_map & in, std::unordered_map > & arg2) + { + std::string test_str("42"); + in[1] = (float) arg2[test_str][0]; + } + + void process502(std::unordered_map & in, std::unordered_map > > & arg2) + { + std::string test_str("42"); + in[1] = (float) arg2[test_str][0][0]; + } + + void process503(std::unordered_map & in, std::unordered_map > > & arg2) + { + std::string test_str("42"); + in[1] = (float) arg2[test_str][0][0].i_; + } + + void process504(std::unordered_map & in, std::unordered_map > > & arg2) + { + std::string test_str("42"); + in[1] = (float) arg2[test_str][0].first; + } }; diff --git a/tests/test_files/libcpp_test.pxd b/tests/test_files/libcpp_test.pxd index 0a8eb8d1..e17258b7 100644 --- a/tests/test_files/libcpp_test.pxd +++ b/tests/test_files/libcpp_test.pxd @@ -4,7 +4,8 @@ from libcpp.set cimport set as libcpp_set from libcpp.vector cimport vector as libcpp_vector from libcpp cimport bool from libcpp.pair cimport pair as libcpp_pair -from libcpp.map cimport map as libcpp_map +from libcpp.map cimport map as libcpp_map +from libcpp.unordered_map cimport unordered_map as libcpp_unordered_map from smart_ptr cimport shared_ptr ctypedef unsigned int UInt @@ -133,3 +134,23 @@ cdef extern from "libcpp_test.hpp": # int process40(AbstractBaseClass* in_) int process40(ABS_Impl1* in_) int process40(ABS_Impl2* in_) + + libcpp_unordered_map[int, float] process41(int i, float f) + libcpp_unordered_map[EEE, int] process42(EEE e, int i) + libcpp_unordered_map[int, EEE] process43(EEE e, int i) + + libcpp_unordered_map[long int, LibCppTest] process44(int ii) + + float process45(libcpp_unordered_map[int, float] in_) + float process46(libcpp_unordered_map[EEE, float] in_) + + int process47(libcpp_unordered_map[int, LibCppTest] in_) + + void process48(libcpp_unordered_map[int, LibCppTest] & in_) + void process49(libcpp_unordered_map[int, float] & in_) + + void process50(libcpp_unordered_map[int, float] & in_, libcpp_unordered_map[int,int] & arg2) + void process501(libcpp_unordered_map[int, float] & in_, libcpp_unordered_map[libcpp_string, libcpp_vector[int] ] & arg2) + void process502(libcpp_unordered_map[int, float] & in_, libcpp_unordered_map[libcpp_string, libcpp_vector[ libcpp_vector[int] ] ] & arg2) + # void process503(libcpp_unordered_map[int, float] & in_, libcpp_unordered_map[libcpp_string, libcpp_vector[ libcpp_vector[Int] ] ] & arg2) + void process504(libcpp_unordered_map[int, float] & in_, libcpp_unordered_map[libcpp_string, libcpp_vector[ libcpp_pair[int, int] ] ] & arg2) diff --git a/tests/test_full_library.py b/tests/test_full_library.py index 88005140..bf218d1e 100644 --- a/tests/test_full_library.py +++ b/tests/test_full_library.py @@ -96,9 +96,12 @@ def compile_and_import(names, source_files, include_dirs=None, extra_files=[], * link_args = [] if sys.platform == "darwin": - compile_args += ["-stdlib=libc++"] + compile_args += ["-stdlib=libc++", "-std=c++11"] link_args += ["-stdlib=libc++"] - + + if sys.platform == "linux" or sys.platform == "linux2": + compile_args += ["-std=c11"] + if sys.platform != "win32": compile_args += ["-Wno-unused-but-set-variable"]