From 5af2978f77cad0eec048ba1ea09b07e8ad7abbfa Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Thu, 10 Jun 2010 01:13:31 +0000 Subject: [PATCH] Add support for the Go programming language. git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@12108 626c5289-ae23-0410-ae9c-e8d60b6d4f22 --- Doc/Manual/Go.html | 463 ++ Doc/Manual/SWIG.html | 1 + Doc/Manual/Sections.html | 1 + Doc/Manual/chapters | 1 + Examples/Makefile.in | 71 + Examples/go/callback/Makefile | 18 + Examples/go/callback/example.cxx | 4 + Examples/go/callback/example.go | 188 + Examples/go/callback/example.h | 23 + Examples/go/callback/example.i | 13 + Examples/go/callback/index.html | 81 + Examples/go/callback/runme.go | 41 + Examples/go/check.list | 13 + Examples/go/class/Makefile | 16 + Examples/go/class/example.cxx | 28 + Examples/go/class/example.go | 284 + Examples/go/class/example.h | 39 + Examples/go/class/example.i | 10 + Examples/go/class/index.html | 203 + Examples/go/class/runme.go | 63 + Examples/go/constants/Makefile | 16 + Examples/go/constants/example.go | 44 + Examples/go/constants/example.i | 25 + Examples/go/constants/index.html | 55 + Examples/go/constants/runme.go | 18 + Examples/go/enum/Makefile | 18 + Examples/go/enum/example.cxx | 37 + Examples/go/enum/example.go | 93 + Examples/go/enum/example.h | 13 + Examples/go/enum/example.i | 11 + Examples/go/enum/index.html | 42 + Examples/go/enum/runme.go | 32 + Examples/go/extend/Makefile | 18 + Examples/go/extend/example.cxx | 4 + Examples/go/extend/example.go | 397 ++ Examples/go/extend/example.h | 56 + Examples/go/extend/example.i | 15 + Examples/go/extend/index.html | 27 + Examples/go/extend/runme.go | 77 + Examples/go/funcptr/Makefile | 18 + Examples/go/funcptr/example.c | 19 + Examples/go/funcptr/example.go | 54 + Examples/go/funcptr/example.h | 9 + Examples/go/funcptr/example.i | 16 + Examples/go/funcptr/index.html | 89 + Examples/go/funcptr/runme.go | 25 + Examples/go/index.html | 89 + Examples/go/multimap/Makefile | 18 + Examples/go/multimap/example.c | 53 + Examples/go/multimap/example.go | 55 + Examples/go/multimap/example.i | 110 + Examples/go/multimap/runme.go | 26 + Examples/go/pointer/Makefile | 18 + Examples/go/pointer/example.c | 16 + Examples/go/pointer/example.go | 68 + Examples/go/pointer/example.i | 30 + Examples/go/pointer/index.html | 143 + Examples/go/pointer/runme.go | 47 + Examples/go/reference/Makefile | 18 + Examples/go/reference/example.cxx | 46 + Examples/go/reference/example.go | 126 + Examples/go/reference/example.h | 26 + Examples/go/reference/example.i | 42 + Examples/go/reference/index.html | 143 + Examples/go/reference/runme.go | 71 + Examples/go/simple/Makefile | 15 + Examples/go/simple/example.c | 18 + Examples/go/simple/example.go | 48 + Examples/go/simple/example.i | 7 + Examples/go/simple/index.html | 126 + Examples/go/simple/runme.go | 25 + Examples/go/template/Makefile | 18 + Examples/go/template/example.go | 150 + Examples/go/template/example.h | 32 + Examples/go/template/example.i | 17 + Examples/go/template/index.html | 113 + Examples/go/template/runme.go | 43 + Examples/go/variables/Makefile | 18 + Examples/go/variables/example.c | 91 + Examples/go/variables/example.go | 198 + Examples/go/variables/example.h | 6 + Examples/go/variables/example.i | 49 + Examples/go/variables/index.html | 87 + Examples/go/variables/runme.go | 67 + Examples/test-suite/dynamic_cast.i | 14 +- Examples/test-suite/go/Makefile.in | 110 + .../test-suite/go/abstract_access_runme.go | 10 + .../test-suite/go/abstract_typedef2_runme.go | 7 + .../test-suite/go/abstract_typedef_runme.go | 11 + .../test-suite/go/abstract_virtual_runme.go | 8 + Examples/test-suite/go/array_member_runme.go | 26 + Examples/test-suite/go/arrays_global_runme.go | 22 + Examples/test-suite/go/class_ignore_runme.go | 10 + .../test-suite/go/class_scope_weird_runme.go | 11 + .../test-suite/go/compactdefaultargs_runme.go | 29 + Examples/test-suite/go/constover_runme.go | 50 + .../test-suite/go/constructor_copy_runme.go | 34 + Examples/test-suite/go/contract_runme.go | 208 + Examples/test-suite/go/cpp_enum_runme.go | 27 + Examples/test-suite/go/cpp_namespace_runme.go | 57 + Examples/test-suite/go/cpp_static_runme.go | 13 + Examples/test-suite/go/default_args_runme.go | 26 + .../go/default_constructor_runme.go | 35 + .../test-suite/go/director_abstract_runme.go | 62 + .../test-suite/go/director_basic_runme.go | 115 + .../test-suite/go/director_classic_runme.go | 135 + .../test-suite/go/director_default_runme.go | 11 + .../test-suite/go/director_detect_runme.go | 46 + Examples/test-suite/go/director_enum_runme.go | 17 + .../test-suite/go/director_exception_runme.go | 95 + .../test-suite/go/director_extend_runme.go | 18 + .../test-suite/go/director_finalizer_runme.go | 37 + Examples/test-suite/go/director_frob_runme.go | 12 + .../test-suite/go/director_nested_runme.go | 79 + .../test-suite/go/director_profile_runme.go | 49 + .../test-suite/go/director_protected_runme.go | 48 + .../test-suite/go/director_string_runme.go | 39 + .../test-suite/go/director_thread_runme.go | 28 + .../test-suite/go/director_unroll_runme.go | 21 + Examples/test-suite/go/disown_runme.go | 10 + Examples/test-suite/go/dynamic_cast_runme.go | 16 + Examples/test-suite/go/empty_runme.go | 6 + Examples/test-suite/go/enum_template_runme.go | 11 + Examples/test-suite/go/enums_runme.go | 25 + .../test-suite/go/exception_order_runme.go | 58 + .../test-suite/go/extend_placement_runme.go | 47 + .../test-suite/go/extend_template_ns_runme.go | 14 + .../test-suite/go/extend_template_runme.go | 14 + .../test-suite/go/extend_variable_runme.go | 9 + Examples/test-suite/go/extern_c_runme.go | 7 + Examples/test-suite/go/friends_runme.go | 50 + Examples/test-suite/go/fvirtual_runme.go | 13 + Examples/test-suite/go/global_ns_arg_runme.go | 8 + Examples/test-suite/go/grouping_runme.go | 19 + .../test-suite/go/import_nomodule_runme.go | 12 + Examples/test-suite/go/imports_runme.go | 17 + Examples/test-suite/go/inctest_runme.go | 18 + .../test-suite/go/inherit_missing_runme.go | 26 + Examples/test-suite/go/input_runme.go | 14 + .../test-suite/go/keyword_rename_runme.go | 8 + Examples/test-suite/go/li_attribute_runme.go | 90 + Examples/test-suite/go/li_carrays_runme.go | 14 + Examples/test-suite/go/li_cdata_runme.go | 13 + Examples/test-suite/go/li_cmalloc_runme.go | 25 + Examples/test-suite/go/li_cpointer_runme.go | 14 + Examples/test-suite/go/li_std_map_runme.go | 30 + .../test-suite/go/member_pointer_runme.go | 49 + .../test-suite/go/memberin_extend_c_runme.go | 11 + Examples/test-suite/go/minherit_runme.go | 82 + Examples/test-suite/go/mod_runme.go | 10 + Examples/test-suite/go/multi_import_runme.go | 29 + .../test-suite/go/namespace_class_runme.go | 19 + .../test-suite/go/namespace_typemap_runme.go | 116 + .../go/namespace_virtual_method_runme.go | 7 + Examples/test-suite/go/naturalvar_runme.go | 17 + .../test-suite/go/nested_workaround_runme.go | 19 + .../go/overload_complicated_runme.go | 62 + Examples/test-suite/go/overload_copy_runme.go | 8 + .../test-suite/go/overload_extend_runme.go | 22 + .../test-suite/go/overload_extendc_runme.go | 33 + .../test-suite/go/overload_rename_runme.go | 10 + .../test-suite/go/overload_simple_runme.go | 125 + .../test-suite/go/overload_subtype_runme.go | 16 + .../go/overload_template_fast_runme.go | 187 + .../test-suite/go/overload_template_runme.go | 188 + Examples/test-suite/go/preproc_runme.go | 21 + Examples/test-suite/go/primitive_ref_runme.go | 57 + Examples/test-suite/go/profiletest_runme.go | 38 + Examples/test-suite/go/refcount_runme.go | 32 + .../go/reference_global_vars_runme.go | 98 + Examples/test-suite/go/rename_scope_runme.go | 18 + .../go/rename_strip_encoder_runme.go | 9 + Examples/test-suite/go/ret_by_value_runme.go | 14 + .../test-suite/go/return_const_value_runme.go | 15 + .../go/smart_pointer_extend_runme.go | 40 + .../go/smart_pointer_member_runme.go | 30 + .../go/smart_pointer_multi_runme.go | 20 + .../go/smart_pointer_multi_typedef_runme.go | 20 + .../go/smart_pointer_overload_runme.go | 28 + .../go/smart_pointer_rename_runme.go | 20 + .../go/smart_pointer_simple_runme.go | 19 + .../smart_pointer_templatevariables_runme.go | 22 + .../go/smart_pointer_typedef_runme.go | 19 + Examples/test-suite/go/sneaky1_runme.go | 10 + .../go/special_variable_macros_runme.go | 25 + .../go/static_const_member_2_runme.go | 18 + .../go/struct_initialization_runme.go | 29 + Examples/test-suite/go/struct_rename_runme.go | 7 + Examples/test-suite/go/struct_value_runme.go | 17 + .../go/template_default_arg_runme.go | 107 + .../test-suite/go/template_extend1_runme.go | 16 + .../test-suite/go/template_extend2_runme.go | 16 + .../test-suite/go/template_inherit_runme.go | 72 + Examples/test-suite/go/template_ns4_runme.go | 10 + Examples/test-suite/go/template_ns_runme.go | 26 + .../test-suite/go/template_opaque_runme.go | 9 + .../test-suite/go/template_ref_type_runme.go | 9 + .../test-suite/go/template_rename_runme.go | 16 + .../test-suite/go/template_static_runme.go | 7 + .../go/template_tbase_template_runme.go | 10 + .../go/template_type_namespace_runme.go | 8 + .../go/template_typedef_cplx3_runme.go | 29 + .../go/template_typedef_cplx4_runme.go | 29 + .../go/template_typedef_import_runme.go | 30 + .../test-suite/go/threads_exception_runme.go | 66 + Examples/test-suite/go/typedef_class_runme.go | 11 + .../test-suite/go/typedef_inherit_runme.go | 31 + Examples/test-suite/go/typedef_scope_runme.go | 16 + .../test-suite/go/typemap_namespace_runme.go | 13 + .../test-suite/go/typemap_ns_using_runme.go | 9 + .../go/typemap_out_optimal_runme.go | 8 + Examples/test-suite/go/typename_runme.go | 13 + Examples/test-suite/go/unions_runme.go | 51 + Examples/test-suite/go/using1_runme.go | 9 + Examples/test-suite/go/using2_runme.go | 9 + .../test-suite/go/using_composition_runme.go | 44 + Examples/test-suite/go/using_extend_runme.go | 30 + Examples/test-suite/go/using_inherit_runme.go | 59 + Examples/test-suite/go/using_private_runme.go | 20 + .../test-suite/go/using_protected_runme.go | 12 + Examples/test-suite/go/varargs_runme.go | 26 + .../test-suite/go/virtual_derivation_runme.go | 12 + Examples/test-suite/go/virtual_poly_runme.go | 43 + Examples/test-suite/go/voidtest_runme.go | 26 + Examples/test-suite/go/wrapmacro_runme.go | 11 + Examples/test-suite/keyword_rename.i | 4 + Examples/test-suite/minherit.i | 2 +- Examples/test-suite/name_warnings.i | 2 + Examples/test-suite/namespace_typemap.i | 26 + Examples/test-suite/null_pointer.i | 2 + Examples/test-suite/overload_simple.i | 2 + Examples/test-suite/return_const_value.i | 9 +- Examples/test-suite/rname.i | 5 + Examples/test-suite/typemap_namespace.i | 5 +- Examples/test-suite/typemap_subst.i | 4 +- Examples/test-suite/union_parameter.i | 2 + Lib/go/cdata.i | 135 + Lib/go/exception.i | 7 + Lib/go/go.swg | 514 ++ Lib/go/gokw.swg | 31 + Lib/go/goruntime.swg | 208 + Lib/go/std_common.i | 4 + Lib/go/std_deque.i | 1 + Lib/go/std_except.i | 29 + Lib/go/std_map.i | 64 + Lib/go/std_pair.i | 34 + Lib/go/std_string.i | 55 + Lib/go/std_vector.i | 78 + Lib/go/stl.i | 9 + Lib/go/typemaps.i | 335 ++ Makefile.in | 17 +- Source/Makefile.am | 1 + Source/Modules/allegrocl.cxx | 2 + Source/Modules/go.cxx | 4824 +++++++++++++++++ Source/Modules/overload.cxx | 2 +- Source/Modules/r.cxx | 2 + Source/Modules/swigmain.cxx | 2 + Source/Modules/swigmod.h | 1 + configure.in | 36 + 259 files changed, 16159 insertions(+), 14 deletions(-) create mode 100644 Doc/Manual/Go.html create mode 100644 Examples/go/callback/Makefile create mode 100644 Examples/go/callback/example.cxx create mode 100644 Examples/go/callback/example.go create mode 100644 Examples/go/callback/example.h create mode 100644 Examples/go/callback/example.i create mode 100644 Examples/go/callback/index.html create mode 100644 Examples/go/callback/runme.go create mode 100644 Examples/go/check.list create mode 100644 Examples/go/class/Makefile create mode 100644 Examples/go/class/example.cxx create mode 100644 Examples/go/class/example.go create mode 100644 Examples/go/class/example.h create mode 100644 Examples/go/class/example.i create mode 100644 Examples/go/class/index.html create mode 100644 Examples/go/class/runme.go create mode 100644 Examples/go/constants/Makefile create mode 100644 Examples/go/constants/example.go create mode 100644 Examples/go/constants/example.i create mode 100644 Examples/go/constants/index.html create mode 100644 Examples/go/constants/runme.go create mode 100644 Examples/go/enum/Makefile create mode 100644 Examples/go/enum/example.cxx create mode 100644 Examples/go/enum/example.go create mode 100644 Examples/go/enum/example.h create mode 100644 Examples/go/enum/example.i create mode 100644 Examples/go/enum/index.html create mode 100644 Examples/go/enum/runme.go create mode 100644 Examples/go/extend/Makefile create mode 100644 Examples/go/extend/example.cxx create mode 100644 Examples/go/extend/example.go create mode 100644 Examples/go/extend/example.h create mode 100644 Examples/go/extend/example.i create mode 100644 Examples/go/extend/index.html create mode 100644 Examples/go/extend/runme.go create mode 100644 Examples/go/funcptr/Makefile create mode 100644 Examples/go/funcptr/example.c create mode 100644 Examples/go/funcptr/example.go create mode 100644 Examples/go/funcptr/example.h create mode 100644 Examples/go/funcptr/example.i create mode 100644 Examples/go/funcptr/index.html create mode 100644 Examples/go/funcptr/runme.go create mode 100644 Examples/go/index.html create mode 100644 Examples/go/multimap/Makefile create mode 100644 Examples/go/multimap/example.c create mode 100644 Examples/go/multimap/example.go create mode 100644 Examples/go/multimap/example.i create mode 100644 Examples/go/multimap/runme.go create mode 100644 Examples/go/pointer/Makefile create mode 100644 Examples/go/pointer/example.c create mode 100644 Examples/go/pointer/example.go create mode 100644 Examples/go/pointer/example.i create mode 100644 Examples/go/pointer/index.html create mode 100644 Examples/go/pointer/runme.go create mode 100644 Examples/go/reference/Makefile create mode 100644 Examples/go/reference/example.cxx create mode 100644 Examples/go/reference/example.go create mode 100644 Examples/go/reference/example.h create mode 100644 Examples/go/reference/example.i create mode 100644 Examples/go/reference/index.html create mode 100644 Examples/go/reference/runme.go create mode 100644 Examples/go/simple/Makefile create mode 100644 Examples/go/simple/example.c create mode 100644 Examples/go/simple/example.go create mode 100644 Examples/go/simple/example.i create mode 100644 Examples/go/simple/index.html create mode 100644 Examples/go/simple/runme.go create mode 100644 Examples/go/template/Makefile create mode 100644 Examples/go/template/example.go create mode 100644 Examples/go/template/example.h create mode 100644 Examples/go/template/example.i create mode 100644 Examples/go/template/index.html create mode 100644 Examples/go/template/runme.go create mode 100644 Examples/go/variables/Makefile create mode 100644 Examples/go/variables/example.c create mode 100644 Examples/go/variables/example.go create mode 100644 Examples/go/variables/example.h create mode 100644 Examples/go/variables/example.i create mode 100644 Examples/go/variables/index.html create mode 100644 Examples/go/variables/runme.go create mode 100644 Examples/test-suite/go/Makefile.in create mode 100644 Examples/test-suite/go/abstract_access_runme.go create mode 100644 Examples/test-suite/go/abstract_typedef2_runme.go create mode 100644 Examples/test-suite/go/abstract_typedef_runme.go create mode 100644 Examples/test-suite/go/abstract_virtual_runme.go create mode 100644 Examples/test-suite/go/array_member_runme.go create mode 100644 Examples/test-suite/go/arrays_global_runme.go create mode 100644 Examples/test-suite/go/class_ignore_runme.go create mode 100644 Examples/test-suite/go/class_scope_weird_runme.go create mode 100644 Examples/test-suite/go/compactdefaultargs_runme.go create mode 100644 Examples/test-suite/go/constover_runme.go create mode 100644 Examples/test-suite/go/constructor_copy_runme.go create mode 100644 Examples/test-suite/go/contract_runme.go create mode 100644 Examples/test-suite/go/cpp_enum_runme.go create mode 100644 Examples/test-suite/go/cpp_namespace_runme.go create mode 100644 Examples/test-suite/go/cpp_static_runme.go create mode 100644 Examples/test-suite/go/default_args_runme.go create mode 100644 Examples/test-suite/go/default_constructor_runme.go create mode 100644 Examples/test-suite/go/director_abstract_runme.go create mode 100644 Examples/test-suite/go/director_basic_runme.go create mode 100644 Examples/test-suite/go/director_classic_runme.go create mode 100644 Examples/test-suite/go/director_default_runme.go create mode 100644 Examples/test-suite/go/director_detect_runme.go create mode 100644 Examples/test-suite/go/director_enum_runme.go create mode 100644 Examples/test-suite/go/director_exception_runme.go create mode 100644 Examples/test-suite/go/director_extend_runme.go create mode 100644 Examples/test-suite/go/director_finalizer_runme.go create mode 100644 Examples/test-suite/go/director_frob_runme.go create mode 100644 Examples/test-suite/go/director_nested_runme.go create mode 100644 Examples/test-suite/go/director_profile_runme.go create mode 100644 Examples/test-suite/go/director_protected_runme.go create mode 100644 Examples/test-suite/go/director_string_runme.go create mode 100644 Examples/test-suite/go/director_thread_runme.go create mode 100644 Examples/test-suite/go/director_unroll_runme.go create mode 100644 Examples/test-suite/go/disown_runme.go create mode 100644 Examples/test-suite/go/dynamic_cast_runme.go create mode 100644 Examples/test-suite/go/empty_runme.go create mode 100644 Examples/test-suite/go/enum_template_runme.go create mode 100644 Examples/test-suite/go/enums_runme.go create mode 100644 Examples/test-suite/go/exception_order_runme.go create mode 100644 Examples/test-suite/go/extend_placement_runme.go create mode 100644 Examples/test-suite/go/extend_template_ns_runme.go create mode 100644 Examples/test-suite/go/extend_template_runme.go create mode 100644 Examples/test-suite/go/extend_variable_runme.go create mode 100644 Examples/test-suite/go/extern_c_runme.go create mode 100644 Examples/test-suite/go/friends_runme.go create mode 100644 Examples/test-suite/go/fvirtual_runme.go create mode 100644 Examples/test-suite/go/global_ns_arg_runme.go create mode 100644 Examples/test-suite/go/grouping_runme.go create mode 100644 Examples/test-suite/go/import_nomodule_runme.go create mode 100644 Examples/test-suite/go/imports_runme.go create mode 100644 Examples/test-suite/go/inctest_runme.go create mode 100644 Examples/test-suite/go/inherit_missing_runme.go create mode 100644 Examples/test-suite/go/input_runme.go create mode 100644 Examples/test-suite/go/keyword_rename_runme.go create mode 100644 Examples/test-suite/go/li_attribute_runme.go create mode 100644 Examples/test-suite/go/li_carrays_runme.go create mode 100644 Examples/test-suite/go/li_cdata_runme.go create mode 100644 Examples/test-suite/go/li_cmalloc_runme.go create mode 100644 Examples/test-suite/go/li_cpointer_runme.go create mode 100644 Examples/test-suite/go/li_std_map_runme.go create mode 100644 Examples/test-suite/go/member_pointer_runme.go create mode 100644 Examples/test-suite/go/memberin_extend_c_runme.go create mode 100644 Examples/test-suite/go/minherit_runme.go create mode 100644 Examples/test-suite/go/mod_runme.go create mode 100644 Examples/test-suite/go/multi_import_runme.go create mode 100644 Examples/test-suite/go/namespace_class_runme.go create mode 100644 Examples/test-suite/go/namespace_typemap_runme.go create mode 100644 Examples/test-suite/go/namespace_virtual_method_runme.go create mode 100644 Examples/test-suite/go/naturalvar_runme.go create mode 100644 Examples/test-suite/go/nested_workaround_runme.go create mode 100644 Examples/test-suite/go/overload_complicated_runme.go create mode 100644 Examples/test-suite/go/overload_copy_runme.go create mode 100644 Examples/test-suite/go/overload_extend_runme.go create mode 100644 Examples/test-suite/go/overload_extendc_runme.go create mode 100644 Examples/test-suite/go/overload_rename_runme.go create mode 100644 Examples/test-suite/go/overload_simple_runme.go create mode 100644 Examples/test-suite/go/overload_subtype_runme.go create mode 100644 Examples/test-suite/go/overload_template_fast_runme.go create mode 100644 Examples/test-suite/go/overload_template_runme.go create mode 100644 Examples/test-suite/go/preproc_runme.go create mode 100644 Examples/test-suite/go/primitive_ref_runme.go create mode 100644 Examples/test-suite/go/profiletest_runme.go create mode 100644 Examples/test-suite/go/refcount_runme.go create mode 100644 Examples/test-suite/go/reference_global_vars_runme.go create mode 100644 Examples/test-suite/go/rename_scope_runme.go create mode 100644 Examples/test-suite/go/rename_strip_encoder_runme.go create mode 100644 Examples/test-suite/go/ret_by_value_runme.go create mode 100644 Examples/test-suite/go/return_const_value_runme.go create mode 100644 Examples/test-suite/go/smart_pointer_extend_runme.go create mode 100644 Examples/test-suite/go/smart_pointer_member_runme.go create mode 100644 Examples/test-suite/go/smart_pointer_multi_runme.go create mode 100644 Examples/test-suite/go/smart_pointer_multi_typedef_runme.go create mode 100644 Examples/test-suite/go/smart_pointer_overload_runme.go create mode 100644 Examples/test-suite/go/smart_pointer_rename_runme.go create mode 100644 Examples/test-suite/go/smart_pointer_simple_runme.go create mode 100644 Examples/test-suite/go/smart_pointer_templatevariables_runme.go create mode 100644 Examples/test-suite/go/smart_pointer_typedef_runme.go create mode 100644 Examples/test-suite/go/sneaky1_runme.go create mode 100644 Examples/test-suite/go/special_variable_macros_runme.go create mode 100644 Examples/test-suite/go/static_const_member_2_runme.go create mode 100644 Examples/test-suite/go/struct_initialization_runme.go create mode 100644 Examples/test-suite/go/struct_rename_runme.go create mode 100644 Examples/test-suite/go/struct_value_runme.go create mode 100644 Examples/test-suite/go/template_default_arg_runme.go create mode 100644 Examples/test-suite/go/template_extend1_runme.go create mode 100644 Examples/test-suite/go/template_extend2_runme.go create mode 100644 Examples/test-suite/go/template_inherit_runme.go create mode 100644 Examples/test-suite/go/template_ns4_runme.go create mode 100644 Examples/test-suite/go/template_ns_runme.go create mode 100644 Examples/test-suite/go/template_opaque_runme.go create mode 100644 Examples/test-suite/go/template_ref_type_runme.go create mode 100644 Examples/test-suite/go/template_rename_runme.go create mode 100644 Examples/test-suite/go/template_static_runme.go create mode 100644 Examples/test-suite/go/template_tbase_template_runme.go create mode 100644 Examples/test-suite/go/template_type_namespace_runme.go create mode 100644 Examples/test-suite/go/template_typedef_cplx3_runme.go create mode 100644 Examples/test-suite/go/template_typedef_cplx4_runme.go create mode 100644 Examples/test-suite/go/template_typedef_import_runme.go create mode 100644 Examples/test-suite/go/threads_exception_runme.go create mode 100644 Examples/test-suite/go/typedef_class_runme.go create mode 100644 Examples/test-suite/go/typedef_inherit_runme.go create mode 100644 Examples/test-suite/go/typedef_scope_runme.go create mode 100644 Examples/test-suite/go/typemap_namespace_runme.go create mode 100644 Examples/test-suite/go/typemap_ns_using_runme.go create mode 100644 Examples/test-suite/go/typemap_out_optimal_runme.go create mode 100644 Examples/test-suite/go/typename_runme.go create mode 100644 Examples/test-suite/go/unions_runme.go create mode 100644 Examples/test-suite/go/using1_runme.go create mode 100644 Examples/test-suite/go/using2_runme.go create mode 100644 Examples/test-suite/go/using_composition_runme.go create mode 100644 Examples/test-suite/go/using_extend_runme.go create mode 100644 Examples/test-suite/go/using_inherit_runme.go create mode 100644 Examples/test-suite/go/using_private_runme.go create mode 100644 Examples/test-suite/go/using_protected_runme.go create mode 100644 Examples/test-suite/go/varargs_runme.go create mode 100644 Examples/test-suite/go/virtual_derivation_runme.go create mode 100644 Examples/test-suite/go/virtual_poly_runme.go create mode 100644 Examples/test-suite/go/voidtest_runme.go create mode 100644 Examples/test-suite/go/wrapmacro_runme.go create mode 100644 Lib/go/cdata.i create mode 100644 Lib/go/exception.i create mode 100644 Lib/go/go.swg create mode 100644 Lib/go/gokw.swg create mode 100644 Lib/go/goruntime.swg create mode 100644 Lib/go/std_common.i create mode 100644 Lib/go/std_deque.i create mode 100644 Lib/go/std_except.i create mode 100644 Lib/go/std_map.i create mode 100644 Lib/go/std_pair.i create mode 100644 Lib/go/std_string.i create mode 100644 Lib/go/std_vector.i create mode 100644 Lib/go/stl.i create mode 100644 Lib/go/typemaps.i create mode 100644 Source/Modules/go.cxx diff --git a/Doc/Manual/Go.html b/Doc/Manual/Go.html new file mode 100644 index 000000000..7d2ce9db8 --- /dev/null +++ b/Doc/Manual/Go.html @@ -0,0 +1,463 @@ + + + +SWIG and Go + + + +

20 SWIG and Go

+ +
+ +
+ + + + +

+This chapter describes SWIG's support of Go. For more information on +the Go programming language +see golang.org. +

+ +

20.1 Overview

+ + +

+Go is a compiled language, not a scripting language. However, it does +not support direct calling of functions written in C/C++. The cgo +program may be used to generate wrappers to call C code from Go, but +there is no convenient way to call C++ code. SWIG fills this gap. +

+ +

+There are (at least) two different Go compilers. One is the gc +compiler, normally invoked under the names 6g, 8g, or 5g. The other +is the gccgo compiler, which is a frontend to the gcc compiler suite. +The interface to C/C++ code is completely different for the two Go +compilers. SWIG supports both, selected by a command line option. +

+ +

+Because Go is a type-safe compiled language, SWIG's runtime type +checking and runtime library are not used with Go. This should be +borne in mind when reading the rest of the SWIG documentation. +

+ +

20.2 Running SWIG with Go

+ + +

+To generate Go code, use the -go option with SWIG. By +default SWIG will generate code for the gc compilers. To generate +code for gccgo, you should use the -gccgo option. +

+ +

20.2.1 Additional Commandline Options

+ + +

+These are the command line options for SWIG's GO module. They can +also be seen by using: +

+ +
+swig -go -help
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Go specific options
-gccgoGenerate code for gccgo. The default is to generate code for + 6g/8g/6g.
-package <name>Set the name of the Go package to <name>. The default + package name is the SWIG module name.
-go-prefix <prefix>When generating code for gccgo, set the prefix to use. This + corresponds to the -fgo-prefix option to gccgo.
-long-type-size <s>Set the size for the C/C++ type long. This controls + whether long is converted to the Go type int32 + or int64. The <s> argument should be 32 or 64.
-rename <old>=<new>Rename <old%gt; to <new> when processing the C/C++ code + and also the SWIG input file. This is a convenient way to rename + names in the C/C++ code which are the same expect for the first + letter, to avoid conflicts when applying the Go renaming rules + described below.
+ +

20.2.2 Go Output Files

+ + +

When generating Go code, SWIG will generate the following + files:

+ + + +

+A typical command sequence would look like this: +

+ +
+% swig -go example.i
+% gcc -c -fpic example.c
+% gcc -c -fpic example_wrap.c
+% gcc -shared example.o example_wrap.o -o example.so
+% 6g example.go
+% 6c example_gc.c
+% gopack grc example.a example.6 example_gc.6
+% 6g main.go  # your code, not generated by SWIG
+% 6l main.6
+
+ +

20.3 A tour of basic C/C++ wrapping

+ + +

+By default, SWIG attempts to build a natural Go interface to your +C/C++ code. However, the languages are somewhat different, so some +modifications have to occur. This section briefly covers the +essential aspects of this wrapping. +

+ +

20.3.1 Go Package Name

+ + +

+All Go source code lives in a package. The name of this package will +default to the name of the module from SWIG's %module +directive. You may override this by using SWIG's -package +command line option. +

+ +

20.3.2 Go Names

+ + +

+In Go, a function is only visible outside the current package if the +first letter of the name is uppercase. This is quite different from +C/C++. Because of this, C/C++ names are modified when generating the +Go interface: the first letter is forced to be uppercase if it is not +already. This affects the names of functions, methods, variables, +constants, enums, and classes. +

+ +

+C/C++ variables are wrapped with setter and getter functions in Go. +First the first letter of the variable name will be forced to +uppercase, and then Get or Set will be prepended. +For example, if the C/C++ variable is called var, then SWIG +will define the functions GetVar and SetVar. If a +variable is declared as const, or if +SWIG's +%immutable directive is used for the variable, then only +the getter will be defined. +

+ +

+C++ classes will be discussed further below. Here we'll note that the +first letter of the class name will be forced to uppercase to give the +name of a type in Go. A constructor will be named New +followed by that name, and the destructor will be +named Delete followed by that name. +

+ +

20.3.3 Go Constants

+ + +

+C/C++ constants created via #define or the %constant +directive become Go constants, declared with a const +declaration. + +

20.3.4 Go Enumerations

+ + +

+C/C++ enumeration types will cause SWIG to define an integer type with +the name of the enumeration (with first letter forced to uppercase as +usual). The values of the enumeration will become variables in Go; +code should avoid modifying those variables. +

+ +

20.3.5 Go Classes

+ + +

+Go has interfaces, methods and inheritance, but it does not have +classes in the same sense as C++. This sections describes how SWIG +represents C++ classes represented in Go. +

+ +

+For a C++ class ClassName, SWIG will define two types in Go: +an underlying type, which will just hold a pointer to the C++ type, +and an interface type. The interface type will be +named ClassName. SWIG will define a +function NewClassName which will take any constructor +arguments and return a value of the interface +type ClassName. SWIG will also define a +destructor DeleteClassName. +

+ +

+SWIG will represent any methods of the C++ class as methods on the +underlying type, and also as methods of the interface type. Thus C++ +methods may be invoked directly using the +usual val.MethodName syntax. Public members of the C++ class +will be given getter and setter functions defined as methods of the +class. +

+ +

+SWIG will represent static methods of C++ classes as ordinary Go +functions. SWIG will use names like ClassName_MethodName. +SWIG will give static members getter and setter functions with names +like GetClassName_VarName. +

+ +

+Given a value of the interface type, Go code can retrieve the pointer +to the C++ type by calling the Swigcptr method. This will +return a value of type SwigcptrClassName, which is just a +name for uintptr. A Go type conversion can be used to +convert this value to a different C++ type, but note that this +conversion will not be type checked and is essentially equivalent +to reinterpret_cast. This should only be used for very +special cases, such as where C++ would use a dynamic_cast. +

+ +

20.3.5.1 Go Class Inheritance

+ + +

+C++ class inheritance is automatically represented in Go due to its +use of interfaces. The interface for a child class will be a superset +of the interface of its parent class. Thus a value of the child class +type in Go may be passed to a function which expects the parent class. +Doing the reverse will require an explicit type assertion, which will +be checked dynamically. +

+ +

20.3.6 Go Templates

+ + +

+In order to use C++ templates in Go, you must tell SWIG to create +wrappers for a particular template instantation. To do this, use +the %template directive. + +

20.3.7 Go Director Classes

+ + +

+SWIG's director feature permits a Go type to act as the subclass of a +C++ class with virtual methods. This is complicated by the fact that +C++ and Go define inheritance differently. In Go, structs can inherit +methods via anonymous field embedding. However, when a method is +called for an embedded struct, if that method calls any other methods, +they are called for the embedded struct, not for the original type. +Therefore, SWIG must use Go interfaces to represent C++ inheritance. +

+ +

+In order to use the director feature in Go, you must define a type in +your Go code. You must then add methods for the type. Define a +method in Go for each C++ virtual function that you want to override. +You must then create a value of your new type, and pass a pointer to +it to the function NewDirectorClassName, +where ClassName is the name of the C++ class. That will +return a value of type ClassName. +

+ +

+For example: +

+ +
+
+type GoClass struct { }
+func (p *GoClass) VirtualFunction() { }
+func MakeClass() ClassName {
+	return NewDirectorClassName(&GoClass{})
+}
+
+
+ +

+Any call in C++ code to the virtual function will wind up calling the +method defined in Go. The Go code may of course call other methods on +itself, and those methods may be defined either in Go or in C++. +

+ +

20.3.8 Default Go primitive type mappings

+ + +

+The following table lists the default type mapping from C/C++ to Go. +This table will tell you which Go type to expect for a function which +uses a given C/C++ type. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
C/C++ typeGo type
boolbool
charbyte
signed charint8
unsigned charbyte
shortint16
unsigned shortuint16
intint
unsigned intuint
longint32 or int64, depending on -long-type-size
unsigned longuint32 or uint64, depending on -long-type-size
long longint64
unsigned long longuint64
floatfloat32
doublefloat64
char *
char []
string
+ +

+Note that SWIG wraps the C char type as a character. Pointers +and arrays of this type are wrapped as strings. The signed +char type can be used if you want to treat char as a +signed number rather than a character. Also note that all const +references to primitive types are treated as if they are passed by +value. +

+ +

+These type mappings are defined by the "go" typemap. You may change +that typemap, or add new values, to control how C/C++ types are mapped +into Go types. +

+ + + diff --git a/Doc/Manual/SWIG.html b/Doc/Manual/SWIG.html index b4f332b14..d523bee77 100644 --- a/Doc/Manual/SWIG.html +++ b/Doc/Manual/SWIG.html @@ -113,6 +113,7 @@ can be obtained by typing swig -help or swig -clisp Generate CLISP wrappers -cffi Generate CFFI wrappers -csharp Generate C# wrappers +-go Generate Go wrappers -guile Generate Guile wrappers -java Generate Java wrappers -lua Generate Lua wrappers diff --git a/Doc/Manual/Sections.html b/Doc/Manual/Sections.html index e514f726d..8693adc07 100644 --- a/Doc/Manual/Sections.html +++ b/Doc/Manual/Sections.html @@ -36,6 +36,7 @@ Last update : SWIG-2.0.1 (in progress)
  • Allegro CL support
  • C# support
  • Chicken support
  • +
  • Go support
  • Guile support
  • Java support
  • Lua support
  • diff --git a/Doc/Manual/chapters b/Doc/Manual/chapters index bf180f1b4..cd399996b 100644 --- a/Doc/Manual/chapters +++ b/Doc/Manual/chapters @@ -17,6 +17,7 @@ CCache.html Allegrocl.html CSharp.html Chicken.html +Go.html Guile.html Java.html Lisp.html diff --git a/Examples/Makefile.in b/Examples/Makefile.in index 9dee0347f..5960d79fb 100644 --- a/Examples/Makefile.in +++ b/Examples/Makefile.in @@ -1141,3 +1141,74 @@ r_clean: rm -f *.@OBJEXT@ *@SO@ NAMESPACE rm -f $(RRSRC) runme.Rout .RData +################################################################## +##### Go ###### +################################################################## + +GO = @GO@ +GOGCC = @GOGCC@ + +GOSWIGARG = `if $(GOGCC) ; then echo -gccgo; fi` +GOCOMPILEARG = `if $(GOGCC) ; then echo -c -g; fi` + +GOSRCS = $(INTERFACE:.i=.go) +GOCSRCS = $(INTERFACE:.i=_gc.c) + +GOC = $(GO:g=c) +GOLD = $(GO:g=l) + +GOPACKAGE = $(INTERFACE:.i=.a) + +GOOBJEXT = $(GO:g=) +GOGCOBJS = $(GOSRCS:.go=.$(GOOBJEXT)) +GOGCCOBJS = $(GOSRCS:.go=.@OBJEXT@) + +# ---------------------------------------------------------------- +# Build a Go dynamically loadable module (C) +# ---------------------------------------------------------------- + +go: $(SRCS) + $(SWIG) -go $(GOSWIGARG) $(SWIGOPT) $(INTERFACEPATH) + $(CC) -g -c $(CCSHARED) $(CFLAGS) $(SRCS) $(ISRCS) $(INCLUDES) + $(LDSHARED) $(CFLAGS) $(OBJS) $(IOBJS) $(LIBS) -o $(LIBPREFIX)$(TARGET)$(SO) + $(GO) -I . $(GOCOMPILEARG) $(GOSRCS) + if ! $(GOGCC) ; then \ + $(GOC) -I $${GOROOT}/pkg/$${GOOS}_$${GOARCH} $(GOCSRCS) && \ + gopack grc $(GOPACKAGE) $(GOGCOBJS) $(GOCSRCS:.c=.$(GOOBJEXT)); \ + fi + +# ---------------------------------------------------------------- +# Build a Go dynamically loadable module (C++) +# ---------------------------------------------------------------- + +go_cpp: $(SRCS) + $(SWIG) -go -c++ $(GOSWIGARG) $(SWIGOPT) $(INTERFACEPATH) + $(CXX) -g -c $(CCSHARED) $(CFLAGS) $(SRCS) $(CXXSRCS) $(ICXXSRCS) $(INCLUDES) + $(CXXSHARED) $(CFLAGS) $(OBJS) $(IOBJS) $(LIBS) $(CPP_DLLIBS) -o $(LIBPREFIX)$(TARGET)$(SO) + $(GO) -I . $(GOCOMPILEARG) $(GOSRCS) + if ! $(GOGCC) ; then \ + $(GOC) -I $${GOROOT}/pkg/$${GOOS}_$${GOARCH} $(GOCSRCS) && \ + gopack grc $(GOPACKAGE) $(GOGCOBJS) $(GOCSRCS:.c=.$(GOOBJEXT)); \ + else true; fi + +# ----------------------------------------------------------------- +# Running a Go example +# ----------------------------------------------------------------- + +go_run: runme.go + $(GO) $(GOCOMPILEARG) runme.go + if $(GOGCC) ; then \ + $(GO) -o runme runme.@OBJEXT@ $(GOGCCOBJS) $(LIBPREFIX)$(TARGET)$(SO); \ + else \ + $(GOLD) -r $${GOROOT}/pkg/$${GOOS}_$${GOARCH}:. -o runme runme.$(GOOBJEXT); \ + fi + env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH ./runme + +# ----------------------------------------------------------------- +# Cleaning the Go examples +# ----------------------------------------------------------------- + +go_clean: + rm -f *_wrap* *_gc* .~* runme + rm -f core @EXTRA_CLEAN@ + rm -f *.@OBJEXT@ *.[568] *.a *@SO@ diff --git a/Examples/go/callback/Makefile b/Examples/go/callback/Makefile new file mode 100644 index 000000000..9dc8b8851 --- /dev/null +++ b/Examples/go/callback/Makefile @@ -0,0 +1,18 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +CXXSRCS = example.cxx +TARGET = example +INTERFACE = example.i +SWIGOPT = + +all:: go + +go:: + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go_cpp + +clean:: + $(MAKE) -f $(TOP)/Makefile go_clean + +check: all + $(MAKE) -f $(TOP)/Makefile TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go_run diff --git a/Examples/go/callback/example.cxx b/Examples/go/callback/example.cxx new file mode 100644 index 000000000..450d75608 --- /dev/null +++ b/Examples/go/callback/example.cxx @@ -0,0 +1,4 @@ +/* File : example.cxx */ + +#include "example.h" + diff --git a/Examples/go/callback/example.go b/Examples/go/callback/example.go new file mode 100644 index 000000000..5c0cfb051 --- /dev/null +++ b/Examples/go/callback/example.go @@ -0,0 +1,188 @@ +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 2.0.1 + * + * This file is not intended to be easily readable and contains a number of + * coding conventions designed to improve portability and efficiency. Do not make + * changes to this file unless you know what you are doing--modify the SWIG + * interface file instead. + * ----------------------------------------------------------------------------- */ + +package example + + +type _swig_fnptr *byte +type _swig_memberptr *byte + + +func _swig_allocatememory(int) *byte +func _swig_internal_allocate(len int) *byte { + return _swig_allocatememory(len) +} + +func _swig_allocatestring(*byte, int) string +func _swig_internal_makegostring(p *byte, l int) string { + return _swig_allocatestring(p, l) +} + +func _swig_internal_gopanic(p *byte, l int) { + panic(_swig_allocatestring(p, l)) +} + +type _swig_DirectorCallback struct { + SwigcptrCallback + v interface{} +} + +func (p *_swig_DirectorCallback) Swigcptr() uintptr { + return p.SwigcptrCallback.Swigcptr() +} + +func (p *_swig_DirectorCallback) SwigIsCallback() { +} + +func (p *_swig_DirectorCallback) DirectorInterface() interface{} { + return p.v +} + +func _swig_NewDirectorCallbackCallback(*_swig_DirectorCallback) SwigcptrCallback + +func NewDirectorCallback(v interface{}) Callback { + p := &_swig_DirectorCallback{0, v} + p.SwigcptrCallback = _swig_NewDirectorCallbackCallback(p) + return p +} + +func _swig_wrap_DeleteDirectorCallback(uintptr) + +func DeleteDirectorCallback(arg1 Callback) { + _swig_wrap_DeleteDirectorCallback(arg1.Swigcptr()) +} + +func Swiggo_DeleteDirector_Callback(p *_swig_DirectorCallback) { + p.SwigcptrCallback = 0 +} + +type _swig_DirectorInterfaceCallbackRun interface { + Run() +} + +func _swig_wrap__swig_DirectorCallback_upcall_Run(SwigcptrCallback) +func (swig_p *_swig_DirectorCallback) Run() { + if swig_g, swig_ok := swig_p.v.(_swig_DirectorInterfaceCallbackRun); swig_ok { + swig_g.Run() + return + } + _swig_wrap__swig_DirectorCallback_upcall_Run(swig_p.SwigcptrCallback) +} + +func DirectorCallbackRun(p Callback) { + _swig_wrap__swig_DirectorCallback_upcall_Run(p.(*_swig_DirectorCallback).SwigcptrCallback) +} + +func Swig_DirectorCallback_callback_run(p *_swig_DirectorCallback) { + p.Run() +} + +type SwigcptrCallback uintptr + +func (p SwigcptrCallback) Swigcptr() uintptr { + return (uintptr)(p) +} + +func (p SwigcptrCallback) SwigIsCallback() { +} + +func (p SwigcptrCallback) DirectorInterface() interface{} { + return nil +} + +func _swig_wrap_delete_Callback(uintptr) + +func DeleteCallback(arg1 Callback) { + _swig_wrap_delete_Callback(arg1.Swigcptr()) +} + +func _swig_wrap_Callback_run(SwigcptrCallback) + +func (arg1 SwigcptrCallback) Run() { + _swig_wrap_Callback_run(arg1) +} + +func _swig_wrap_new_Callback() SwigcptrCallback + +func NewCallback() Callback { + return _swig_wrap_new_Callback() +} + +type Callback interface { + Swigcptr() uintptr + SwigIsCallback() + DirectorInterface() interface{} + Run() +} + +type SwigcptrCaller uintptr + +func (p SwigcptrCaller) Swigcptr() uintptr { + return (uintptr)(p) +} + +func (p SwigcptrCaller) SwigIsCaller() { +} + +func _swig_wrap_new_Caller() SwigcptrCaller + +func NewCaller() Caller { + return _swig_wrap_new_Caller() +} + +func _swig_wrap_delete_Caller(uintptr) + +func DeleteCaller(arg1 Caller) { + _swig_wrap_delete_Caller(arg1.Swigcptr()) +} + +func _swig_wrap_Caller_delCallback(SwigcptrCaller) + +func (arg1 SwigcptrCaller) DelCallback() { + _swig_wrap_Caller_delCallback(arg1) +} + +func _swig_wrap_Caller_setCallback(SwigcptrCaller, uintptr) + +func (arg1 SwigcptrCaller) SetCallback(arg2 Callback) { + _swig_wrap_Caller_setCallback(arg1, arg2.Swigcptr()) +} + +func _swig_wrap_Caller_call(SwigcptrCaller) + +func (arg1 SwigcptrCaller) Call() { + _swig_wrap_Caller_call(arg1) +} + +type Caller interface { + Swigcptr() uintptr + SwigIsCaller() + DelCallback() + SetCallback(arg2 Callback) + Call() +} + + +type SwigcptrSwigDirector_Callback uintptr +type SwigDirector_Callback interface { + Swigcptr() uintptr; +} +func (p SwigcptrSwigDirector_Callback) Swigcptr() uintptr { + return uintptr(p) +} + +type SwigcptrVoid uintptr +type Void interface { + Swigcptr() uintptr; +} +func (p SwigcptrVoid) Swigcptr() uintptr { + return uintptr(p) +} + diff --git a/Examples/go/callback/example.h b/Examples/go/callback/example.h new file mode 100644 index 000000000..1a0e8c432 --- /dev/null +++ b/Examples/go/callback/example.h @@ -0,0 +1,23 @@ +/* File : example.h */ + +#include +#include + +class Callback { +public: + virtual ~Callback() { std::cout << "Callback::~Callback()" << std:: endl; } + virtual void run() { std::cout << "Callback::run()" << std::endl; } +}; + + +class Caller { +private: + Callback *_callback; +public: + Caller(): _callback(0) {} + ~Caller() { delCallback(); } + void delCallback() { delete _callback; _callback = 0; } + void setCallback(Callback *cb) { delCallback(); _callback = cb; } + void call() { if (_callback) _callback->run(); } +}; + diff --git a/Examples/go/callback/example.i b/Examples/go/callback/example.i new file mode 100644 index 000000000..90beda01a --- /dev/null +++ b/Examples/go/callback/example.i @@ -0,0 +1,13 @@ +/* File : example.i */ +%module(directors="1") example +%{ +#include "example.h" +%} + +%include "std_string.i" + +/* turn on director wrapping Callback */ +%feature("director") Callback; + +%include "example.h" + diff --git a/Examples/go/callback/index.html b/Examples/go/callback/index.html new file mode 100644 index 000000000..b053cf547 --- /dev/null +++ b/Examples/go/callback/index.html @@ -0,0 +1,81 @@ + + +SWIG:Examples:go:callback + + + + + +SWIG/Examples/go/callback/ +
    + +

    Implementing C++ callbacks in Go

    + +

    +This example illustrates how to use directors to implement C++ +callbacks in Go. +

    + +

    +Because Go and C++ use inheritance differently, you must call a +different function to create a class which uses callbacks. Instead of +calling the usual constructor function whose name is New +followed by the capitalized name of the class, you call a function +named NewDirector followed by the capitalized name of the +class. +

    + +

    +The first argument to the NewDirector function is an instance +of a type. The NewDirector function will return an interface +value as usual. However, when calling any method on the returned +value, the program will first check whether the value passed +to NewDirector implements that method. If it does, the +method will be called in Go. This is true whether the method is +called from Go code or C++ code. +

    + +

    +Note that the Go code will be called with just the Go value, not the +C++ value. If the Go code needs to call a C++ method on itself, you +need to get a copy of the C++ object. This is typically done as +follows: + +

    +
    +type Child struct { abi Parent }
    +func (p *Child) ChildMethod() {
    +	p.abi.ParentMethod()
    +}
    +func f() {
    +	p := &Child{nil}
    +	d := NewDirectorParent(p)
    +	p.abi = d
    +	...
    +}
    +
    +
    + +In other words, we first create the Go value. We pass that to +the NewDirector function to create the C++ value; this C++ +value will be created with an association to the Go value. We then +store the C++ value in the Go value, giving us the reverse +association. That permits us to call parent methods from the child. + +

    + +

    +To delete a director object, use the function DeleteDirector +followed by the capitalized name of the class. +

    + +

    +

    + +
    + + diff --git a/Examples/go/callback/runme.go b/Examples/go/callback/runme.go new file mode 100644 index 000000000..ffa4b3874 --- /dev/null +++ b/Examples/go/callback/runme.go @@ -0,0 +1,41 @@ +package main + +import ( + "fmt" + . "./example" +) + +func main() { + fmt.Println("Adding and calling a normal C++ callback") + fmt.Println("----------------------------------------") + + caller := NewCaller() + callback := NewCallback() + + caller.SetCallback(callback) + caller.Call() + caller.DelCallback() + + callback = NewDirectorCallback(new(GoCallback)) + + fmt.Println() + fmt.Println("Adding and calling a Go callback") + fmt.Println("------------------------------------") + + caller.SetCallback(callback) + caller.Call() + caller.DelCallback() + + // Test that a double delete does not occur as the object has + // already been deleted from the C++ layer. + DeleteDirectorCallback(callback) + + fmt.Println() + fmt.Println("Go exit") +} + +type GoCallback struct{} + +func (p *GoCallback) Run() { + fmt.Println("GoCallback.Run") +} diff --git a/Examples/go/check.list b/Examples/go/check.list new file mode 100644 index 000000000..5399b8979 --- /dev/null +++ b/Examples/go/check.list @@ -0,0 +1,13 @@ +# see top-level Makefile.in +callback +class +constants +enum +extend +funcptr +multimap +pointer +reference +simple +template +variables diff --git a/Examples/go/class/Makefile b/Examples/go/class/Makefile new file mode 100644 index 000000000..53d31d1a4 --- /dev/null +++ b/Examples/go/class/Makefile @@ -0,0 +1,16 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +CXXSRCS = example.cxx +TARGET = example +INTERFACE = example.i +LIBS = -lm + +all:: + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go_cpp + +clean:: + $(MAKE) -f $(TOP)/Makefile go_clean + +check: all + $(MAKE) -f $(TOP)/Makefile TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go_run diff --git a/Examples/go/class/example.cxx b/Examples/go/class/example.cxx new file mode 100644 index 000000000..1e8e203dd --- /dev/null +++ b/Examples/go/class/example.cxx @@ -0,0 +1,28 @@ +/* File : example.c */ + +#include "example.h" +#define M_PI 3.14159265358979323846 + +/* Move the shape to a new location */ +void Shape::move(double dx, double dy) { + x += dx; + y += dy; +} + +int Shape::nshapes = 0; + +double Circle::area(void) { + return M_PI*radius*radius; +} + +double Circle::perimeter(void) { + return 2*M_PI*radius; +} + +double Square::area(void) { + return width*width; +} + +double Square::perimeter(void) { + return 4*width; +} diff --git a/Examples/go/class/example.go b/Examples/go/class/example.go new file mode 100644 index 000000000..ec8113ad4 --- /dev/null +++ b/Examples/go/class/example.go @@ -0,0 +1,284 @@ +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 2.0.1 + * + * This file is not intended to be easily readable and contains a number of + * coding conventions designed to improve portability and efficiency. Do not make + * changes to this file unless you know what you are doing--modify the SWIG + * interface file instead. + * ----------------------------------------------------------------------------- */ + +package example + + +type _swig_fnptr *byte +type _swig_memberptr *byte + + +func _swig_allocatememory(int) *byte +func _swig_internal_allocate(len int) *byte { + return _swig_allocatememory(len) +} + +func _swig_allocatestring(*byte, int) string +func _swig_internal_makegostring(p *byte, l int) string { + return _swig_allocatestring(p, l) +} + +func _swig_internal_gopanic(p *byte, l int) { + panic(_swig_allocatestring(p, l)) +} + +type SwigcptrShape uintptr + +func (p SwigcptrShape) Swigcptr() uintptr { + return (uintptr)(p) +} + +func (p SwigcptrShape) SwigIsShape() { +} + +func _swig_wrap_delete_Shape(uintptr) + +func DeleteShape(arg1 Shape) { + _swig_wrap_delete_Shape(arg1.Swigcptr()) +} + +func _swig_wrap_Shape_x_set(SwigcptrShape, float64) + +func (arg1 SwigcptrShape) SetX(arg2 float64) { + _swig_wrap_Shape_x_set(arg1, arg2) +} + +func _swig_wrap_Shape_x_get(SwigcptrShape) float64 + +func (arg1 SwigcptrShape) GetX() float64 { + return _swig_wrap_Shape_x_get(arg1) +} + +func _swig_wrap_Shape_y_set(SwigcptrShape, float64) + +func (arg1 SwigcptrShape) SetY(arg2 float64) { + _swig_wrap_Shape_y_set(arg1, arg2) +} + +func _swig_wrap_Shape_y_get(SwigcptrShape) float64 + +func (arg1 SwigcptrShape) GetY() float64 { + return _swig_wrap_Shape_y_get(arg1) +} + +func _swig_wrap_Shape_move(SwigcptrShape, float64, float64) + +func (arg1 SwigcptrShape) Move(arg2 float64, arg3 float64) { + _swig_wrap_Shape_move(arg1, arg2, arg3) +} + +func _swig_wrap_Shape_area(SwigcptrShape) float64 + +func (arg1 SwigcptrShape) Area() float64 { + return _swig_wrap_Shape_area(arg1) +} + +func _swig_wrap_Shape_perimeter(SwigcptrShape) float64 + +func (arg1 SwigcptrShape) Perimeter() float64 { + return _swig_wrap_Shape_perimeter(arg1) +} + +func _swig_wrap_Shape_nshapes_set(int) + +func SetShapeNshapes(arg1 int) { + _swig_wrap_Shape_nshapes_set(arg1) +} + +func GetShapeNshapes() int +type Shape interface { + Swigcptr() uintptr + SwigIsShape() + SetX(arg2 float64) + GetX() float64 + SetY(arg2 float64) + GetY() float64 + Move(arg2 float64, arg3 float64) + Area() float64 + Perimeter() float64 +} + +type SwigcptrCircle uintptr + +func (p SwigcptrCircle) Swigcptr() uintptr { + return (uintptr)(p) +} + +func (p SwigcptrCircle) SwigIsCircle() { +} + +func _swig_wrap_new_Circle(float64) SwigcptrCircle + +func NewCircle(arg1 float64) Circle { + return _swig_wrap_new_Circle(arg1) +} + +func _swig_wrap_Circle_area(SwigcptrCircle) float64 + +func (arg1 SwigcptrCircle) Area() float64 { + return _swig_wrap_Circle_area(arg1) +} + +func _swig_wrap_Circle_perimeter(SwigcptrCircle) float64 + +func (arg1 SwigcptrCircle) Perimeter() float64 { + return _swig_wrap_Circle_perimeter(arg1) +} + +func _swig_wrap_delete_Circle(uintptr) + +func DeleteCircle(arg1 Circle) { + _swig_wrap_delete_Circle(arg1.Swigcptr()) +} + +func _swig_wrap_SetCircle_X(SwigcptrCircle, float64) + +func (_swig_base SwigcptrCircle) SetX(arg1 float64) { + _swig_wrap_SetCircle_X(_swig_base, arg1) +} + +func _swig_wrap_GetCircle_X(SwigcptrCircle) float64 + +func (_swig_base SwigcptrCircle) GetX() float64 { + return _swig_wrap_GetCircle_X(_swig_base) +} + +func _swig_wrap_SetCircle_Y(SwigcptrCircle, float64) + +func (_swig_base SwigcptrCircle) SetY(arg1 float64) { + _swig_wrap_SetCircle_Y(_swig_base, arg1) +} + +func _swig_wrap_GetCircle_Y(SwigcptrCircle) float64 + +func (_swig_base SwigcptrCircle) GetY() float64 { + return _swig_wrap_GetCircle_Y(_swig_base) +} + +func _swig_wrap_Circle_move(SwigcptrCircle, float64, float64) + +func (_swig_base SwigcptrCircle) Move(arg1 float64, arg2 float64) { + _swig_wrap_Circle_move(_swig_base, arg1, arg2) +} + +func (p SwigcptrCircle) SwigIsShape() { +} + +func (p SwigcptrCircle) SwigGetShape() Shape { + return SwigcptrShape(p.Swigcptr()) +} + +type Circle interface { + Swigcptr() uintptr + SwigIsCircle() + Area() float64 + Perimeter() float64 + SetX(arg1 float64) + GetX() float64 + SetY(arg1 float64) + GetY() float64 + Move(arg1 float64, arg2 float64) + SwigIsShape() + SwigGetShape() Shape +} + +type SwigcptrSquare uintptr + +func (p SwigcptrSquare) Swigcptr() uintptr { + return (uintptr)(p) +} + +func (p SwigcptrSquare) SwigIsSquare() { +} + +func _swig_wrap_new_Square(float64) SwigcptrSquare + +func NewSquare(arg1 float64) Square { + return _swig_wrap_new_Square(arg1) +} + +func _swig_wrap_Square_area(SwigcptrSquare) float64 + +func (arg1 SwigcptrSquare) Area() float64 { + return _swig_wrap_Square_area(arg1) +} + +func _swig_wrap_Square_perimeter(SwigcptrSquare) float64 + +func (arg1 SwigcptrSquare) Perimeter() float64 { + return _swig_wrap_Square_perimeter(arg1) +} + +func _swig_wrap_delete_Square(uintptr) + +func DeleteSquare(arg1 Square) { + _swig_wrap_delete_Square(arg1.Swigcptr()) +} + +func _swig_wrap_SetSquare_X(SwigcptrSquare, float64) + +func (_swig_base SwigcptrSquare) SetX(arg1 float64) { + _swig_wrap_SetSquare_X(_swig_base, arg1) +} + +func _swig_wrap_GetSquare_X(SwigcptrSquare) float64 + +func (_swig_base SwigcptrSquare) GetX() float64 { + return _swig_wrap_GetSquare_X(_swig_base) +} + +func _swig_wrap_SetSquare_Y(SwigcptrSquare, float64) + +func (_swig_base SwigcptrSquare) SetY(arg1 float64) { + _swig_wrap_SetSquare_Y(_swig_base, arg1) +} + +func _swig_wrap_GetSquare_Y(SwigcptrSquare) float64 + +func (_swig_base SwigcptrSquare) GetY() float64 { + return _swig_wrap_GetSquare_Y(_swig_base) +} + +func _swig_wrap_Square_move(SwigcptrSquare, float64, float64) + +func (_swig_base SwigcptrSquare) Move(arg1 float64, arg2 float64) { + _swig_wrap_Square_move(_swig_base, arg1, arg2) +} + +func (p SwigcptrSquare) SwigIsShape() { +} + +func (p SwigcptrSquare) SwigGetShape() Shape { + return SwigcptrShape(p.Swigcptr()) +} + +type Square interface { + Swigcptr() uintptr + SwigIsSquare() + Area() float64 + Perimeter() float64 + SetX(arg1 float64) + GetX() float64 + SetY(arg1 float64) + GetY() float64 + Move(arg1 float64, arg2 float64) + SwigIsShape() + SwigGetShape() Shape +} + + +type SwigcptrVoid uintptr +type Void interface { + Swigcptr() uintptr; +} +func (p SwigcptrVoid) Swigcptr() uintptr { + return uintptr(p) +} + diff --git a/Examples/go/class/example.h b/Examples/go/class/example.h new file mode 100644 index 000000000..46d901361 --- /dev/null +++ b/Examples/go/class/example.h @@ -0,0 +1,39 @@ +/* File : example.h */ + +class Shape { +public: + Shape() { + nshapes++; + } + virtual ~Shape() { + nshapes--; + }; + double x, y; + void move(double dx, double dy); + virtual double area(void) = 0; + virtual double perimeter(void) = 0; + static int nshapes; +}; + +class Circle : public Shape { +private: + double radius; +public: + Circle(double r) : radius(r) { }; + virtual double area(void); + virtual double perimeter(void); +}; + +class Square : public Shape { +private: + double width; +public: + Square(double w) : width(w) { }; + virtual double area(void); + virtual double perimeter(void); +}; + + + + + diff --git a/Examples/go/class/example.i b/Examples/go/class/example.i new file mode 100644 index 000000000..75700b305 --- /dev/null +++ b/Examples/go/class/example.i @@ -0,0 +1,10 @@ +/* File : example.i */ +%module example + +%{ +#include "example.h" +%} + +/* Let's just grab the original header file here */ +%include "example.h" + diff --git a/Examples/go/class/index.html b/Examples/go/class/index.html new file mode 100644 index 000000000..b39119d12 --- /dev/null +++ b/Examples/go/class/index.html @@ -0,0 +1,203 @@ + + +SWIG:Examples:go:class + + + + + +SWIG/Examples/go/class/ +
    + +

    Wrapping a simple C++ class

    + +

    +This example illustrates the most primitive form of C++ class wrapping +performed by SWIG. In this case, C++ classes are simply transformed +into a collection of C-style functions that provide access to class +members. + +

    The C++ Code

    + +Suppose you have some C++ classes described by the following (and +admittedly lame) header file: + +
    +
    +/* File : example.h */
    +
    +class Shape {
    +public:
    +  Shape() {
    +    nshapes++;
    +  }
    +  virtual ~Shape() {
    +    nshapes--;
    +  };
    +  double  x, y;   
    +  void    move(double dx, double dy);
    +  virtual double area() = 0;
    +  virtual double perimeter() = 0;
    +  static  int nshapes;
    +};
    +
    +class Circle : public Shape {
    +private:
    +  double radius;
    +public:
    +  Circle(double r) : radius(r) { };
    +  virtual double area();
    +  virtual double perimeter();
    +};
    +
    +class Square : public Shape {
    +private:
    +  double width;
    +public:
    +  Square(double w) : width(w) { };
    +  virtual double area();
    +  virtual double perimeter();
    +};
    +
    +
    + +

    The SWIG interface

    + +A simple SWIG interface for this can be built by simply grabbing the +header file like this: + +
    +
    +/* File : example.i */
    +%module example
    +
    +%{
    +#include "example.h"
    +%}
    +
    +/* Let's just grab the original header file here */
    +%include "example.h"
    +
    +
    + +Note: when creating a C++ extension, you must run SWIG with +the -c++ option like this: +
    +
    +% swig -c++ -go example.i
    +
    +
    + +

    A sample Go script

    + +See example.go for a program that calls the +C++ functions from Go. + +

    Key points

    + +
      +
    • To create a new object, you call a constructor like this: + +
      +
      +c := example.NewCircle(10.0)
      +
      +
      + +The name of the constructor is New followed by the name of +the class, capitalized. + +

      +

    • +The constructor returns a value of interface type. The methods of the +interface will be the methods of the C++ class, plus member accessor +functions. + +

      +

    • To access member data, a pair of accessor methods are used. For +example: + +
      +
      +c.SetX(15)          # Set member data
      +x := c.GetX()       # Get member data.
      +
      +
      + +These are methods on the type returned by the constructor. The getter +is named Get followed by the name of the member, +capitalized. The setter is similar but uses Set. + +

      +

    • To invoke a member function, you simply do this + +
      +
      +fmt.Println("The area is", example.c.Area())
      +
      +
      + +
    • To invoke a destructor, simply do this + +
      +
      +example.DeleteShape(c)     # Deletes a shape
      +
      +
      + +The name of the destructor is Delete followed by the name of +the class, capitalized. (Note: destructors are currently not +inherited. This might change later). + +

      +

    • Static member variables are wrapped much like C global variables. +For example: + +
      +
      +n := GetShapeNshapes()     # Get a static data member
      +SetShapeNshapes(13)        # Set a static data member
      +
      +
      + +The name is Get or Set, followed by the name of the +class, capitalized, followed by the name of the member, capitalized. + +
    + +

    General Comments

    + +
      +
    • This low-level interface is not the only way to handle C++ code. +Director classes provide a much higher-level interface. + +

      +

    • Because C++ and Go implement inheritance quite differently, you +can not simply upcast an object in Go code when using multiple +inheritance. When using only single inheritance, you can simply pass +a class to a function expecting a parent class. When using multiple +inheritance, you have to call an automatically generated getter +function named Get followed by the capitalized name of the +immediate parent. This will return the same object converted to the + parent class. + +

      +

    • +Overloaded methods should normally work. However, when calling an +overloaded method you must explicitly convert constants to the +expected type when it is not int or float. In +particular, a floating point constant will default to +type float, but C++ functions typically expect the C++ +type double which is equivalent to the Go +type float64 So calling an overloaded method with a floating +point constant typically requires an explicit conversion +to float64. + +

      +

    • Namespaces are not supported in any very coherent way. + +
    + +
    + + diff --git a/Examples/go/class/runme.go b/Examples/go/class/runme.go new file mode 100644 index 000000000..ff64bb4be --- /dev/null +++ b/Examples/go/class/runme.go @@ -0,0 +1,63 @@ +// This example illustrates how C++ classes can be used from Go using SWIG. + +package main + +import ( + "fmt" + . "./example" +) + +func main() { + // ----- Object creation ----- + + fmt.Println("Creating some objects:") + c := NewCircle(10) + fmt.Println(" Created circle", c) + s := NewSquare(10) + fmt.Println(" Created square", s) + + // ----- Access a static member ----- + + fmt.Println("\nA total of", GetShapeNshapes(), "shapes were created") + + // ----- Member data access ----- + + // Notice how we can do this using functions specific to + // the 'Circle' class. + c.SetX(20) + c.SetY(30) + + // Now use the same functions in the base class + var shape Shape = s + shape.SetX(-10) + shape.SetY(5) + + fmt.Println("\nHere is their current position:") + fmt.Println(" Circle = (", c.GetX(), " ", c.GetY(), ")") + fmt.Println(" Square = (", s.GetX(), " ", s.GetY(), ")") + + // ----- Call some methods ----- + + fmt.Println("\nHere are some properties of the shapes:") + shapes := []Shape{c, s} + for i := 0; i < len(shapes); i++ { + fmt.Println(" ", shapes[i]) + fmt.Println(" area = ", shapes[i].Area()) + fmt.Println(" perimeter = ", shapes[i].Perimeter()) + } + + // Notice how the area() and perimeter() functions really + // invoke the appropriate virtual method on each object. + + // ----- Delete everything ----- + + fmt.Println("\nGuess I'll clean up now") + + // Note: this invokes the virtual destructor + // You could leave this to the garbage collector + DeleteCircle(c) + DeleteSquare(s) + + fmt.Println(GetShapeNshapes(), " shapes remain") + fmt.Println("Goodbye") +} diff --git a/Examples/go/constants/Makefile b/Examples/go/constants/Makefile new file mode 100644 index 000000000..71d4d73a4 --- /dev/null +++ b/Examples/go/constants/Makefile @@ -0,0 +1,16 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +CXXSRCS = +TARGET = example +INTERFACE = example.i +SWIGOPT = + +all:: + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go + +clean:: + $(MAKE) -f $(TOP)/Makefile go_clean + +check: all + $(MAKE) -f $(TOP)/Makefile TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go_run diff --git a/Examples/go/constants/example.go b/Examples/go/constants/example.go new file mode 100644 index 000000000..0e5e66418 --- /dev/null +++ b/Examples/go/constants/example.go @@ -0,0 +1,44 @@ +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 2.0.1 + * + * This file is not intended to be easily readable and contains a number of + * coding conventions designed to improve portability and efficiency. Do not make + * changes to this file unless you know what you are doing--modify the SWIG + * interface file instead. + * ----------------------------------------------------------------------------- */ + +package example + + +type _swig_fnptr *byte +type _swig_memberptr *byte + + +func _swig_allocatememory(int) *byte +func _swig_internal_allocate(len int) *byte { + return _swig_allocatememory(len) +} + +func _swig_allocatestring(*byte, int) string +func _swig_internal_makegostring(p *byte, l int) string { + return _swig_allocatestring(p, l) +} + +func _swig_internal_gopanic(p *byte, l int) { + panic(_swig_allocatestring(p, l)) +} + +const ICONST int = 42 +const FCONST float64 = 2.1828 +const CCONST byte = 'x' +func _swig_getCCONST2() byte +var CCONST2 byte = _swig_getCCONST2() +const SCONST string = "Hello World" +func _swig_getSCONST2() string +var SCONST2 string = _swig_getSCONST2() +func _swig_getEXPR() float64 +var EXPR float64 = _swig_getEXPR() +const Iconst int = 37 +const Fconst float64 = 3.14 + diff --git a/Examples/go/constants/example.i b/Examples/go/constants/example.i new file mode 100644 index 000000000..daca042df --- /dev/null +++ b/Examples/go/constants/example.i @@ -0,0 +1,25 @@ +/* File : example.i */ +%module example + +/* A few preprocessor macros */ + +#define ICONST 42 +#define FCONST 2.1828 +#define CCONST 'x' +#define CCONST2 '\n' +#define SCONST "Hello World" +#define SCONST2 "\"Hello World\"" + +/* This should work just fine */ +#define EXPR ICONST + 3*(FCONST) + +/* This shouldn't do anything */ +#define EXTERN extern + +/* Neither should this (BAR isn't defined) */ +#define FOO (ICONST + BAR) + +/* The following directives also produce constants */ + +%constant int iconst = 37; +%constant double fconst = 3.14; diff --git a/Examples/go/constants/index.html b/Examples/go/constants/index.html new file mode 100644 index 000000000..b1397ab2d --- /dev/null +++ b/Examples/go/constants/index.html @@ -0,0 +1,55 @@ + + +SWIG:Examples:go:constants + + + + +SWIG/Examples/go/constants/ +
    + +

    Wrapping C Constants

    + +

    +When SWIG encounters C preprocessor macros and C declarations that +look like constants, it creates a Go constant with an identical value. +Click here to see a SWIG interface with some +constant declarations in it. + + +

    Accessing Constants from Go

    +Click here for +the section on constants in the SWIG and Go documentation. +

    + +Click here to see a Go program that prints out +the values of the constants contained in the above file.

    +

    Key points

    +
      +
    • All names are capitalized to make them visible. +
    • The values of preprocessor macros are converted into Go constants. +
    • C string literals such as "Hello World" are converted into Go strings. +
    • Macros that are not fully defined are simply ignored. For example: +
      +
      +#define EXTERN extern
      +
      +
      +is ignored because SWIG has no idea what type of variable this would be. + +

      +

    • Expressions are allowed provided that all of their components are +defined. Otherwise, the constant is ignored. + +
    • Certain C declarations involving 'const' are also turned into Go +constants. +
    • The constants that appear in a SWIG interface file do not have to +appear in any sort of matching C source file since the creation of a +constant does not require linkage to a stored value (i.e., a value +held in a C global variable or memory location). +
    + +
    + + + diff --git a/Examples/go/constants/runme.go b/Examples/go/constants/runme.go new file mode 100644 index 000000000..78a047e20 --- /dev/null +++ b/Examples/go/constants/runme.go @@ -0,0 +1,18 @@ +package main + +import ( + "fmt" + "./example" +) + +func main() { + fmt.Println("ICONST = ", example.ICONST, " (should be 42)") + fmt.Println("FCONST = ", example.FCONST, " (should be 2.1828)") + fmt.Printf("CCONST = %c (should be 'x')\n", example.CCONST) + fmt.Printf("CCONST2 = %c(this should be on a new line)\n", example.CCONST2) + fmt.Println("SCONST = ", example.SCONST, " (should be 'Hello World')") + fmt.Println("SCONST2 = ", example.SCONST2, " (should be '\"Hello World\"')") + fmt.Println("EXPR = ", example.EXPR, " (should be 48.5484)") + fmt.Println("iconst = ", example.Iconst, " (should be 37)") + fmt.Println("fconst = ", example.Fconst, " (should be 3.14)") +} diff --git a/Examples/go/enum/Makefile b/Examples/go/enum/Makefile new file mode 100644 index 000000000..9dc8b8851 --- /dev/null +++ b/Examples/go/enum/Makefile @@ -0,0 +1,18 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +CXXSRCS = example.cxx +TARGET = example +INTERFACE = example.i +SWIGOPT = + +all:: go + +go:: + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go_cpp + +clean:: + $(MAKE) -f $(TOP)/Makefile go_clean + +check: all + $(MAKE) -f $(TOP)/Makefile TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go_run diff --git a/Examples/go/enum/example.cxx b/Examples/go/enum/example.cxx new file mode 100644 index 000000000..df7bb6328 --- /dev/null +++ b/Examples/go/enum/example.cxx @@ -0,0 +1,37 @@ +/* File : example.cxx */ + +#include "example.h" +#include + +void Foo::enum_test(speed s) { + if (s == IMPULSE) { + printf("IMPULSE speed\n"); + } else if (s == WARP) { + printf("WARP speed\n"); + } else if (s == LUDICROUS) { + printf("LUDICROUS speed\n"); + } else { + printf("Unknown speed\n"); + } +} + +void enum_test(color c, Foo::speed s) { + if (c == RED) { + printf("color = RED, "); + } else if (c == BLUE) { + printf("color = BLUE, "); + } else if (c == GREEN) { + printf("color = GREEN, "); + } else { + printf("color = Unknown color!, "); + } + if (s == Foo::IMPULSE) { + printf("speed = IMPULSE speed\n"); + } else if (s == Foo::WARP) { + printf("speed = WARP speed\n"); + } else if (s == Foo::LUDICROUS) { + printf("speed = LUDICROUS speed\n"); + } else { + printf("speed = Unknown speed!\n"); + } +} diff --git a/Examples/go/enum/example.go b/Examples/go/enum/example.go new file mode 100644 index 000000000..4653ab57a --- /dev/null +++ b/Examples/go/enum/example.go @@ -0,0 +1,93 @@ +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 2.0.1 + * + * This file is not intended to be easily readable and contains a number of + * coding conventions designed to improve portability and efficiency. Do not make + * changes to this file unless you know what you are doing--modify the SWIG + * interface file instead. + * ----------------------------------------------------------------------------- */ + +package example + + +type _swig_fnptr *byte +type _swig_memberptr *byte + + +func _swig_allocatememory(int) *byte +func _swig_internal_allocate(len int) *byte { + return _swig_allocatememory(len) +} + +func _swig_allocatestring(*byte, int) string +func _swig_internal_makegostring(p *byte, l int) string { + return _swig_allocatestring(p, l) +} + +func _swig_internal_gopanic(p *byte, l int) { + panic(_swig_allocatestring(p, l)) +} + +type Color int +func _swig_getRED() Color +var RED Color = _swig_getRED() +func _swig_getBLUE() Color +var BLUE Color = _swig_getBLUE() +func _swig_getGREEN() Color +var GREEN Color = _swig_getGREEN() +type SwigcptrFoo uintptr + +func (p SwigcptrFoo) Swigcptr() uintptr { + return (uintptr)(p) +} + +func (p SwigcptrFoo) SwigIsFoo() { +} + +func _swig_wrap_new_Foo() SwigcptrFoo + +func NewFoo() Foo { + return _swig_wrap_new_Foo() +} + +type FooSpeed int +func _swig_getFoo_IMPULSE_Foo() FooSpeed +var FooIMPULSE FooSpeed = _swig_getFoo_IMPULSE_Foo() +func _swig_getFoo_WARP_Foo() FooSpeed +var FooWARP FooSpeed = _swig_getFoo_WARP_Foo() +func _swig_getFoo_LUDICROUS_Foo() FooSpeed +var FooLUDICROUS FooSpeed = _swig_getFoo_LUDICROUS_Foo() +func _swig_wrap_Foo_enum_test(SwigcptrFoo, FooSpeed) + +func (arg1 SwigcptrFoo) Enum_test(arg2 FooSpeed) { + _swig_wrap_Foo_enum_test(arg1, arg2) +} + +func _swig_wrap_delete_Foo(uintptr) + +func DeleteFoo(arg1 Foo) { + _swig_wrap_delete_Foo(arg1.Swigcptr()) +} + +type Foo interface { + Swigcptr() uintptr + SwigIsFoo() + Enum_test(arg2 FooSpeed) +} + +func _swig_wrap_enum_test(Color, FooSpeed) + +func Enum_test(arg1 Color, arg2 FooSpeed) { + _swig_wrap_enum_test(arg1, arg2) +} + + +type SwigcptrVoid uintptr +type Void interface { + Swigcptr() uintptr; +} +func (p SwigcptrVoid) Swigcptr() uintptr { + return uintptr(p) +} + diff --git a/Examples/go/enum/example.h b/Examples/go/enum/example.h new file mode 100644 index 000000000..9119cd9fc --- /dev/null +++ b/Examples/go/enum/example.h @@ -0,0 +1,13 @@ +/* File : example.h */ + +enum color { RED, BLUE, GREEN }; + +class Foo { + public: + Foo() { } + enum speed { IMPULSE=10, WARP=20, LUDICROUS=30 }; + void enum_test(speed s); +}; + +void enum_test(color c, Foo::speed s); + diff --git a/Examples/go/enum/example.i b/Examples/go/enum/example.i new file mode 100644 index 000000000..23ee8a822 --- /dev/null +++ b/Examples/go/enum/example.i @@ -0,0 +1,11 @@ +/* File : example.i */ +%module example + +%{ +#include "example.h" +%} + +/* Let's just grab the original header file here */ + +%include "example.h" + diff --git a/Examples/go/enum/index.html b/Examples/go/enum/index.html new file mode 100644 index 000000000..868efe6ad --- /dev/null +++ b/Examples/go/enum/index.html @@ -0,0 +1,42 @@ + + +SWIG:Examples:go:enum + + + + + +SWIG/Examples/go/enum/ +
    + +

    Wrapping enumerations

    + +

    +This example tests SWIG's ability to wrap enumerations. +

      +
    • +Enum values are expressed as constants or variables in GO. +
    • +If the enum is named, then that name, capitalized, as defined as a new +type name for int. All the enum values will be defined to +have that type. +
    • +If the enum is declared at global level, then the name in Go is simply +the enum value, capitalized. +
    • +If the enum is declared within a C++ class or struct, then the name in +Go is the capitalized name of the class or struct followed by the +capitalized name of the enum value. +
    • +
    + +

    +

    + +
    + + diff --git a/Examples/go/enum/runme.go b/Examples/go/enum/runme.go new file mode 100644 index 000000000..419df5f93 --- /dev/null +++ b/Examples/go/enum/runme.go @@ -0,0 +1,32 @@ +package main + +import ( + "fmt" + . "./example" +) + +func main() { + // Print out the value of some enums + fmt.Println("*** color ***") + fmt.Println(" RED = ", RED) + fmt.Println(" BLUE = ", BLUE) + fmt.Println(" GREEN = ", GREEN) + + fmt.Println("\n*** Foo::speed ***") + fmt.Println(" Foo::IMPULSE = ", FooIMPULSE) + fmt.Println(" Foo::WARP = ", FooWARP) + fmt.Println(" Foo::LUDICROUS = ", FooLUDICROUS) + + fmt.Println("\nTesting use of enums with functions\n") + + Enum_test(RED, FooIMPULSE) + Enum_test(BLUE, FooWARP) + Enum_test(GREEN, FooLUDICROUS) + + fmt.Println("\nTesting use of enum with class method") + f := NewFoo() + + f.Enum_test(FooIMPULSE) + f.Enum_test(FooWARP) + f.Enum_test(FooLUDICROUS) +} diff --git a/Examples/go/extend/Makefile b/Examples/go/extend/Makefile new file mode 100644 index 000000000..9dc8b8851 --- /dev/null +++ b/Examples/go/extend/Makefile @@ -0,0 +1,18 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +CXXSRCS = example.cxx +TARGET = example +INTERFACE = example.i +SWIGOPT = + +all:: go + +go:: + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go_cpp + +clean:: + $(MAKE) -f $(TOP)/Makefile go_clean + +check: all + $(MAKE) -f $(TOP)/Makefile TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go_run diff --git a/Examples/go/extend/example.cxx b/Examples/go/extend/example.cxx new file mode 100644 index 000000000..450d75608 --- /dev/null +++ b/Examples/go/extend/example.cxx @@ -0,0 +1,4 @@ +/* File : example.cxx */ + +#include "example.h" + diff --git a/Examples/go/extend/example.go b/Examples/go/extend/example.go new file mode 100644 index 000000000..08f21e6ab --- /dev/null +++ b/Examples/go/extend/example.go @@ -0,0 +1,397 @@ +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 2.0.1 + * + * This file is not intended to be easily readable and contains a number of + * coding conventions designed to improve portability and efficiency. Do not make + * changes to this file unless you know what you are doing--modify the SWIG + * interface file instead. + * ----------------------------------------------------------------------------- */ + +package example + + +type _swig_fnptr *byte +type _swig_memberptr *byte + + +func _swig_allocatememory(int) *byte +func _swig_internal_allocate(len int) *byte { + return _swig_allocatememory(len) +} + +func _swig_allocatestring(*byte, int) string +func _swig_internal_makegostring(p *byte, l int) string { + return _swig_allocatestring(p, l) +} + +func _swig_internal_gopanic(p *byte, l int) { + panic(_swig_allocatestring(p, l)) +} + +type _swig_DirectorEmployee struct { + SwigcptrEmployee + v interface{} +} + +func (p *_swig_DirectorEmployee) Swigcptr() uintptr { + return p.SwigcptrEmployee.Swigcptr() +} + +func (p *_swig_DirectorEmployee) SwigIsEmployee() { +} + +func (p *_swig_DirectorEmployee) DirectorInterface() interface{} { + return p.v +} + +func _swig_NewDirectorEmployeeEmployee(*_swig_DirectorEmployee, string) SwigcptrEmployee + +func NewDirectorEmployee(v interface{}, arg1 string) Employee { + p := &_swig_DirectorEmployee{0, v} + p.SwigcptrEmployee = _swig_NewDirectorEmployeeEmployee(p, arg1) + return p +} + +type _swig_DirectorInterfaceEmployeeGetTitle interface { + GetTitle() string +} + +func _swig_wrap__swig_DirectorEmployee_upcall_GetTitle(SwigcptrEmployee) string +func (swig_p *_swig_DirectorEmployee) GetTitle() string { + if swig_g, swig_ok := swig_p.v.(_swig_DirectorInterfaceEmployeeGetTitle); swig_ok { + return swig_g.GetTitle() + } + return _swig_wrap__swig_DirectorEmployee_upcall_GetTitle(swig_p.SwigcptrEmployee) +} + +func DirectorEmployeeGetTitle(p Employee) string { + return _swig_wrap__swig_DirectorEmployee_upcall_GetTitle(p.(*_swig_DirectorEmployee).SwigcptrEmployee) +} + +func Swig_DirectorEmployee_callback_getTitle(p *_swig_DirectorEmployee) (swig_result string) { + return p.GetTitle() +} + +type _swig_DirectorInterfaceEmployeeGetName interface { + GetName() string +} + +func _swig_wrap__swig_DirectorEmployee_upcall_GetName(SwigcptrEmployee) string +func (swig_p *_swig_DirectorEmployee) GetName() string { + if swig_g, swig_ok := swig_p.v.(_swig_DirectorInterfaceEmployeeGetName); swig_ok { + return swig_g.GetName() + } + return _swig_wrap__swig_DirectorEmployee_upcall_GetName(swig_p.SwigcptrEmployee) +} + +func DirectorEmployeeGetName(p Employee) string { + return _swig_wrap__swig_DirectorEmployee_upcall_GetName(p.(*_swig_DirectorEmployee).SwigcptrEmployee) +} + +func Swig_DirectorEmployee_callback_getName(p *_swig_DirectorEmployee) (swig_result string) { + return p.GetName() +} + +type _swig_DirectorInterfaceEmployeeGetPosition interface { + GetPosition() string +} + +func _swig_wrap__swig_DirectorEmployee_upcall_GetPosition(SwigcptrEmployee) string +func (swig_p *_swig_DirectorEmployee) GetPosition() string { + if swig_g, swig_ok := swig_p.v.(_swig_DirectorInterfaceEmployeeGetPosition); swig_ok { + return swig_g.GetPosition() + } + return _swig_wrap__swig_DirectorEmployee_upcall_GetPosition(swig_p.SwigcptrEmployee) +} + +func DirectorEmployeeGetPosition(p Employee) string { + return _swig_wrap__swig_DirectorEmployee_upcall_GetPosition(p.(*_swig_DirectorEmployee).SwigcptrEmployee) +} + +func Swig_DirectorEmployee_callback_getPosition(p *_swig_DirectorEmployee) (swig_result string) { + return p.GetPosition() +} + +func _swig_wrap_DeleteDirectorEmployee(uintptr) + +func DeleteDirectorEmployee(arg1 Employee) { + _swig_wrap_DeleteDirectorEmployee(arg1.Swigcptr()) +} + +func Swiggo_DeleteDirector_Employee(p *_swig_DirectorEmployee) { + p.SwigcptrEmployee = 0 +} + +type SwigcptrEmployee uintptr + +func (p SwigcptrEmployee) Swigcptr() uintptr { + return (uintptr)(p) +} + +func (p SwigcptrEmployee) SwigIsEmployee() { +} + +func (p SwigcptrEmployee) DirectorInterface() interface{} { + return nil +} + +func _swig_wrap_new_Employee(string) SwigcptrEmployee + +func NewEmployee(arg1 string) Employee { + return _swig_wrap_new_Employee(arg1) +} + +func _swig_wrap_Employee_getTitle(SwigcptrEmployee) string + +func (arg1 SwigcptrEmployee) GetTitle() string { + return _swig_wrap_Employee_getTitle(arg1) +} + +func _swig_wrap_Employee_getName(SwigcptrEmployee) string + +func (arg1 SwigcptrEmployee) GetName() string { + return _swig_wrap_Employee_getName(arg1) +} + +func _swig_wrap_Employee_getPosition(SwigcptrEmployee) string + +func (arg1 SwigcptrEmployee) GetPosition() string { + return _swig_wrap_Employee_getPosition(arg1) +} + +func _swig_wrap_delete_Employee(uintptr) + +func DeleteEmployee(arg1 Employee) { + _swig_wrap_delete_Employee(arg1.Swigcptr()) +} + +type Employee interface { + Swigcptr() uintptr + SwigIsEmployee() + DirectorInterface() interface{} + GetTitle() string + GetName() string + GetPosition() string +} + +type _swig_DirectorManager struct { + SwigcptrManager + v interface{} +} + +func (p *_swig_DirectorManager) Swigcptr() uintptr { + return p.SwigcptrManager.Swigcptr() +} + +func (p *_swig_DirectorManager) SwigIsManager() { +} + +func (p *_swig_DirectorManager) DirectorInterface() interface{} { + return p.v +} + +func _swig_NewDirectorManagerManager(*_swig_DirectorManager, string) SwigcptrManager + +func NewDirectorManager(v interface{}, arg1 string) Manager { + p := &_swig_DirectorManager{0, v} + p.SwigcptrManager = _swig_NewDirectorManagerManager(p, arg1) + return p +} + +type _swig_DirectorInterfaceManagerGetTitle interface { + GetTitle() string +} + +func _swig_wrap__swig_DirectorManager_upcall_GetTitle(SwigcptrManager) string +func (swig_p *_swig_DirectorManager) GetTitle() string { + if swig_g, swig_ok := swig_p.v.(_swig_DirectorInterfaceManagerGetTitle); swig_ok { + return swig_g.GetTitle() + } + return _swig_wrap__swig_DirectorManager_upcall_GetTitle(swig_p.SwigcptrManager) +} + +func DirectorManagerGetTitle(p Manager) string { + return _swig_wrap__swig_DirectorManager_upcall_GetTitle(p.(*_swig_DirectorManager).SwigcptrManager) +} + +func Swig_DirectorManager_callback_getTitle(p *_swig_DirectorManager) (swig_result string) { + return p.GetTitle() +} + +type _swig_DirectorInterfaceManagerGetName interface { + GetName() string +} + +func _swig_wrap__swig_DirectorManager_upcall_GetName(SwigcptrManager) string +func (swig_p *_swig_DirectorManager) GetName() string { + if swig_g, swig_ok := swig_p.v.(_swig_DirectorInterfaceManagerGetName); swig_ok { + return swig_g.GetName() + } + return _swig_wrap__swig_DirectorManager_upcall_GetName(swig_p.SwigcptrManager) +} + +func DirectorManagerGetName(p Manager) string { + return _swig_wrap__swig_DirectorManager_upcall_GetName(p.(*_swig_DirectorManager).SwigcptrManager) +} + +func Swig_DirectorManager_callback_getName(p *_swig_DirectorManager) (swig_result string) { + return p.GetName() +} + +type _swig_DirectorInterfaceManagerGetPosition interface { + GetPosition() string +} + +func _swig_wrap__swig_DirectorManager_upcall_GetPosition(SwigcptrManager) string +func (swig_p *_swig_DirectorManager) GetPosition() string { + if swig_g, swig_ok := swig_p.v.(_swig_DirectorInterfaceManagerGetPosition); swig_ok { + return swig_g.GetPosition() + } + return _swig_wrap__swig_DirectorManager_upcall_GetPosition(swig_p.SwigcptrManager) +} + +func DirectorManagerGetPosition(p Manager) string { + return _swig_wrap__swig_DirectorManager_upcall_GetPosition(p.(*_swig_DirectorManager).SwigcptrManager) +} + +func Swig_DirectorManager_callback_getPosition(p *_swig_DirectorManager) (swig_result string) { + return p.GetPosition() +} + +func _swig_wrap_DeleteDirectorManager(uintptr) + +func DeleteDirectorManager(arg1 Manager) { + _swig_wrap_DeleteDirectorManager(arg1.Swigcptr()) +} + +func Swiggo_DeleteDirector_Manager(p *_swig_DirectorManager) { + p.SwigcptrManager = 0 +} + +type SwigcptrManager uintptr + +func (p SwigcptrManager) Swigcptr() uintptr { + return (uintptr)(p) +} + +func (p SwigcptrManager) SwigIsManager() { +} + +func (p SwigcptrManager) DirectorInterface() interface{} { + return nil +} + +func _swig_wrap_new_Manager(string) SwigcptrManager + +func NewManager(arg1 string) Manager { + return _swig_wrap_new_Manager(arg1) +} + +func _swig_wrap_Manager_getPosition(SwigcptrManager) string + +func (arg1 SwigcptrManager) GetPosition() string { + return _swig_wrap_Manager_getPosition(arg1) +} + +func _swig_wrap_delete_Manager(uintptr) + +func DeleteManager(arg1 Manager) { + _swig_wrap_delete_Manager(arg1.Swigcptr()) +} + +func _swig_wrap_Manager_getTitle(SwigcptrManager) string + +func (_swig_base SwigcptrManager) GetTitle() string { + return _swig_wrap_Manager_getTitle(_swig_base) +} + +func _swig_wrap_Manager_getName(SwigcptrManager) string + +func (_swig_base SwigcptrManager) GetName() string { + return _swig_wrap_Manager_getName(_swig_base) +} + +func (p SwigcptrManager) SwigIsEmployee() { +} + +func (p SwigcptrManager) SwigGetEmployee() Employee { + return SwigcptrEmployee(p.Swigcptr()) +} + +type Manager interface { + Swigcptr() uintptr + SwigIsManager() + DirectorInterface() interface{} + GetPosition() string + GetTitle() string + GetName() string + SwigIsEmployee() + SwigGetEmployee() Employee +} + +type SwigcptrEmployeeList uintptr + +func (p SwigcptrEmployeeList) Swigcptr() uintptr { + return (uintptr)(p) +} + +func (p SwigcptrEmployeeList) SwigIsEmployeeList() { +} + +func _swig_wrap_new_EmployeeList() SwigcptrEmployeeList + +func NewEmployeeList() EmployeeList { + return _swig_wrap_new_EmployeeList() +} + +func _swig_wrap_EmployeeList_addEmployee(SwigcptrEmployeeList, uintptr) + +func (arg1 SwigcptrEmployeeList) AddEmployee(arg2 Employee) { + _swig_wrap_EmployeeList_addEmployee(arg1, arg2.Swigcptr()) +} + +func _swig_wrap_EmployeeList_get_item(SwigcptrEmployeeList, int) SwigcptrEmployee + +func (arg1 SwigcptrEmployeeList) Get_item(arg2 int) Employee { + return _swig_wrap_EmployeeList_get_item(arg1, arg2) +} + +func _swig_wrap_delete_EmployeeList(uintptr) + +func DeleteEmployeeList(arg1 EmployeeList) { + _swig_wrap_delete_EmployeeList(arg1.Swigcptr()) +} + +type EmployeeList interface { + Swigcptr() uintptr + SwigIsEmployeeList() + AddEmployee(arg2 Employee) + Get_item(arg2 int) Employee +} + + +type SwigcptrSwigDirector_Manager uintptr +type SwigDirector_Manager interface { + Swigcptr() uintptr; +} +func (p SwigcptrSwigDirector_Manager) Swigcptr() uintptr { + return uintptr(p) +} + +type SwigcptrSwigDirector_Employee uintptr +type SwigDirector_Employee interface { + Swigcptr() uintptr; +} +func (p SwigcptrSwigDirector_Employee) Swigcptr() uintptr { + return uintptr(p) +} + +type SwigcptrVoid uintptr +type Void interface { + Swigcptr() uintptr; +} +func (p SwigcptrVoid) Swigcptr() uintptr { + return uintptr(p) +} + diff --git a/Examples/go/extend/example.h b/Examples/go/extend/example.h new file mode 100644 index 000000000..b27ab9711 --- /dev/null +++ b/Examples/go/extend/example.h @@ -0,0 +1,56 @@ +/* File : example.h */ + +#include +#include +#include +#include +#include + +class Employee { +private: + std::string name; +public: + Employee(const char* n): name(n) {} + virtual std::string getTitle() { return getPosition() + " " + getName(); } + virtual std::string getName() { return name; } + virtual std::string getPosition() const { return "Employee"; } + virtual ~Employee() { printf("~Employee() @ %p\n", this); } +}; + + +class Manager: public Employee { +public: + Manager(const char* n): Employee(n) {} + virtual std::string getPosition() const { return "Manager"; } +}; + + +class EmployeeList { + std::vector list; +public: + EmployeeList() { + list.push_back(new Employee("Bob")); + list.push_back(new Employee("Jane")); + list.push_back(new Manager("Ted")); + } + void addEmployee(Employee *p) { + list.push_back(p); + std::cout << "New employee added. Current employees are:" << std::endl; + std::vector::iterator i; + for (i=list.begin(); i!=list.end(); i++) { + std::cout << " " << (*i)->getTitle() << std::endl; + } + } + const Employee *get_item(int i) { + return list[i]; + } + ~EmployeeList() { + std::vector::iterator i; + std::cout << "~EmployeeList, deleting " << list.size() << " employees." << std::endl; + for (i=list.begin(); i!=list.end(); i++) { + delete *i; + } + std::cout << "~EmployeeList empty." << std::endl; + } +}; + diff --git a/Examples/go/extend/example.i b/Examples/go/extend/example.i new file mode 100644 index 000000000..c8ec32e09 --- /dev/null +++ b/Examples/go/extend/example.i @@ -0,0 +1,15 @@ +/* File : example.i */ +%module(directors="1") example +%{ +#include "example.h" +%} + +%include "std_vector.i" +%include "std_string.i" + +/* turn on director wrapping for Manager */ +%feature("director") Employee; +%feature("director") Manager; + +%include "example.h" + diff --git a/Examples/go/extend/index.html b/Examples/go/extend/index.html new file mode 100644 index 000000000..471fa9cdc --- /dev/null +++ b/Examples/go/extend/index.html @@ -0,0 +1,27 @@ + + +SWIG:Examples:go:extend + + + + + +SWIG/Examples/go/extend/ +
    + +

    Extending a simple C++ class in Go

    + +

    +This example illustrates the extending of a C++ class with cross +language polymorphism. + +

    +

    + +
    + + diff --git a/Examples/go/extend/runme.go b/Examples/go/extend/runme.go new file mode 100644 index 000000000..796c5ce68 --- /dev/null +++ b/Examples/go/extend/runme.go @@ -0,0 +1,77 @@ +// This file illustrates the cross language polymorphism using directors. + +package main + +import ( + "fmt" + . "./example" +) + +type CEO struct{} + +func (p *CEO) GetPosition() string { + return "CEO" +} + +func main() { + // Create an instance of CEO, a class derived from the Go + // proxy of the underlying C++ class. The calls to getName() + // and getPosition() are standard, the call to getTitle() uses + // the director wrappers to call CEO.getPosition(). + + e := NewDirectorManager(new(CEO), "Alice") + fmt.Println(e.GetName(), " is a ", e.GetPosition()) + fmt.Println("Just call her \"", e.GetTitle(), "\"") + fmt.Println("----------------------") + + + // Create a new EmployeeList instance. This class does not + // have a C++ director wrapper, but can be used freely with + // other classes that do. + + list := NewEmployeeList() + + // EmployeeList owns its items, so we must surrender ownership + // of objects we add. + // e.DisownMemory() + list.AddEmployee(e) + fmt.Println("----------------------") + + // Now we access the first four items in list (three are C++ + // objects that EmployeeList's constructor adds, the last is + // our CEO). The virtual methods of all these instances are + // treated the same. For items 0, 1, and 2, all methods + // resolve in C++. For item 3, our CEO, GetTitle calls + // GetPosition which resolves in Go. The call to GetPosition + // is slightly different, however, because of the overidden + // GetPosition() call, since now the object reference has been + // "laundered" by passing through EmployeeList as an + // Employee*. Previously, Go resolved the call immediately in + // CEO, but now Go thinks the object is an instance of class + // Employee. So the call passes through the Employee proxy + // class and on to the C wrappers and C++ director, eventually + // ending up back at the Java CEO implementation of + // getPosition(). The call to GetTitle() for item 3 runs the + // C++ Employee::getTitle() method, which in turn calls + // GetPosition(). This virtual method call passes down + // through the C++ director class to the Java implementation + // in CEO. All this routing takes place transparently. + + fmt.Println("(position, title) for items 0-3:") + + fmt.Println(" ", list.Get_item(0).GetPosition(), ", \"", list.Get_item(0).GetTitle(), "\"") + fmt.Println(" ", list.Get_item(1).GetPosition(), ", \"", list.Get_item(1).GetTitle(), "\"") + fmt.Println(" ", list.Get_item(2).GetPosition(), ", \"", list.Get_item(2).GetTitle(), "\"") + fmt.Println(" ", list.Get_item(3).GetPosition(), ", \"", list.Get_item(3).GetTitle(), "\"") + fmt.Println("----------------------") + + // Time to delete the EmployeeList, which will delete all the + // Employee* items it contains. The last item is our CEO, + // which gets destroyed as well. + DeleteEmployeeList(list) + fmt.Println("----------------------") + + // All done. + + fmt.Println("Go exit") +} diff --git a/Examples/go/funcptr/Makefile b/Examples/go/funcptr/Makefile new file mode 100644 index 000000000..b0aa9c970 --- /dev/null +++ b/Examples/go/funcptr/Makefile @@ -0,0 +1,18 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +SRCS = example.c +TARGET = example +INTERFACE = example.i +SWIGOPT = + +all:: go + +go:: + $(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \ + SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go + +clean:: + $(MAKE) -f $(TOP)/Makefile go_clean + +check: all + $(MAKE) -f $(TOP)/Makefile TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go_run diff --git a/Examples/go/funcptr/example.c b/Examples/go/funcptr/example.c new file mode 100644 index 000000000..5c4a3dabf --- /dev/null +++ b/Examples/go/funcptr/example.c @@ -0,0 +1,19 @@ +/* File : example.c */ + +int do_op(int a, int b, int (*op)(int,int)) { + return (*op)(a,b); +} + +int add(int a, int b) { + return a+b; +} + +int sub(int a, int b) { + return a-b; +} + +int mul(int a, int b) { + return a*b; +} + +int (*funcvar)(int,int) = add; diff --git a/Examples/go/funcptr/example.go b/Examples/go/funcptr/example.go new file mode 100644 index 000000000..b059bae8d --- /dev/null +++ b/Examples/go/funcptr/example.go @@ -0,0 +1,54 @@ +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 2.0.1 + * + * This file is not intended to be easily readable and contains a number of + * coding conventions designed to improve portability and efficiency. Do not make + * changes to this file unless you know what you are doing--modify the SWIG + * interface file instead. + * ----------------------------------------------------------------------------- */ + +package example + + +type _swig_fnptr *byte +type _swig_memberptr *byte + + +func _swig_allocatememory(int) *byte +func _swig_internal_allocate(len int) *byte { + return _swig_allocatememory(len) +} + +func _swig_allocatestring(*byte, int) string +func _swig_internal_makegostring(p *byte, l int) string { + return _swig_allocatestring(p, l) +} + +func _swig_internal_gopanic(p *byte, l int) { + panic(_swig_allocatestring(p, l)) +} + +func Do_op(int, int, _swig_fnptr) int +func _swig_getADD() _swig_fnptr +var ADD _swig_fnptr = _swig_getADD() +func _swig_getSUB() _swig_fnptr +var SUB _swig_fnptr = _swig_getSUB() +func _swig_getMUL() _swig_fnptr +var MUL _swig_fnptr = _swig_getMUL() +func _swig_wrap_funcvar_set(_swig_fnptr) + +func SetFuncvar(arg1 _swig_fnptr) { + _swig_wrap_funcvar_set(arg1) +} + +func GetFuncvar() _swig_fnptr + +type SwigcptrVoid uintptr +type Void interface { + Swigcptr() uintptr; +} +func (p SwigcptrVoid) Swigcptr() uintptr { + return uintptr(p) +} + diff --git a/Examples/go/funcptr/example.h b/Examples/go/funcptr/example.h new file mode 100644 index 000000000..9936e24fc --- /dev/null +++ b/Examples/go/funcptr/example.h @@ -0,0 +1,9 @@ +/* file: example.h */ + +extern int do_op(int,int, int (*op)(int,int)); +extern int add(int,int); +extern int sub(int,int); +extern int mul(int,int); + +extern int (*funcvar)(int,int); + diff --git a/Examples/go/funcptr/example.i b/Examples/go/funcptr/example.i new file mode 100644 index 000000000..8b3bef678 --- /dev/null +++ b/Examples/go/funcptr/example.i @@ -0,0 +1,16 @@ +/* File : example.i */ +%module example +%{ +#include "example.h" +%} + +/* Wrap a function taking a pointer to a function */ +extern int do_op(int a, int b, int (*op)(int, int)); + +/* Now install a bunch of "ops" as constants */ +%constant int (*ADD)(int,int) = add; +%constant int (*SUB)(int,int) = sub; +%constant int (*MUL)(int,int) = mul; + +extern int (*funcvar)(int,int); + diff --git a/Examples/go/funcptr/index.html b/Examples/go/funcptr/index.html new file mode 100644 index 000000000..4212260a9 --- /dev/null +++ b/Examples/go/funcptr/index.html @@ -0,0 +1,89 @@ + + +SWIG:Examples:go:funcptr + + + + + +SWIG/Examples/go/funcptr/ +
    + +

    Pointers to Functions

    + +

    +Okay, just what in the heck does SWIG do with a declaration like this? + +

    +
    +int do_op(int a, int b, int (*op)(int, int));
    +
    +
    + +Well, it creates a wrapper as usual. Of course, that does raise some +questions about the third argument (the pointer to a function). + +

    +In this case, SWIG will wrap the function pointer as it does for all +other pointers. However, in order to actually call this function from +a Go program, you will need to pass some kind of C function pointer +object. In C, this is easy, you just supply a function name as an +argument like this: + +

    +
    +/* Some callback function */
    +int add(int a, int b) {
    +   return a+b;
    +} 
    +...
    +int r = do_op(x,y,add);
    +
    +
    + +To make this work with SWIG, you will need to do a little extra work. +Specifically, you need to create some function pointer objects using +the %constant directive like this: + +
    +
    +%constant(int (*)(int,int)) ADD = add;
    +
    +
    + +Now, in a Go program, you would do this: + +
    +
    +int r = do_op(x,y, example.ADD)
    +
    +
    +where example is the module name. + +

    An Example

    + +Here are some files that illustrate this with a simple example: + + + +

    Notes

    + +
      +
    • The value of a function pointer must correspond to a function +written in C or C++. It is not possible to pass an arbitrary Go +function in as a substitute for a C function pointer. + +
    + +
    + + + + + + diff --git a/Examples/go/funcptr/runme.go b/Examples/go/funcptr/runme.go new file mode 100644 index 000000000..73ecbb805 --- /dev/null +++ b/Examples/go/funcptr/runme.go @@ -0,0 +1,25 @@ +package main + +import ( + "fmt" + . "./example" +) + +func main() { + a := 37 + b := 42 + + // Now call our C function with a bunch of callbacks + + fmt.Println("Trying some C callback functions") + fmt.Println(" a = ", a) + fmt.Println(" b = ", b) + fmt.Println(" ADD(a,b) = ", Do_op(a, b, ADD)) + fmt.Println(" SUB(a,b) = ", Do_op(a, b, SUB)) + fmt.Println(" MUL(a,b) = ", Do_op(a, b, MUL)) + + fmt.Println("Here is what the C callback function classes are called in Go") + fmt.Println(" ADD = ", ADD) + fmt.Println(" SUB = ", SUB) + fmt.Println(" MUL = ", MUL) +} diff --git a/Examples/go/index.html b/Examples/go/index.html new file mode 100644 index 000000000..21dda21b5 --- /dev/null +++ b/Examples/go/index.html @@ -0,0 +1,89 @@ + + +SWIG:Examples:Go + + + +

    SWIG Go Examples

    + +

    +The following examples illustrate the use of SWIG with Go. + +

      +
    • simple. A minimal example showing how SWIG can +be used to wrap a C function, a global variable, and a constant. +
    • constants. This shows how preprocessor macros and +certain C declarations are turned into constants. +
    • variables. An example showing how to access C global variables from Go. +
    • enum. Wrapping enumerations. +
    • class. Wrapping a simple C++ class. +
    • reference. C++ references. +
    • pointer. Simple pointer handling. +
    • funcptr. Pointers to functions. +
    • template. C++ templates. +
    • callback. C++ callbacks using directors. +
    • extend. Polymorphism using directors. +
    + +

    Compilation Issues

    + +
      +
    • To create a Go extension, SWIG is run with the following options: + +
      +
      +% swig -go interface.i
      +
      +
      + +
    • On Unix the compilation of examples is done using the +file Example/Makefile. This makefile performs a manual +module compilation which is platform specific. When using +the 6g or 8g compiler, the steps look like this +(GNU/Linux): + +
      +
      +% swig -go interface.i
      +% gcc -fpic -c interface_wrap.c
      +% gcc -shared interface_wrap.o $(OBJS) -o interfacemodule.so 
      +% 6g interface.go
      +% 6c interface_gc.c
      +% gopack grc interface.a interface.6 interface_gc.6
      +% 6l program.6
      +
      +
      + +
    • When using the gccgo compiler, the steps look like this: + +
      +
      +% swig -go interface.i
      +% gcc -c interface_wrap.c
      +% gccgo -c interface.go
      +% gccgo program.o interface.o interface_wrap.o
      +
      +
      + +

      Compatibility

      + +The examples have been extensively tested on the following platforms: + +
        +
      • GNU/Linux +
      + +All of the examples were last tested with the following configuration +(10 May 2010): + +
        +
      • Ubuntu Hardy +
      • gcc-4.2.4 +
      + +Your mileage may vary. If you experience a problem, please let us know by +contacting us on the mailing lists. + + diff --git a/Examples/go/multimap/Makefile b/Examples/go/multimap/Makefile new file mode 100644 index 000000000..b0aa9c970 --- /dev/null +++ b/Examples/go/multimap/Makefile @@ -0,0 +1,18 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +SRCS = example.c +TARGET = example +INTERFACE = example.i +SWIGOPT = + +all:: go + +go:: + $(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \ + SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go + +clean:: + $(MAKE) -f $(TOP)/Makefile go_clean + +check: all + $(MAKE) -f $(TOP)/Makefile TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go_run diff --git a/Examples/go/multimap/example.c b/Examples/go/multimap/example.c new file mode 100644 index 000000000..b8360fa8a --- /dev/null +++ b/Examples/go/multimap/example.c @@ -0,0 +1,53 @@ +/* File : example.c */ +#include +#include +#include + +/* Compute the greatest common divisor of positive integers */ +int gcd(int x, int y) { + int g; + g = y; + while (x > 0) { + g = x; + x = y % x; + y = g; + } + return g; +} + +int gcdmain(int argc, char *argv[]) { + int x,y; + if (argc != 3) { + printf("usage: gcd x y\n"); + return -1; + } + x = atoi(argv[1]); + y = atoi(argv[2]); + printf("gcd(%d,%d) = %d\n", x,y,gcd(x,y)); + return 0; +} + +int count(char *bytes, int len, char c) { + int i; + int count = 0; + for (i = 0; i < len; i++) { + if (bytes[i] == c) count++; + } + return count; +} + +void capitalize(char *str, int len) { + int i; + for (i = 0; i < len; i++) { + str[i] = (char)toupper(str[i]); + } +} + +void circle(double x, double y) { + double a = x*x + y*y; + if (a > 1.0) { + printf("Bad points %g, %g\n", x,y); + } else { + printf("Good points %g, %g\n", x,y); + } +} diff --git a/Examples/go/multimap/example.go b/Examples/go/multimap/example.go new file mode 100644 index 000000000..59ed9eaad --- /dev/null +++ b/Examples/go/multimap/example.go @@ -0,0 +1,55 @@ +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 2.0.1 + * + * This file is not intended to be easily readable and contains a number of + * coding conventions designed to improve portability and efficiency. Do not make + * changes to this file unless you know what you are doing--modify the SWIG + * interface file instead. + * ----------------------------------------------------------------------------- */ + +package example + + +type _swig_fnptr *byte +type _swig_memberptr *byte + + +func _swig_allocatememory(int) *byte +func _swig_internal_allocate(len int) *byte { + return _swig_allocatememory(len) +} + +func _swig_allocatestring(*byte, int) string +func _swig_internal_makegostring(p *byte, l int) string { + return _swig_allocatestring(p, l) +} + +func _swig_internal_gopanic(p *byte, l int) { + panic(_swig_allocatestring(p, l)) +} + +func Gcd(int, int) int +func Gcdmain([]string) int +func Count(string, byte) int +func _swig_wrap_capitalize([]string) + +func Capitalize(arg1 []string) { + _swig_wrap_capitalize(arg1) +} + +func _swig_wrap_circle(float64, float64) + +func Circle(arg1 float64, arg2 float64) { + _swig_wrap_circle(arg1, arg2) +} + + +type SwigcptrVoid uintptr +type Void interface { + Swigcptr() uintptr; +} +func (p SwigcptrVoid) Swigcptr() uintptr { + return uintptr(p) +} + diff --git a/Examples/go/multimap/example.i b/Examples/go/multimap/example.i new file mode 100644 index 000000000..04d6eea20 --- /dev/null +++ b/Examples/go/multimap/example.i @@ -0,0 +1,110 @@ +/* File : example.i */ +%module example + +%{ +extern int gcd(int x, int y); +extern int gcdmain(int argc, char *argv[]); +extern int count(char *bytes, int len, char c); +extern void capitalize (char *str, int len); +extern void circle (double cx, double cy); +extern int squareCubed (int n, int *OUTPUT); +%} + +extern int gcd(int x, int y); + +%typemap(go) (int argc, char *argv[]) "[]string" + +%typemap(in) (int argc, char *argv[]) +%{ + { + int i; + _gostring_* a; + + $1 = $input.len; + a = (_gostring_*) $input.array; + $2 = (char **) malloc (($1 + 1) * sizeof (char *)); + for (i = 0; i < $1; i++) { + _gostring_ *ps = &a[i]; + $2[i] = (char *) ps->p; + } + $2[i] = NULL; + } +%} + +%typemap(argout) (int argc, char *argv[]) "" /* override char *[] default */ + +%typemap(freearg) (int argc, char *argv[]) +%{ + free($2); +%} + +extern int gcdmain(int argc, char *argv[]); + +%typemap(go) (char *bytes, int len) "string" + +%typemap(in) (char *bytes, int len) +%{ + $1 = $input.p; + $2 = $input.n; +%} + +extern int count(char *bytes, int len, char c); + +/* This example shows how to wrap a function that mutates a c string. A one + * element Go string slice is used so that the string can be returned + * modified. + */ + +%typemap(go) (char *str, int len) "[]string" + +%typemap(in) (char *str, int len) +%{ + { + _gostring_ *a; + char *p; + int n; + + a = (_gostring_*) $input.array; + p = a[0].p; + n = a[0].n; + $1 = malloc(n + 1); + $2 = n; + memcpy($1, p, n); + } +%} + +/* Return the mutated string as a modified element in the array. */ +%typemap(argout) (char *str, int len) +%{ + { + _gostring_ *a; + + a = (_gostring_*) $input.array; + a[0] = _swig_makegostring($1, $2); + } +%} + +%typemap(freearg) (char *str, int len) +%{ + free($1); +%} + +extern void capitalize(char *str, int len); + +/* A multi-valued constraint. Force two arguments to lie + inside the unit circle */ + +%typemap(check) (double cx, double cy) +%{ + { + double a = $1*$1 + $2*$2; + if (a > 1.0) { + _swig_gopanic("$1_name and $2_name must be in unit circle"); + return; + } + } +%} + +extern void circle(double cx, double cy); + + diff --git a/Examples/go/multimap/runme.go b/Examples/go/multimap/runme.go new file mode 100644 index 000000000..94c29127c --- /dev/null +++ b/Examples/go/multimap/runme.go @@ -0,0 +1,26 @@ +package main + +import ( + "fmt" + . "./example" +) + +func main() { + // Call our gcd() function + x := 42 + y := 105 + g := Gcd(x, y) + fmt.Println("The gcd of ", x, " and ", y, " is ", g) + + // Call the gcdmain() function + args := []string{"gcdmain", "42", "105"} + Gcdmain(args) + + // Call the count function + fmt.Println(Count("Hello World", 'l')) + + // Call the capitalize function + capitalizeMe := []string{"hello world"} + Capitalize(capitalizeMe) + fmt.Println(capitalizeMe[0]) +} diff --git a/Examples/go/pointer/Makefile b/Examples/go/pointer/Makefile new file mode 100644 index 000000000..b0aa9c970 --- /dev/null +++ b/Examples/go/pointer/Makefile @@ -0,0 +1,18 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +SRCS = example.c +TARGET = example +INTERFACE = example.i +SWIGOPT = + +all:: go + +go:: + $(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \ + SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go + +clean:: + $(MAKE) -f $(TOP)/Makefile go_clean + +check: all + $(MAKE) -f $(TOP)/Makefile TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go_run diff --git a/Examples/go/pointer/example.c b/Examples/go/pointer/example.c new file mode 100644 index 000000000..b877d9a5b --- /dev/null +++ b/Examples/go/pointer/example.c @@ -0,0 +1,16 @@ +/* File : example.c */ + +void add(int *x, int *y, int *result) { + *result = *x + *y; +} + +void sub(int *x, int *y, int *result) { + *result = *x - *y; +} + +int divide(int n, int d, int *r) { + int q; + q = n/d; + *r = n - q*d; + return q; +} diff --git a/Examples/go/pointer/example.go b/Examples/go/pointer/example.go new file mode 100644 index 000000000..567c41c32 --- /dev/null +++ b/Examples/go/pointer/example.go @@ -0,0 +1,68 @@ +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 2.0.1 + * + * This file is not intended to be easily readable and contains a number of + * coding conventions designed to improve portability and efficiency. Do not make + * changes to this file unless you know what you are doing--modify the SWIG + * interface file instead. + * ----------------------------------------------------------------------------- */ + +package example + + +type _swig_fnptr *byte +type _swig_memberptr *byte + + +func _swig_allocatememory(int) *byte +func _swig_internal_allocate(len int) *byte { + return _swig_allocatememory(len) +} + +func _swig_allocatestring(*byte, int) string +func _swig_internal_makegostring(p *byte, l int) string { + return _swig_allocatestring(p, l) +} + +func _swig_internal_gopanic(p *byte, l int) { + panic(_swig_allocatestring(p, l)) +} + +func _swig_wrap_add(*int, *int, *int) + +func Add(arg1 *int, arg2 *int, arg3 *int) { + _swig_wrap_add(arg1, arg2, arg3) +} + +func New_intp() *int +func Copy_intp(int) *int +func _swig_wrap_delete_intp(*int) + +func Delete_intp(arg1 *int) { + _swig_wrap_delete_intp(arg1) +} + +func _swig_wrap_intp_assign(*int, int) + +func Intp_assign(arg1 *int, arg2 int) { + _swig_wrap_intp_assign(arg1, arg2) +} + +func Intp_value(*int) int +func _swig_wrap_sub(int, int, []int) + +func Sub(arg1 int, arg2 int, arg3 []int) { + _swig_wrap_sub(arg1, arg2, arg3) +} + +func Divide(int, int, []int) int + +type SwigcptrVoid uintptr +type Void interface { + Swigcptr() uintptr; +} +func (p SwigcptrVoid) Swigcptr() uintptr { + return uintptr(p) +} + diff --git a/Examples/go/pointer/example.i b/Examples/go/pointer/example.i new file mode 100644 index 000000000..a8ac79499 --- /dev/null +++ b/Examples/go/pointer/example.i @@ -0,0 +1,30 @@ +/* File : example.i */ +%module example + +%{ +extern void add(int *, int *, int *); +extern void sub(int *, int *, int *); +extern int divide(int, int, int *); +%} + +/* This example illustrates a couple of different techniques + for manipulating C pointers */ + +/* First we'll use the pointer library */ +extern void add(int *x, int *y, int *result); +%include cpointer.i +%pointer_functions(int, intp); + +/* Next we'll use some typemaps */ + +%include typemaps.i +extern void sub(int *INPUT, int *INPUT, int *OUTPUT); + +/* Next we'll use typemaps and the %apply directive */ + +%apply int *OUTPUT { int *r }; +extern int divide(int n, int d, int *r); + + + + diff --git a/Examples/go/pointer/index.html b/Examples/go/pointer/index.html new file mode 100644 index 000000000..cfa8a3acc --- /dev/null +++ b/Examples/go/pointer/index.html @@ -0,0 +1,143 @@ + + +SWIG:Examples:go:pointer + + + + +SWIG/Examples/go/pointer/ +
      + +

      Simple Pointer Handling

      + +

      +This example illustrates a couple of techniques for handling simple +pointers in SWIG. The prototypical example is a C function that +operates on pointers such as this: + +

      +
      +void add(int *x, int *y, int *r) { 
      +    *r = *x + *y;
      +}
      +
      +
      + +By default, SWIG wraps this function exactly as specified and creates +an interface that expects pointer objects for arguments. This only +works when there is a precise correspondence between the C type and +some Go type. +

      + +

      Other approaches

      + +

      +

    • The SWIG pointer library provides a different, safer, way to + handle pointers. For example, in the interface file you would do + this: + +
      +
      +%include cpointer.i
      +%pointer_functions(int, intp);
      +
      +
      + +and from Go you would use pointers like this: + +
      +
      +a := example.New_intp()
      +b := example.New_intp()
      +c := example.New_intp()
      +Intp_Assign(a, 37)
      +Intp_Assign(b, 42)
      +
      +fmt.Println("     a =", a)
      +fmt.Println("     b =", b)
      +fmt.Println("     c =", c)
      +
      +// Call the add() function with some pointers
      +example.Add(a,b,c)
      +
      +// Now get the result
      +res := example.Intp_value(c)
      +fmt.Println("     37 + 42 =", res)
      +
      +// Clean up the pointers
      +example.Delete_intp(a)
      +example.Delete_intp(b)
      +example.Delete_intp(c)
      +
      +
      + +

      +

    • Use the SWIG typemap library. This library allows you to +completely change the way arguments are processed by SWIG. For +example: + +
      +
      +%include "typemaps.i"
      +void add(int *INPUT, int *INPUT, int *OUTPUT);
      +
      +
      + +And in a Go program: + +
      +
      +r := []int{0}
      +example.Sub(37,42,r)
      +fmt.Println("Result =", r[0])
      +
      +
      +Needless to say, this is substantially easier although a bit unusual. + +

      +

    • A final alternative is to use the typemaps library in combination +with the %apply directive. This allows you to change the names of parameters +that behave as input or output parameters. For example: + +
      +
      +%include "typemaps.i"
      +%apply int *INPUT {int *x, int *y};
      +%apply int *OUTPUT {int *r};
      +
      +void add(int *x, int *y, int *r);
      +void sub(int *x, int *y, int *r);
      +void mul(int *x, int *y, int *r);
      +... etc ...
      +
      +
      + +
    + +

    Example

    + +The following example illustrates the use of these features for pointer +extraction. + + + +

    Notes

    + +
      +
    • Since pointers are used for so many different things (arrays, output values, +etc...) the complexity of pointer handling can be as complicated as you want to +make it. + +

      +

    • More documentation on the typemaps.i and cpointer.i library files can be +found in the SWIG user manual. The files also contain documentation. + +
    + +
    + + diff --git a/Examples/go/pointer/runme.go b/Examples/go/pointer/runme.go new file mode 100644 index 000000000..9cbcda489 --- /dev/null +++ b/Examples/go/pointer/runme.go @@ -0,0 +1,47 @@ +package main + +import ( + "fmt" + . "./example" +) + +func main() { + // First create some objects using the pointer library. + fmt.Println("Testing the pointer library") + a := New_intp() + b := New_intp() + c := New_intp() + Intp_assign(a, 37) + Intp_assign(b, 42) + + fmt.Println(" a =", a) + fmt.Println(" b =", b) + fmt.Println(" c =", c) + + // Call the add() function with some pointers + Add(a, b, c) + + // Now get the result + res := Intp_value(c) + fmt.Println(" 37 + 42 =", res) + + // Clean up the pointers + Delete_intp(a) + Delete_intp(b) + Delete_intp(c) + + // Now try the typemap library + // Now it is no longer necessary to manufacture pointers. + // Instead we use a single element array which in Java is modifiable. + + fmt.Println("Trying the typemap library") + r := []int{0} + Sub(37, 42, r) + fmt.Println(" 37 - 42 = ", r[0]) + + // Now try the version with return value + + fmt.Println("Testing return value") + q := Divide(42, 37, r) + fmt.Println(" 42/37 = ", q, " remainder ", r[0]) +} diff --git a/Examples/go/reference/Makefile b/Examples/go/reference/Makefile new file mode 100644 index 000000000..9dc8b8851 --- /dev/null +++ b/Examples/go/reference/Makefile @@ -0,0 +1,18 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +CXXSRCS = example.cxx +TARGET = example +INTERFACE = example.i +SWIGOPT = + +all:: go + +go:: + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go_cpp + +clean:: + $(MAKE) -f $(TOP)/Makefile go_clean + +check: all + $(MAKE) -f $(TOP)/Makefile TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go_run diff --git a/Examples/go/reference/example.cxx b/Examples/go/reference/example.cxx new file mode 100644 index 000000000..8a513bf49 --- /dev/null +++ b/Examples/go/reference/example.cxx @@ -0,0 +1,46 @@ +/* File : example.cxx */ + +/* Deal with Microsoft's attempt at deprecating C standard runtime functions */ +#if !defined(SWIG_NO_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) +# define _CRT_SECURE_NO_DEPRECATE +#endif + +#include "example.h" +#include +#include + +Vector operator+(const Vector &a, const Vector &b) { + Vector r; + r.x = a.x + b.x; + r.y = a.y + b.y; + r.z = a.z + b.z; + return r; +} + +char *Vector::print() { + static char temp[512]; + sprintf(temp,"Vector %p (%g,%g,%g)", this, x,y,z); + return temp; +} + +VectorArray::VectorArray(int size) { + items = new Vector[size]; + maxsize = size; +} + +VectorArray::~VectorArray() { + delete [] items; +} + +Vector &VectorArray::operator[](int index) { + if ((index < 0) || (index >= maxsize)) { + printf("Panic! Array index out of bounds.\n"); + exit(1); + } + return items[index]; +} + +int VectorArray::size() { + return maxsize; +} + diff --git a/Examples/go/reference/example.go b/Examples/go/reference/example.go new file mode 100644 index 000000000..fb98f8a18 --- /dev/null +++ b/Examples/go/reference/example.go @@ -0,0 +1,126 @@ +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 2.0.1 + * + * This file is not intended to be easily readable and contains a number of + * coding conventions designed to improve portability and efficiency. Do not make + * changes to this file unless you know what you are doing--modify the SWIG + * interface file instead. + * ----------------------------------------------------------------------------- */ + +package example + + +type _swig_fnptr *byte +type _swig_memberptr *byte + + +func _swig_allocatememory(int) *byte +func _swig_internal_allocate(len int) *byte { + return _swig_allocatememory(len) +} + +func _swig_allocatestring(*byte, int) string +func _swig_internal_makegostring(p *byte, l int) string { + return _swig_allocatestring(p, l) +} + +func _swig_internal_gopanic(p *byte, l int) { + panic(_swig_allocatestring(p, l)) +} + +type SwigcptrVector uintptr + +func (p SwigcptrVector) Swigcptr() uintptr { + return (uintptr)(p) +} + +func (p SwigcptrVector) SwigIsVector() { +} + +func _swig_wrap_new_Vector(float64, float64, float64) SwigcptrVector + +func NewVector(arg1 float64, arg2 float64, arg3 float64) Vector { + return _swig_wrap_new_Vector(arg1, arg2, arg3) +} + +func _swig_wrap_delete_Vector(uintptr) + +func DeleteVector(arg1 Vector) { + _swig_wrap_delete_Vector(arg1.Swigcptr()) +} + +func _swig_wrap_Vector_print(SwigcptrVector) string + +func (arg1 SwigcptrVector) Print() string { + return _swig_wrap_Vector_print(arg1) +} + +type Vector interface { + Swigcptr() uintptr + SwigIsVector() + Print() string +} + +func _swig_wrap_addv(uintptr, uintptr) SwigcptrVector + +func Addv(arg1 Vector, arg2 Vector) Vector { + return _swig_wrap_addv(arg1.Swigcptr(), arg2.Swigcptr()) +} + +type SwigcptrVectorArray uintptr + +func (p SwigcptrVectorArray) Swigcptr() uintptr { + return (uintptr)(p) +} + +func (p SwigcptrVectorArray) SwigIsVectorArray() { +} + +func _swig_wrap_new_VectorArray(int) SwigcptrVectorArray + +func NewVectorArray(arg1 int) VectorArray { + return _swig_wrap_new_VectorArray(arg1) +} + +func _swig_wrap_delete_VectorArray(uintptr) + +func DeleteVectorArray(arg1 VectorArray) { + _swig_wrap_delete_VectorArray(arg1.Swigcptr()) +} + +func _swig_wrap_VectorArray_size(SwigcptrVectorArray) int + +func (arg1 SwigcptrVectorArray) Size() int { + return _swig_wrap_VectorArray_size(arg1) +} + +func _swig_wrap_VectorArray_get(SwigcptrVectorArray, int) SwigcptrVector + +func (arg1 SwigcptrVectorArray) Get(arg2 int) Vector { + return _swig_wrap_VectorArray_get(arg1, arg2) +} + +func _swig_wrap_VectorArray_set(SwigcptrVectorArray, int, uintptr) + +func (arg1 SwigcptrVectorArray) Set(arg2 int, arg3 Vector) { + _swig_wrap_VectorArray_set(arg1, arg2, arg3.Swigcptr()) +} + +type VectorArray interface { + Swigcptr() uintptr + SwigIsVectorArray() + Size() int + Get(arg2 int) Vector + Set(arg2 int, arg3 Vector) +} + + +type SwigcptrVoid uintptr +type Void interface { + Swigcptr() uintptr; +} +func (p SwigcptrVoid) Swigcptr() uintptr { + return uintptr(p) +} + diff --git a/Examples/go/reference/example.h b/Examples/go/reference/example.h new file mode 100644 index 000000000..4915adb1b --- /dev/null +++ b/Examples/go/reference/example.h @@ -0,0 +1,26 @@ +/* File : example.h */ + +class Vector { +private: + double x,y,z; +public: + Vector() : x(0), y(0), z(0) { }; + Vector(double x, double y, double z) : x(x), y(y), z(z) { }; + friend Vector operator+(const Vector &a, const Vector &b); + char *print(); +}; + +class VectorArray { +private: + Vector *items; + int maxsize; +public: + VectorArray(int maxsize); + ~VectorArray(); + Vector &operator[](int); + int size(); +}; + + + + diff --git a/Examples/go/reference/example.i b/Examples/go/reference/example.i new file mode 100644 index 000000000..1cf19c82c --- /dev/null +++ b/Examples/go/reference/example.i @@ -0,0 +1,42 @@ +/* File : example.i */ + +/* This file has a few "typical" uses of C++ references. */ + +%module example + +%{ +#include "example.h" +%} + +class Vector { +public: + Vector(double x, double y, double z); + ~Vector(); + char *print(); +}; + +/* This helper function calls an overloaded operator */ +%inline %{ +Vector addv(Vector &a, Vector &b) { + return a+b; +} +%} + +/* Wrapper around an array of vectors class */ + +class VectorArray { +public: + VectorArray(int maxsize); + ~VectorArray(); + int size(); + + /* This wrapper provides an alternative to the [] operator */ + %extend { + Vector &get(int index) { + return (*$self)[index]; + } + void set(int index, Vector &a) { + (*$self)[index] = a; + } + } +}; diff --git a/Examples/go/reference/index.html b/Examples/go/reference/index.html new file mode 100644 index 000000000..5e8589349 --- /dev/null +++ b/Examples/go/reference/index.html @@ -0,0 +1,143 @@ + + +SWIG:Examples:go:reference + + + + + +SWIG/Examples/go/reference/ +
    + +

    C++ Reference Handling

    + +

    +This example tests SWIG's handling of C++ references. A reference in +C++ is much like a pointer. Go represents C++ classes as pointers +which are stored in interface values. Therefore, a reference to a +class in C++ simply becomes an object of the class type in Go. For +types which are not classes, a reference in C++ is represented as a +pointer in Go. + +

    Some examples

    + +References are most commonly used as function parameters. For +example, you might have a function like this: + +
    +
    +Vector addv(const Vector &a, const Vector &b) {
    +   Vector result;
    +   result.x = a.x + b.x;
    +   result.y = a.y + b.y;
    +   result.z = a.z + b.z;
    +   return result;
    +}
    +
    +
    + +In these cases, SWIG transforms everything into a pointer and creates +a wrapper that looks like this in C++. + +
    +
    +Vector wrap_addv(Vector *a, Vector *b);
    +
    +
    + +or like this in Go: + +
    +
    +func Addv(arg1 Vector, arg2 Vector) Vector
    +
    +
    + +Occasionally, a reference is used as a return value of a function +when the return result is to be used as an lvalue in an expression. +The prototypical example is an operator like this: + +
    +
    +Vector &operator[](int index);
    +
    +
    + +or a method: + +
    +
    +Vector &get(int index);
    +
    +
    + +For functions returning references, a wrapper like this is created: + +
    +
    +Vector *wrap_Object_get(Object *self, int index) {
    +    Vector &result = self->get(index);
    +    return &result;
    +}
    +
    +
    + +The following header file contains some class +definitions with some operators and use of references. + +

    SWIG Interface

    + +SWIG does NOT support overloaded operators so it can not directly +build an interface to the classes in the above file. However, a +number of workarounds can be made. For example, an overloaded +operator can be stuck behind a function call such as the addv +function above. Array access can be handled with a pair of set/get +functions like this: + +
    +
    +class VectorArray {
    +public:
    + ...
    +   %addmethods {
    +    Vector &get(int index) {
    +      return (*self)[index];
    +    }
    +    void set(int index, Vector &a) {
    +      (*self)[index] = a;
    +    }
    +   }
    +   ...
    +}
    +
    +
    + +Click here to see a SWIG interface file with +these additions. + +

    Sample Go program

    + +Click here to see a Go program that manipulates +some C++ references. + +

    Notes:

    + +
      +
    • C++ references primarily provide notational convenience for C++ +source code. However, Go only supports the 'x.a' notation so it +doesn't much matter. + +

      +

    • When a program returns a reference, a pointer is returned. Unlike +return by value, memory is not allocated to hold the return result. + +

      +

    • SWIG has particular trouble handling various combinations of +references and pointers. This is side effect of an old parsing scheme +and type representation that will be replaced in future versions. + +
    + +
    + + diff --git a/Examples/go/reference/runme.go b/Examples/go/reference/runme.go new file mode 100644 index 000000000..3683d6144 --- /dev/null +++ b/Examples/go/reference/runme.go @@ -0,0 +1,71 @@ +// This example illustrates the manipulation of C++ references in Java. + +package main + +import ( + "fmt" + . "./example" +) + +func main() { + fmt.Println("Creating some objects:") + a := NewVector(3, 4, 5) + b := NewVector(10, 11, 12) + + fmt.Println(" Created ", a.Print()) + fmt.Println(" Created ", b.Print()) + + // ----- Call an overloaded operator ----- + + // This calls the wrapper we placed around + // + // operator+(const Vector &a, const Vector &) + // + // It returns a new allocated object. + + fmt.Println("Adding a+b") + c := Addv(a, b) + fmt.Println(" a+b = " + c.Print()) + + // Because addv returns a reference, Addv will return a + // pointer allocated using Go's memory allocator. That means + // that it will be freed by Go's garbage collector, and we can + // not use DeleteVector to release it. + + c = nil + + // ----- Create a vector array ----- + + fmt.Println("Creating an array of vectors") + va := NewVectorArray(10) + fmt.Println(" va = ", va) + + // ----- Set some values in the array ----- + + // These operators copy the value of Vector a and Vector b to + // the vector array + va.Set(0, a) + va.Set(1, b) + + va.Set(2, Addv(a, b)) + + // Get some values from the array + + fmt.Println("Getting some array values") + for i := 0; i < 5; i++ { + fmt.Println(" va(", i, ") = ", va.Get(i).Print()) + } + + // Watch under resource meter to check on this + fmt.Println("Making sure we don't leak memory.") + for i := 0; i < 1000000; i++ { + c = va.Get(i % 10) + } + + // ----- Clean up ----- This could be omitted. The garbage + // collector would then clean up for us. + fmt.Println("Cleaning up") + DeleteVectorArray(va) + DeleteVector(a) + DeleteVector(b) +} diff --git a/Examples/go/simple/Makefile b/Examples/go/simple/Makefile new file mode 100644 index 000000000..e67fa8bb6 --- /dev/null +++ b/Examples/go/simple/Makefile @@ -0,0 +1,15 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +SRCS = example.c +TARGET = example +INTERFACE = example.i + +all:: + $(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \ + TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go + +clean:: + $(MAKE) -f $(TOP)/Makefile go_clean + +check: all + $(MAKE) -f $(TOP)/Makefile TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go_run diff --git a/Examples/go/simple/example.c b/Examples/go/simple/example.c new file mode 100644 index 000000000..1c2af789c --- /dev/null +++ b/Examples/go/simple/example.c @@ -0,0 +1,18 @@ +/* File : example.c */ + +/* A global variable */ +double Foo = 3.0; + +/* Compute the greatest common divisor of positive integers */ +int gcd(int x, int y) { + int g; + g = y; + while (x > 0) { + g = x; + x = y % x; + y = g; + } + return g; +} + + diff --git a/Examples/go/simple/example.go b/Examples/go/simple/example.go new file mode 100644 index 000000000..df0e70564 --- /dev/null +++ b/Examples/go/simple/example.go @@ -0,0 +1,48 @@ +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 2.0.1 + * + * This file is not intended to be easily readable and contains a number of + * coding conventions designed to improve portability and efficiency. Do not make + * changes to this file unless you know what you are doing--modify the SWIG + * interface file instead. + * ----------------------------------------------------------------------------- */ + +package example + + +type _swig_fnptr *byte +type _swig_memberptr *byte + + +func _swig_allocatememory(int) *byte +func _swig_internal_allocate(len int) *byte { + return _swig_allocatememory(len) +} + +func _swig_allocatestring(*byte, int) string +func _swig_internal_makegostring(p *byte, l int) string { + return _swig_allocatestring(p, l) +} + +func _swig_internal_gopanic(p *byte, l int) { + panic(_swig_allocatestring(p, l)) +} + +func Gcd(int, int) int +func _swig_wrap_Foo_set(float64) + +func SetFoo(arg1 float64) { + _swig_wrap_Foo_set(arg1) +} + +func GetFoo() float64 + +type SwigcptrVoid uintptr +type Void interface { + Swigcptr() uintptr; +} +func (p SwigcptrVoid) Swigcptr() uintptr { + return uintptr(p) +} + diff --git a/Examples/go/simple/example.i b/Examples/go/simple/example.i new file mode 100644 index 000000000..24093b9bf --- /dev/null +++ b/Examples/go/simple/example.i @@ -0,0 +1,7 @@ +/* File : example.i */ +%module example + +%inline %{ +extern int gcd(int x, int y); +extern double Foo; +%} diff --git a/Examples/go/simple/index.html b/Examples/go/simple/index.html new file mode 100644 index 000000000..82372ef37 --- /dev/null +++ b/Examples/go/simple/index.html @@ -0,0 +1,126 @@ + + +SWIG:Examples:go:simple + + + + + +SWIG/Examples/go/simple/ +
    + +

    Simple Go Example

    + +

    +This example illustrates how you can hook Go to a very simple C program containing +a function and a global variable. + +

    The C Code

    + +Suppose you have the following C code: + +
    +
    +/* File : example.c */
    +
    +/* A global variable */
    +double Foo = 3.0;
    +
    +/* Compute the greatest common divisor of positive integers */
    +int gcd(int x, int y) {
    +  int g;
    +  g = y;
    +  while (x > 0) {
    +    g = x;
    +    x = y % x;
    +    y = g;
    +  }
    +  return g;
    +}
    +
    +
    + +

    The SWIG interface

    + +Here is a simple SWIG interface file: + +
    +
    +/* File: example.i */
    +%module example
    +
    +extern int gcd(int x, int y);
    +extern double Foo;
    +
    +
    + +

    Compilation

    + +These are the instructions if you are using 6g/8g +rather than gccgo. + +
      +
    1. Run swig -go example.i. This + will create the three + files example.go, example_gc.c, + and example_wrap.c. +
    2. Compile example.go + using 6g or 8g; e.g., 6g example.go. +
    3. Compile example_gc.c + using 6c or 8c; e.g., 6c example_gc.c. +
    4. Put the two object files together into an archive + named example.a; e.g., gopack grc example.a example.6 + example_gc.6. +
    5. Compile the example_wrap.c + file using your standard C compiler with the -fpic option; + e.g., gcc -c -O -fpic example_wrap.c. +
    6. Put the gcc compiled object file into a shared library; + e.g., gcc -shared -o example.so example_wrap.o. +
    7. Compile the program which demonstrates how to use the library; + e.g., 6g runme.go. +
    8. Link the program; e.g., 6l -o runme runme.6. +
    9. Now you should have a program runme. +
    + +

    Using the extension

    + +The Go program which demonstrates calling the C functions from Go +is runme.go. + +

    Key points

    + +
      +
    • Use the import statement to load your extension module from Go. For example: +
      +
      +import "example"
      +
      +
      + +
    • C functions work just like Go functions. However, the function + names are automatically capitalized in order to make the names + visible from other Go packages. For example: +
      +
      +g := example.Gcd(42,105)
      +
      +
      + +(If there are name conflicts, you can use the %rename +directive in the .i file or the -rename option to Go to +rename one or the other symbol). + +
    • C global variables are accessed using getter and setter + functions. The getter function is named Get followed by + the capitalized name of the C variable. The Setter function + uses Set instead of Get. +
      +
      +a = example.GetFoo()
      +
      +
      +
    + +
    + + diff --git a/Examples/go/simple/runme.go b/Examples/go/simple/runme.go new file mode 100644 index 000000000..c829ad21a --- /dev/null +++ b/Examples/go/simple/runme.go @@ -0,0 +1,25 @@ +package main + +import ( + "fmt" + "./example" +) + +func main() { + // Call our gcd() function + x := 42 + y := 105 + g := example.Gcd(x, y) + fmt.Println("The gcd of", x, "and", y, "is", g) + + // Manipulate the Foo global variable + + // Output its current value + fmt.Println("Foo =", example.GetFoo()) + + // Change its value + example.SetFoo(3.1415926) + + // See if the change took effect + fmt.Println("Foo =", example.GetFoo()) +} diff --git a/Examples/go/template/Makefile b/Examples/go/template/Makefile new file mode 100644 index 000000000..b9278b53e --- /dev/null +++ b/Examples/go/template/Makefile @@ -0,0 +1,18 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +CXXSRCS = +TARGET = example +INTERFACE = example.i +SWIGOPT = + +all:: go + +go:: + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go_cpp + +clean:: + $(MAKE) -f $(TOP)/Makefile go_clean + +check: all + $(MAKE) -f $(TOP)/Makefile TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go_run diff --git a/Examples/go/template/example.go b/Examples/go/template/example.go new file mode 100644 index 000000000..671b5c2ba --- /dev/null +++ b/Examples/go/template/example.go @@ -0,0 +1,150 @@ +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 2.0.1 + * + * This file is not intended to be easily readable and contains a number of + * coding conventions designed to improve portability and efficiency. Do not make + * changes to this file unless you know what you are doing--modify the SWIG + * interface file instead. + * ----------------------------------------------------------------------------- */ + +package example + + +type _swig_fnptr *byte +type _swig_memberptr *byte + + +func _swig_allocatememory(int) *byte +func _swig_internal_allocate(len int) *byte { + return _swig_allocatememory(len) +} + +func _swig_allocatestring(*byte, int) string +func _swig_internal_makegostring(p *byte, l int) string { + return _swig_allocatestring(p, l) +} + +func _swig_internal_gopanic(p *byte, l int) { + panic(_swig_allocatestring(p, l)) +} + +func Maxint(int, int) int +func Maxdouble(float64, float64) float64 +type SwigcptrVecint uintptr + +func (p SwigcptrVecint) Swigcptr() uintptr { + return (uintptr)(p) +} + +func (p SwigcptrVecint) SwigIsVecint() { +} + +func _swig_wrap_new_vecint(int) SwigcptrVecint + +func NewVecint(arg1 int) Vecint { + return _swig_wrap_new_vecint(arg1) +} + +func _swig_wrap_vecint_get(SwigcptrVecint, int) *int + +func (arg1 SwigcptrVecint) Get(arg2 int) *int { + return _swig_wrap_vecint_get(arg1, arg2) +} + +func _swig_wrap_vecint_set(SwigcptrVecint, int, *int) + +func (arg1 SwigcptrVecint) Set(arg2 int, arg3 *int) { + _swig_wrap_vecint_set(arg1, arg2, arg3) +} + +func _swig_wrap_vecint_getitem(SwigcptrVecint, int) int + +func (arg1 SwigcptrVecint) Getitem(arg2 int) int { + return _swig_wrap_vecint_getitem(arg1, arg2) +} + +func _swig_wrap_vecint_setitem(SwigcptrVecint, int, int) + +func (arg1 SwigcptrVecint) Setitem(arg2 int, arg3 int) { + _swig_wrap_vecint_setitem(arg1, arg2, arg3) +} + +func _swig_wrap_delete_vecint(uintptr) + +func DeleteVecint(arg1 Vecint) { + _swig_wrap_delete_vecint(arg1.Swigcptr()) +} + +type Vecint interface { + Swigcptr() uintptr + SwigIsVecint() + Get(arg2 int) *int + Set(arg2 int, arg3 *int) + Getitem(arg2 int) int + Setitem(arg2 int, arg3 int) +} + +type SwigcptrVecdouble uintptr + +func (p SwigcptrVecdouble) Swigcptr() uintptr { + return (uintptr)(p) +} + +func (p SwigcptrVecdouble) SwigIsVecdouble() { +} + +func _swig_wrap_new_vecdouble(int) SwigcptrVecdouble + +func NewVecdouble(arg1 int) Vecdouble { + return _swig_wrap_new_vecdouble(arg1) +} + +func _swig_wrap_vecdouble_get(SwigcptrVecdouble, int) *float64 + +func (arg1 SwigcptrVecdouble) Get(arg2 int) *float64 { + return _swig_wrap_vecdouble_get(arg1, arg2) +} + +func _swig_wrap_vecdouble_set(SwigcptrVecdouble, int, *float64) + +func (arg1 SwigcptrVecdouble) Set(arg2 int, arg3 *float64) { + _swig_wrap_vecdouble_set(arg1, arg2, arg3) +} + +func _swig_wrap_vecdouble_getitem(SwigcptrVecdouble, int) float64 + +func (arg1 SwigcptrVecdouble) Getitem(arg2 int) float64 { + return _swig_wrap_vecdouble_getitem(arg1, arg2) +} + +func _swig_wrap_vecdouble_setitem(SwigcptrVecdouble, int, float64) + +func (arg1 SwigcptrVecdouble) Setitem(arg2 int, arg3 float64) { + _swig_wrap_vecdouble_setitem(arg1, arg2, arg3) +} + +func _swig_wrap_delete_vecdouble(uintptr) + +func DeleteVecdouble(arg1 Vecdouble) { + _swig_wrap_delete_vecdouble(arg1.Swigcptr()) +} + +type Vecdouble interface { + Swigcptr() uintptr + SwigIsVecdouble() + Get(arg2 int) *float64 + Set(arg2 int, arg3 *float64) + Getitem(arg2 int) float64 + Setitem(arg2 int, arg3 float64) +} + + +type SwigcptrVoid uintptr +type Void interface { + Swigcptr() uintptr; +} +func (p SwigcptrVoid) Swigcptr() uintptr { + return uintptr(p) +} + diff --git a/Examples/go/template/example.h b/Examples/go/template/example.h new file mode 100644 index 000000000..7401df650 --- /dev/null +++ b/Examples/go/template/example.h @@ -0,0 +1,32 @@ +/* File : example.h */ + +// Some template definitions + +template T max(T a, T b) { return a>b ? a : b; } + +template class vector { + T *v; + int sz; + public: + vector(int _sz) { + v = new T[_sz]; + sz = _sz; + } + T &get(int index) { + return v[index]; + } + void set(int index, T &val) { + v[index] = val; + } +#ifdef SWIG + %extend { + T getitem(int index) { + return $self->get(index); + } + void setitem(int index, T val) { + $self->set(index,val); + } + } +#endif +}; + diff --git a/Examples/go/template/example.i b/Examples/go/template/example.i new file mode 100644 index 000000000..8f94c4da1 --- /dev/null +++ b/Examples/go/template/example.i @@ -0,0 +1,17 @@ +/* File : example.i */ +%module example + +%{ +#include "example.h" +%} + +/* Let's just grab the original header file here */ +%include "example.h" + +/* Now instantiate some specific template declarations */ + +%template(maxint) max; +%template(maxdouble) max; +%template(vecint) vector; +%template(vecdouble) vector; + diff --git a/Examples/go/template/index.html b/Examples/go/template/index.html new file mode 100644 index 000000000..a14e3b29a --- /dev/null +++ b/Examples/go/template/index.html @@ -0,0 +1,113 @@ + + +SWIG:Examples:go:template + + + + + +SWIG/Examples/go/template/ +
    + +

    C++ template support

    + +

    +This example illustrates how C++ templates can be used from Go using +SWIG. + +

    The C++ Code

    + +Lets take a templated function and a templated class as follows: + +
    +
    +/* File : example.h */
    +
    +// Some template definitions
    +
    +template T max(T a, T b) { return  a>b ? a : b; }
    +
    +template class vector {
    +  T *v;
    +  int sz;
    + public:
    +  vector(int _sz) {
    +    v = new T[_sz];
    +    sz = _sz;
    +  }
    +  T &get(int index) {
    +    return v[index];
    +  }
    +  void set(int index, T &val) {
    +    v[index] = val;
    +  }
    +#ifdef SWIG
    +  %addmethods {
    +    T getitem(int index) {
    +      return self->get(index);
    +    }
    +    void setitem(int index, T val) {
    +      self->set(index,val);
    +    }
    +  }
    +#endif
    +};
    +
    +
    +The %addmethods is used for a neater interface from Go as the +functions get and set use C++ references to +primitive types. These are tricky to use from Go as they end up as +pointers, which only work when the C++ and Go types correspond +precisely. + +

    The SWIG interface

    + +A simple SWIG interface for this can be built by simply grabbing the +header file like this: + +
    +
    +/* File : example.i */
    +%module example
    +
    +%{
    +#include "example.h"
    +%}
    +
    +/* Let's just grab the original header file here */
    +%include "example.h"
    +
    +/* Now instantiate some specific template declarations */
    +
    +%template(maxint) max;
    +%template(maxdouble) max;
    +%template(vecint) vector;
    +%template(vecdouble) vector;
    +
    +
    + +Note that SWIG parses the templated function max and +templated class vector and so knows about them. However to +generate code for use from Go, SWIG has to be told which class/type to +use as the template parameter. The SWIG directive %template is used +for this. + +

    A sample Go program

    + +Click here to see a Go program that calls the +C++ functions from Go. + +

    Notes

    Use templated classes just like you would any other +SWIG generated Go class. Use the classnames specified by the %template +directive. + +
    +
    +vecdouble dv = new vecdouble(1000);
    +dv.setitem(i, 12.34));
    +
    +
    + +
    + + diff --git a/Examples/go/template/runme.go b/Examples/go/template/runme.go new file mode 100644 index 000000000..8b3d4000e --- /dev/null +++ b/Examples/go/template/runme.go @@ -0,0 +1,43 @@ +// This example illustrates how C++ templates can be used from Go. + +package main + +import ( + "fmt" + . "./example" +) + +func main() { + + // Call some templated functions + fmt.Println(Maxint(3, 7)) + fmt.Println(Maxdouble(3.14, 2.18)) + + // Create some class + iv := NewVecint(100) + dv := NewVecdouble(1000) + + for i := 0; i < 100; i++ { + iv.Setitem(i, 2*i) + } + + for i := 0; i < 1000; i++ { + dv.Setitem(i, 1.0/float64(i+1)) + } + + { + sum := 0 + for i := 0; i < 100; i++ { + sum = sum + iv.Getitem(i) + } + fmt.Println(sum) + } + + { + sum := float64(0.0) + for i := 0; i < 1000; i++ { + sum = sum + dv.Getitem(i) + } + fmt.Println(sum) + } +} diff --git a/Examples/go/variables/Makefile b/Examples/go/variables/Makefile new file mode 100644 index 000000000..b0aa9c970 --- /dev/null +++ b/Examples/go/variables/Makefile @@ -0,0 +1,18 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +SRCS = example.c +TARGET = example +INTERFACE = example.i +SWIGOPT = + +all:: go + +go:: + $(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \ + SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go + +clean:: + $(MAKE) -f $(TOP)/Makefile go_clean + +check: all + $(MAKE) -f $(TOP)/Makefile TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go_run diff --git a/Examples/go/variables/example.c b/Examples/go/variables/example.c new file mode 100644 index 000000000..aa4ffe9b3 --- /dev/null +++ b/Examples/go/variables/example.c @@ -0,0 +1,91 @@ +/* File : example.c */ + +/* I'm a file containing some C global variables */ + +/* Deal with Microsoft's attempt at deprecating C standard runtime functions */ +#if !defined(SWIG_NO_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) +# define _CRT_SECURE_NO_DEPRECATE +#endif + +#include +#include +#include "example.h" + +int ivar = 0; +short svar = 0; +long lvar = 0; +unsigned int uivar = 0; +unsigned short usvar = 0; +unsigned long ulvar = 0; +signed char scvar = 0; +unsigned char ucvar = 0; +char cvar = 0; +float fvar = 0; +double dvar = 0; +char *strvar = 0; +const char cstrvar[] = "Goodbye"; +int *iptrvar = 0; +char name[256] = "Dave"; +char path[256] = "/home/beazley"; + + +/* Global variables involving a structure */ +Point *ptptr = 0; +Point pt = { 10, 20 }; + +/* A variable that we will make read-only in the interface */ +int status = 1; + +/* A debugging function to print out their values */ + +void print_vars() { + printf("ivar = %d\n", ivar); + printf("svar = %d\n", svar); + printf("lvar = %ld\n", lvar); + printf("uivar = %u\n", uivar); + printf("usvar = %u\n", usvar); + printf("ulvar = %lu\n", ulvar); + printf("scvar = %d\n", scvar); + printf("ucvar = %u\n", ucvar); + printf("fvar = %g\n", fvar); + printf("dvar = %g\n", dvar); + printf("cvar = %c\n", cvar); + printf("strvar = %s\n", strvar ? strvar : "(null)"); + printf("cstrvar = %s\n", cstrvar ? cstrvar : "(null)"); + printf("iptrvar = %p\n", iptrvar); + printf("name = %s\n", name); + printf("ptptr = %p (%d, %d)\n", ptptr, ptptr ? ptptr->x : 0, ptptr ? ptptr->y : 0); + printf("pt = (%d, %d)\n", pt.x, pt.y); + printf("status = %d\n", status); +} + +/* A function to create an integer (to test iptrvar) */ + +int *new_int(int value) { + int *ip = (int *) malloc(sizeof(int)); + *ip = value; + return ip; +} + +/* A function to create a point */ + +Point *new_Point(int x, int y) { + Point *p = (Point *) malloc(sizeof(Point)); + p->x = x; + p->y = y; + return p; +} + +char * Point_print(Point *p) { + static char buffer[256]; + if (p) { + sprintf(buffer,"(%d,%d)", p->x,p->y); + } else { + sprintf(buffer,"null"); + } + return buffer; +} + +void pt_print() { + printf("(%d, %d)\n", pt.x, pt.y); +} diff --git a/Examples/go/variables/example.go b/Examples/go/variables/example.go new file mode 100644 index 000000000..f4f299b73 --- /dev/null +++ b/Examples/go/variables/example.go @@ -0,0 +1,198 @@ +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 2.0.1 + * + * This file is not intended to be easily readable and contains a number of + * coding conventions designed to improve portability and efficiency. Do not make + * changes to this file unless you know what you are doing--modify the SWIG + * interface file instead. + * ----------------------------------------------------------------------------- */ + +package example + + +type _swig_fnptr *byte +type _swig_memberptr *byte + + +func _swig_allocatememory(int) *byte +func _swig_internal_allocate(len int) *byte { + return _swig_allocatememory(len) +} + +func _swig_allocatestring(*byte, int) string +func _swig_internal_makegostring(p *byte, l int) string { + return _swig_allocatestring(p, l) +} + +func _swig_internal_gopanic(p *byte, l int) { + panic(_swig_allocatestring(p, l)) +} + +func _swig_wrap_ivar_set(int) + +func SetIvar(arg1 int) { + _swig_wrap_ivar_set(arg1) +} + +func GetIvar() int +func _swig_wrap_svar_set(int16) + +func SetSvar(arg1 int16) { + _swig_wrap_svar_set(arg1) +} + +func GetSvar() int16 +func _swig_wrap_lvar_set(int32) + +func SetLvar(arg1 int32) { + _swig_wrap_lvar_set(arg1) +} + +func GetLvar() int32 +func _swig_wrap_uivar_set(uint) + +func SetUivar(arg1 uint) { + _swig_wrap_uivar_set(arg1) +} + +func GetUivar() uint +func _swig_wrap_usvar_set(uint16) + +func SetUsvar(arg1 uint16) { + _swig_wrap_usvar_set(arg1) +} + +func GetUsvar() uint16 +func _swig_wrap_ulvar_set(uint32) + +func SetUlvar(arg1 uint32) { + _swig_wrap_ulvar_set(arg1) +} + +func GetUlvar() uint32 +func _swig_wrap_scvar_set(int8) + +func SetScvar(arg1 int8) { + _swig_wrap_scvar_set(arg1) +} + +func GetScvar() int8 +func _swig_wrap_ucvar_set(byte) + +func SetUcvar(arg1 byte) { + _swig_wrap_ucvar_set(arg1) +} + +func GetUcvar() byte +func _swig_wrap_cvar_set(byte) + +func SetCvar(arg1 byte) { + _swig_wrap_cvar_set(arg1) +} + +func GetCvar() byte +func _swig_wrap_fvar_set(float32) + +func SetFvar(arg1 float32) { + _swig_wrap_fvar_set(arg1) +} + +func GetFvar() float32 +func _swig_wrap_dvar_set(float64) + +func SetDvar(arg1 float64) { + _swig_wrap_dvar_set(arg1) +} + +func GetDvar() float64 +func _swig_wrap_strvar_set(string) + +func SetStrvar(arg1 string) { + _swig_wrap_strvar_set(arg1) +} + +func GetStrvar() string +func GetCstrvar() string +func _swig_wrap_iptrvar_set(*int) + +func SetIptrvar(arg1 *int) { + _swig_wrap_iptrvar_set(arg1) +} + +func GetIptrvar() *int +func _swig_wrap_name_set(string) + +func SetName(arg1 string) { + _swig_wrap_name_set(arg1) +} + +func GetName() string +func _swig_wrap_ptptr_set(uintptr) + +func SetPtptr(arg1 Point) { + _swig_wrap_ptptr_set(arg1.Swigcptr()) +} + +func _swig_wrap_ptptr_get() SwigcptrPoint + +func GetPtptr() Point { + return _swig_wrap_ptptr_get() +} + +func _swig_wrap_pt_set(uintptr) + +func SetPt(arg1 Point) { + _swig_wrap_pt_set(arg1.Swigcptr()) +} + +func _swig_wrap_pt_get() SwigcptrPoint + +func GetPt() Point { + return _swig_wrap_pt_get() +} + +func GetStatus() int +func GetPath() string +func _swig_wrap_print_vars() + +func Print_vars() { + _swig_wrap_print_vars() +} + +func New_int(int) *int +func _swig_wrap_new_Point(int, int) SwigcptrPoint + +func New_Point(arg1 int, arg2 int) Point { + return _swig_wrap_new_Point(arg1, arg2) +} + +func _swig_wrap_Point_print(uintptr) string + +func Point_print(arg1 Point) string { + return _swig_wrap_Point_print(arg1.Swigcptr()) +} + +func _swig_wrap_pt_print() + +func Pt_print() { + _swig_wrap_pt_print() +} + + +type SwigcptrPoint uintptr +type Point interface { + Swigcptr() uintptr; +} +func (p SwigcptrPoint) Swigcptr() uintptr { + return uintptr(p) +} + +type SwigcptrVoid uintptr +type Void interface { + Swigcptr() uintptr; +} +func (p SwigcptrVoid) Swigcptr() uintptr { + return uintptr(p) +} + diff --git a/Examples/go/variables/example.h b/Examples/go/variables/example.h new file mode 100644 index 000000000..0f7e89594 --- /dev/null +++ b/Examples/go/variables/example.h @@ -0,0 +1,6 @@ +/* File: example.h */ + +typedef struct { + int x,y; +} Point; + diff --git a/Examples/go/variables/example.i b/Examples/go/variables/example.i new file mode 100644 index 000000000..591b871ed --- /dev/null +++ b/Examples/go/variables/example.i @@ -0,0 +1,49 @@ +/* File : example.i */ +%module example +%{ +#include "example.h" +%} + +/* Some global variable declarations */ +%inline %{ +extern int ivar; +extern short svar; +extern long lvar; +extern unsigned int uivar; +extern unsigned short usvar; +extern unsigned long ulvar; +extern signed char scvar; +extern unsigned char ucvar; +extern char cvar; +extern float fvar; +extern double dvar; +extern char *strvar; +extern const char cstrvar[]; +extern int *iptrvar; +extern char name[256]; + +extern Point *ptptr; +extern Point pt; +%} + + +/* Some read-only variables */ + +%immutable; + +%inline %{ +extern int status; +extern char path[256]; +%} + +%mutable; + +/* Some helper functions to make it easier to test */ +%inline %{ +extern void print_vars(); +extern int *new_int(int value); +extern Point *new_Point(int x, int y); +extern char *Point_print(Point *p); +extern void pt_print(); +%} + diff --git a/Examples/go/variables/index.html b/Examples/go/variables/index.html new file mode 100644 index 000000000..5a11194df --- /dev/null +++ b/Examples/go/variables/index.html @@ -0,0 +1,87 @@ + + +SWIG:Examples:go:variables + + + + +SWIG/Examples/go/variables/ +
    + +

    Wrapping C Global Variables

    + +

    +When a C global variable appears in an interface file, SWIG provides +getter and setter functions for the variable. The getter function is +named Get followed by the capitalized name of the variable. +The setter variable starts with Set instead. The getter +function takes no parameters and returns the value of the variable. +The setter function takes a single parameter with the same type as the +variable, and returns nothing. + +

    Click here to see a SWIG interface with +some variable declarations in it. + +

    Manipulating Variables from Go

    + +For example, if the package is called example, the global +variable + +
    +
    +double foo;
    +
    +
    + +will be accessed from Go as +
    +
    +example.GetFoo();
    +example.SetFoo(12.3);
    +
    +
    + +Click here to see the example program that +updates and prints out the values of the variables using this +technique. + +

    Key points

    + +
      +
    • The name of the variable is capitalized. +
    • When a global variable has the type "char *", SWIG +manages it as a character string. +
    • signed char and unsigned char are handled as +small 8-bit integers. +
    • String array variables such as 'char name[256]' are +managed as Go strings, but when setting the value, the result is +truncated to the maximum length of the array. Furthermore, the string +is assumed to be null-terminated. +
    • When structures and classes are used as global variables, they are +mapped into pointers. Getting the "value" returns a pointer to the +global variable. Setting the value of a structure results in a memory +copy from a pointer to the global. +
    + +

    Creating read-only variables

    + +The %immutable and %mutable directives can be used +to specify a collection of read-only variables. A read only variable +will have a getter function but no setter function. For example: + +
    +
    +%immutable;
    +int    status;
    +double blah;
    +...
    +%mutable;
    +
    +
    + +The %immutable directive remains in effect until it is +explicitly disabled using the %mutable directive. + + + +
    diff --git a/Examples/go/variables/runme.go b/Examples/go/variables/runme.go new file mode 100644 index 000000000..26cad4b3c --- /dev/null +++ b/Examples/go/variables/runme.go @@ -0,0 +1,67 @@ +// This example illustrates global variable access from Go. + +package main + +import ( + "fmt" + "./example" +) + +func main() { + // Try to set the values of some global variables + + example.SetIvar(42) + example.SetSvar(-31000) + example.SetLvar(65537) + example.SetUivar(123456) + example.SetUsvar(61000) + example.SetUlvar(654321) + example.SetScvar(-13) + example.SetUcvar(251) + example.SetCvar('S') + example.SetFvar(3.14159) + example.SetDvar(2.1828) + example.SetStrvar("Hello World") + example.SetIptrvar(example.New_int(37)) + example.SetPtptr(example.New_Point(37, 42)) + example.SetName("Bill") + + // Now print out the values of the variables + + fmt.Println("Variables (values printed from Go)") + + fmt.Println("ivar =", example.GetIvar()) + fmt.Println("svar =", example.GetSvar()) + fmt.Println("lvar =", example.GetLvar()) + fmt.Println("uivar =", example.GetUivar()) + fmt.Println("usvar =", example.GetUsvar()) + fmt.Println("ulvar =", example.GetUlvar()) + fmt.Println("scvar =", example.GetScvar()) + fmt.Println("ucvar =", example.GetUcvar()) + fmt.Println("fvar =", example.GetFvar()) + fmt.Println("dvar =", example.GetDvar()) + fmt.Printf("cvar = %c\n", example.GetCvar()) + fmt.Println("strvar =", example.GetStrvar()) + fmt.Println("cstrvar =", example.GetCstrvar()) + fmt.Println("iptrvar =", example.GetIptrvar()) + fmt.Println("name =", example.GetName()) + fmt.Println("ptptr =", example.GetPtptr(), example.Point_print(example.GetPtptr())) + fmt.Println("pt =", example.GetPt(), example.Point_print(example.GetPt())) + + fmt.Println("\nVariables (values printed from C)") + + example.Print_vars() + + // This line would not compile: since status is marked with + // %immutable, there is no SetStatus function. + // fmt.Println("\nNow I'm going to try and modify some read only variables") + // example.SetStatus(0) + + fmt.Println("\nI'm going to try and update a structure variable.\n") + + example.SetPt(example.GetPtptr()) + + fmt.Println("The new value is") + example.Pt_print() + fmt.Println("You should see the value", example.Point_print(example.GetPtptr())) +} diff --git a/Examples/test-suite/dynamic_cast.i b/Examples/test-suite/dynamic_cast.i index 5d4fbb0b6..ccbaa5b47 100644 --- a/Examples/test-suite/dynamic_cast.i +++ b/Examples/test-suite/dynamic_cast.i @@ -1,7 +1,7 @@ /* File : example.i */ %module dynamic_cast -#if !defined(SWIGJAVA) && !defined(SWIGCSHARP) +#if !defined(SWIGJAVA) && !defined(SWIGCSHARP) && !defined(SWIGGO) %apply SWIGTYPE *DYNAMIC { Foo * }; #endif @@ -17,7 +17,7 @@ public: }; %} -#if defined(SWIGJAVA) || defined(SWIGCSHARP) +#if defined(SWIGJAVA) || defined(SWIGCSHARP) || defined(SWIGGO) %typemap(out) Foo *blah { Bar *downcast = dynamic_cast($1); *(Bar **)&$result = downcast; @@ -37,6 +37,14 @@ public: } #endif +#if defined(SWIGGO) +%insert(go_runtime) %{ +func FooToBar(f Foo) Bar { + return SwigcptrBar(f.Swigcptr()) +} +%} +#endif + %inline %{ class Bar : public Foo { @@ -54,7 +62,7 @@ char *do_test(Bar *b) { } %} -#if !defined(SWIGJAVA) && !defined(SWIGCSHARP) +#if !defined(SWIGJAVA) && !defined(SWIGCSHARP) && !defined(SWIGGO) // A general purpose function for dynamic casting of a Foo * %{ static swig_type_info * diff --git a/Examples/test-suite/go/Makefile.in b/Examples/test-suite/go/Makefile.in new file mode 100644 index 000000000..d666c81bf --- /dev/null +++ b/Examples/test-suite/go/Makefile.in @@ -0,0 +1,110 @@ +####################################################################### +# Makefile for Go test-suite +####################################################################### + +LANGUAGE = go +GO = 6g +GOGCC = false +SCRIPTSUFFIX = _runme.go + +GOCOMPILEARG = `if $(GOGCC) ; then echo -c -g; fi` +GOC = $(GO:g=c) +GOLD = $(GO:g=l) + +GOOBJEXT = $(GO:g=) + +SO = @SO@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +top_builddir = @top_builddir@ + +include $(srcdir)/../common.mk + +# Custom tests - tests with additional commandline options +constant_pointers.cpptest: SWIGOPT += -rename foo=foofn +director_enum.cpptest: SWIGOPT += -rename Hello=Helloe +director_finalizer.cpptest: SWIGOPT += -rename deleteFoo=deleteFooFn +enum_thorough.cpptest: SWIGOPT += -rename One=Onee -rename Two=Twoe +mixed_types.cpptest: SWIGOPT += -rename Hello=Helloe +overload_simple.cpptest: SWIGOPT += -rename foo=foofn +smart_pointer_extend.cpptest: SWIGOPT += -rename CPtrFoo=CPtrFoos +smart_pointer_member.cpptest: SWIGOPT += -rename Foo=Foos +special_variable_macros.cpptest: SWIGOPT += -rename Name=Names +template_partial_specialization.cpptest: SWIGOPT += -rename b=bfn +template_partial_specialization_typedef.cpptest: SWIGOPT += -rename b=bfn +template_specialization_enum.cpptest: SWIGOPT += -rename Hello=Helloe +preproc.ctest: SWIGOPT += -rename a5=a5c -rename a6=a6c +mod.multicpptest: SWIGOPT += -rename GetC=GetCFn + +.SUFFIXES: .cpptest .ctest .multicpptest + +# Rules for the different types of tests +%.cpptest: + $(setup) + +$(swig_and_compile_cpp) + $(run_testcase) + +%.ctest: + $(setup) + +$(swig_and_compile_c) + $(run_testcase) + +%.multicpptest: + $(setup) + +$(swig_and_compile_multi_cpp) + $(run_multi_testcase) + +multi_import.multicpptest: + $(setup) + for f in multi_import_b multi_import_a; do \ + $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile CXXSRCS="$(CXXSRCS)" \ + SWIG_LIB="$(SWIG_LIB)" SWIG="$(SWIG)" LIBS='$(LIBS)' \ + INCLUDES="$(INCLUDES)" SWIGOPT="$(SWIGOPT)" NOLINK=true \ + TARGET="$(TARGETPREFIX)$${f}$(TARGETSUFFIX)" INTERFACEDIR="$(INTERFACEDIR)" INTERFACE="$$f.i" \ + $(LANGUAGE)$(VARIANT)_cpp; \ + done + $(run_multi_testcase) + +# Runs the testcase. +run_testcase = \ + if test -f $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX); then \ + $(GO) -I . $(GOCOMPILEARG) $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) && \ + if $(GOGCC) ; then \ + $(GO) -o $*_runme $(SCRIPTPREFIX)$*_runme.@OBJEXT@ $*.@OBJEXT@ $*$(SO); \ + else \ + $(GOLD) -L . -r $${GOROOT}/pkg/$${GOOS}_$${GOARCH}:. -o $*_runme $(SCRIPTPREFIX)$*_runme.$(GOOBJEXT); \ + fi && \ + env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH ./$*_runme; \ + fi + +run_multi_testcase = \ + if test -f $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX); then \ + $(GO) -I . $(GOCOMPILEARG) $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) && \ + if $(GOGCC) ; then \ + files=`cat $(top_srcdir)/$(EXAMPLES)/$(TEST_SUITE)/$*.list`; \ + $(GO) -o $*_runme $(SCRIPTPREFIX)$*_runme.@OBJEXT@ `for f in $$files; do echo $$f.@OBJEXT@ $$f$(SO); done`; \ + else \ + $(GOLD) -L . -r $${GOROOT}/pkg/$${GOOS}_$${GOARCH}:. -o $*_runme $(SCRIPTPREFIX)$*_runme.$(GOOBJEXT); \ + fi && \ + env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH ./$*_runme; \ + fi + +%.clean: + @rm -f $*.go $*_gc.c $*_wrap.* $*_runme + +clean: + $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile go_clean + rm -f mod_a.go mod_b.go imports_a.go imports_b.go + rm -f clientdata_prop_a.go clientdata_prop_b.go + rm -f multi_import_a.go multi_import_b.go + rm -f packageoption_a.go packageoption_b.go packageoption_c.go + +cvsignore: + @echo '*_gc.c *_wrap.* *.so *.dll *.exp *.lib' + @echo Makefile + @echo mod_a.go mod_b.go imports_a.go imports_b.go + @echo clientdata_prop_a.go clientdata_prop_b.go + @echo multi_import_a.go multi_import_b.go + @echo packageoption_a.go packageoption_b.go packageoption_c.go + @for i in ${CPP_TEST_CASES} ${C_TEST_CASES}; do echo $$i.go; done diff --git a/Examples/test-suite/go/abstract_access_runme.go b/Examples/test-suite/go/abstract_access_runme.go new file mode 100644 index 000000000..a2cfeda92 --- /dev/null +++ b/Examples/test-suite/go/abstract_access_runme.go @@ -0,0 +1,10 @@ +package main + +import "./abstract_access" + +func main() { + d := abstract_access.NewD() + if d.Do_x() != 1 { + panic(d.Do_x()) + } +} diff --git a/Examples/test-suite/go/abstract_typedef2_runme.go b/Examples/test-suite/go/abstract_typedef2_runme.go new file mode 100644 index 000000000..ef760e45d --- /dev/null +++ b/Examples/test-suite/go/abstract_typedef2_runme.go @@ -0,0 +1,7 @@ +package main + +import "./abstract_typedef2" + +func main() { + abstract_typedef2.NewA_UF() +} diff --git a/Examples/test-suite/go/abstract_typedef_runme.go b/Examples/test-suite/go/abstract_typedef_runme.go new file mode 100644 index 000000000..99ff94ded --- /dev/null +++ b/Examples/test-suite/go/abstract_typedef_runme.go @@ -0,0 +1,11 @@ +package main + +import "./abstract_typedef" + +func main() { + e := abstract_typedef.NewEngine() + a := abstract_typedef.NewA() + if !a.Write(e) { + panic("failed") + } +} diff --git a/Examples/test-suite/go/abstract_virtual_runme.go b/Examples/test-suite/go/abstract_virtual_runme.go new file mode 100644 index 000000000..b87cf9b5c --- /dev/null +++ b/Examples/test-suite/go/abstract_virtual_runme.go @@ -0,0 +1,8 @@ +package main + +import "./abstract_virtual" + +func main() { + abstract_virtual.NewD() + abstract_virtual.NewE() +} diff --git a/Examples/test-suite/go/array_member_runme.go b/Examples/test-suite/go/array_member_runme.go new file mode 100644 index 000000000..d8a8fac2b --- /dev/null +++ b/Examples/test-suite/go/array_member_runme.go @@ -0,0 +1,26 @@ +package main + +import . "./array_member" + +func main() { + f := NewFoo() + f.SetData(GetGlobal_data()) + + for i := 0; i < 8; i++ { + if Get_value(f.GetData(), i) != Get_value(GetGlobal_data(), i) { + panic("Bad array assignment") + } + } + + for i := 0; i < 8; i++ { + Set_value(f.GetData(), i, -i) + } + + SetGlobal_data(f.GetData()) + + for i := 0; i < 8; i++ { + if Get_value(f.GetData(), i) != Get_value(GetGlobal_data(), i) { + panic("Bad array assignment") + } + } +} diff --git a/Examples/test-suite/go/arrays_global_runme.go b/Examples/test-suite/go/arrays_global_runme.go new file mode 100644 index 000000000..0ff40090c --- /dev/null +++ b/Examples/test-suite/go/arrays_global_runme.go @@ -0,0 +1,22 @@ +package main + +import . "./arrays_global" + +func main() { + SetArray_i(GetArray_const_i()) + + GetBeginString_FIX44a() + GetBeginString_FIX44b() + GetBeginString_FIX44c() + GetBeginString_FIX44d() + GetBeginString_FIX44d() + SetBeginString_FIX44b("12\00045") + GetBeginString_FIX44b() + GetBeginString_FIX44d() + GetBeginString_FIX44e() + GetBeginString_FIX44f() + + Test_a("hello", "hi", "chello", "chi") + + Test_b("1234567", "hi") +} diff --git a/Examples/test-suite/go/class_ignore_runme.go b/Examples/test-suite/go/class_ignore_runme.go new file mode 100644 index 000000000..82e52eff5 --- /dev/null +++ b/Examples/test-suite/go/class_ignore_runme.go @@ -0,0 +1,10 @@ +package main + +import "./class_ignore" + +func main() { + a := class_ignore.NewBar() + if class_ignore.Do_blah(a) != "Bar::blah" { + panic(class_ignore.Do_blah(a)) + } +} diff --git a/Examples/test-suite/go/class_scope_weird_runme.go b/Examples/test-suite/go/class_scope_weird_runme.go new file mode 100644 index 000000000..332586f31 --- /dev/null +++ b/Examples/test-suite/go/class_scope_weird_runme.go @@ -0,0 +1,11 @@ +package main + +import "./class_scope_weird" + +func main() { + f := class_scope_weird.NewFoo() + class_scope_weird.NewFoo(3) + if f.Bar(3) != 3 { + panic(f.Bar(3)) + } +} diff --git a/Examples/test-suite/go/compactdefaultargs_runme.go b/Examples/test-suite/go/compactdefaultargs_runme.go new file mode 100644 index 000000000..8818dce07 --- /dev/null +++ b/Examples/test-suite/go/compactdefaultargs_runme.go @@ -0,0 +1,29 @@ +package main + +import . "./compactdefaultargs" + +func main() { + defaults1 := NewDefaults1(1000) + defaults1 = NewDefaults1() + + if defaults1.Ret(float64(10.0)) != 10.0 { + println(1, defaults1.Ret(float64(10.0))) + panic(defaults1.Ret(float64(10.0))) + } + + if defaults1.Ret() != -1.0 { + println(2, defaults1.Ret()) + panic(defaults1.Ret()) + } + + defaults2 := NewDefaults2(1000) + defaults2 = NewDefaults2() + + if defaults2.Ret(float64(10.0)) != 10.0 { + panic(defaults2.Ret(float64(10.0))) + } + + if defaults2.Ret() != -1.0 { + panic(defaults2.Ret()) + } +} diff --git a/Examples/test-suite/go/constover_runme.go b/Examples/test-suite/go/constover_runme.go new file mode 100644 index 000000000..e649140a6 --- /dev/null +++ b/Examples/test-suite/go/constover_runme.go @@ -0,0 +1,50 @@ +package main + +import ( + "fmt" + "os" + "./constover" +) + +func main() { + error := 0 + + p := constover.Test("test") + if p != "test" { + fmt.Println("test failed!") + error = 1 + } + + p = constover.Test_pconst("test") + if p != "test_pconst" { + fmt.Println("test_pconst failed!") + error = 1 + } + + f := constover.NewFoo() + p = f.Test("test") + if p != "test" { + fmt.Println("member-test failed!") + error = 1 + } + + p = f.Test_pconst("test") + if p != "test_pconst" { + fmt.Println("member-test_pconst failed!") + error = 1 + } + + p = f.Test_constm("test") + if p != "test_constmethod" { + fmt.Println("member-test_constm failed!") + error = 1 + } + + p = f.Test_pconstm("test") + if p != "test_pconstmethod" { + fmt.Println("member-test_pconstm failed!") + error = 1 + } + + os.Exit(error) +} diff --git a/Examples/test-suite/go/constructor_copy_runme.go b/Examples/test-suite/go/constructor_copy_runme.go new file mode 100644 index 000000000..d9b77a9db --- /dev/null +++ b/Examples/test-suite/go/constructor_copy_runme.go @@ -0,0 +1,34 @@ +package main + +import . "./constructor_copy" + +func main() { + f1 := NewFoo1(3) + f11 := NewFoo1(f1) + + if f1.GetX() != f11.GetX() { + panic("f1/f11 x mismatch") + } + + bi := NewBari(5) + bc := NewBari(bi) + + if bi.GetX() != bc.GetX() { + panic("bi/bc x mismatch") + } + + bd := NewBard(5) + good := false + func() { + defer func() { + if recover() != nil { + good = true + } + }() + NewBard(bd) + }() + + if !good { + panic("bd !good") + } +} diff --git a/Examples/test-suite/go/contract_runme.go b/Examples/test-suite/go/contract_runme.go new file mode 100644 index 000000000..d86110be2 --- /dev/null +++ b/Examples/test-suite/go/contract_runme.go @@ -0,0 +1,208 @@ +package main + +import "./contract" + +func main() { + contract.Test_preassert(1, 2) + contract.Test_postassert(3) + func() { + defer func() { + if recover() == nil { + panic("Failed! Postassertions are broken") + } + }() + contract.Test_postassert(-3) + }() + + contract.Test_prepost(2, 3) + contract.Test_prepost(5, -4) + func() { + defer func() { + if recover() == nil { + panic("Failed! Preassertions are broken") + } + }() + contract.Test_prepost(-3, 4) + }() + + func() { + defer func() { + if recover() == nil { + panic("Failed! Postassertions are broken") + } + }() + contract.Test_prepost(4, -10) + }() + + f := contract.NewFoo() + f.Test_preassert(4, 5) + func() { + defer func() { + if recover() == nil { + panic("Failed! Method preassertion.") + } + }() + f.Test_preassert(-2, 3) + }() + + f.Test_postassert(4) + func() { + defer func() { + if recover() == nil { + panic("Failed! Method postassertion") + } + }() + f.Test_postassert(-4) + }() + + f.Test_prepost(3, 4) + f.Test_prepost(4, -3) + func() { + defer func() { + if recover() == nil { + panic("Failed! Method preassertion.") + } + }() + f.Test_prepost(-4, 2) + }() + + func() { + defer func() { + if recover() == nil { + panic("Failed! Method postassertion.") + } + }() + f.Test_prepost(4, -10) + }() + + contract.FooStest_prepost(4, 0) + func() { + defer func() { + if recover() == nil { + panic("Failed! Static method preassertion") + } + }() + contract.FooStest_prepost(-4, 2) + }() + + func() { + defer func() { + if recover() == nil { + panic("Failed! Static method posteassertion") + } + }() + contract.FooStest_prepost(4, -10) + }() + + b := contract.NewBar() + func() { + defer func() { + if recover() == nil { + panic("Failed! Inherited preassertion.") + } + }() + b.Test_prepost(2, -4) + }() + + d := contract.NewD() + func() { + defer func() { + if recover() == nil { + panic("Failed! Inherited preassertion (D).") + } + }() + d.Foo(-1, 1, 1, 1, 1) + }() + + func() { + defer func() { + if recover() == nil { + panic("Failed! Inherited preassertion (D).") + } + }() + d.Foo(1, -1, 1, 1, 1) + }() + + func() { + defer func() { + if recover() == nil { + panic("Failed! Inherited preassertion (D).") + } + }() + d.Foo(1, 1, -1, 1, 1) + }() + + func() { + defer func() { + if recover() == nil { + panic("Failed! Inherited preassertion (D).") + } + }() + d.Foo(1, 1, 1, -1, 1) + }() + + func() { + defer func() { + if recover() == nil { + panic("Failed! Inherited preassertion (D).") + } + }() + d.Foo(1, 1, 1, 1, -1) + }() + + func() { + defer func() { + if recover() == nil { + panic("Failed! Inherited preassertion (D).") + } + }() + d.Bar(-1, 1, 1, 1, 1) + }() + + func() { + defer func() { + if recover() == nil { + panic("Failed! Inherited preassertion (D).") + } + }() + d.Bar(1, -1, 1, 1, 1) + }() + + func() { + defer func() { + if recover() == nil { + panic("Failed! Inherited preassertion (D).") + } + }() + d.Bar(1, 1, -1, 1, 1) + }() + + func() { + defer func() { + if recover() == nil { + panic("Failed! Inherited preassertion (D).") + } + }() + d.Bar(1, 1, 1, -1, 1) + }() + + func() { + defer func() { + if recover() == nil { + panic("Failed! Inherited preassertion (D).") + } + }() + d.Bar(1, 1, 1, 1, -1) + }() + + //Namespace + my := contract.NewMyClass(1) + func() { + defer func() { + if recover() == nil { + panic("Failed! constructor preassertion") + } + }() + my = contract.NewMyClass(0) + }() +} diff --git a/Examples/test-suite/go/cpp_enum_runme.go b/Examples/test-suite/go/cpp_enum_runme.go new file mode 100644 index 000000000..7d7db953d --- /dev/null +++ b/Examples/test-suite/go/cpp_enum_runme.go @@ -0,0 +1,27 @@ +package main + +import "./cpp_enum" + +func main() { + f := cpp_enum.NewFoo() + + if f.GetHola() != cpp_enum.FooHello { + panic(f.GetHola()) + } + + f.SetHola(cpp_enum.FooHi) + if f.GetHola() != cpp_enum.FooHi { + panic(f.GetHola()) + } + + f.SetHola(cpp_enum.FooHello) + + if f.GetHola() != cpp_enum.FooHello { + panic(f.GetHola()) + } + + cpp_enum.SetHi(cpp_enum.Hello) + if cpp_enum.GetHi() != cpp_enum.Hello { + panic(cpp_enum.Hi) + } +} diff --git a/Examples/test-suite/go/cpp_namespace_runme.go b/Examples/test-suite/go/cpp_namespace_runme.go new file mode 100644 index 000000000..8482b043f --- /dev/null +++ b/Examples/test-suite/go/cpp_namespace_runme.go @@ -0,0 +1,57 @@ +// Note: This example assumes that namespaces are flattened +package main + +import "./cpp_namespace" + +func main() { + n := cpp_namespace.Fact(4) + if n != 24 { + panic("Bad return value!") + } + + if cpp_namespace.GetFoo() != 42 { + panic("Bad variable value!") + } + + t := cpp_namespace.NewTest() + if t.Method() != "Test::method" { + panic("Bad method return value!") + } + + if cpp_namespace.Do_method(t) != "Test::method" { + panic("Bad return value!") + } + + if cpp_namespace.Do_method2(t) != "Test::method" { + panic("Bad return value!") + } + + cpp_namespace.Weird("hello", 4) + + cpp_namespace.DeleteTest(t) + + t2 := cpp_namespace.NewTest2() + t3 := cpp_namespace.NewTest3() + t4 := cpp_namespace.NewTest4() + t5 := cpp_namespace.NewTest5() + + if cpp_namespace.Foo3(42) != 42 { + panic("Bad return value!") + } + + if cpp_namespace.Do_method3(t2, 40) != "Test2::method" { + panic("Bad return value!") + } + + if cpp_namespace.Do_method3(t3, 40) != "Test3::method" { + panic("Bad return value!") + } + + if cpp_namespace.Do_method3(t4, 40) != "Test4::method" { + panic("Bad return value!") + } + + if cpp_namespace.Do_method3(t5, 40) != "Test5::method" { + panic("Bad return value!") + } +} diff --git a/Examples/test-suite/go/cpp_static_runme.go b/Examples/test-suite/go/cpp_static_runme.go new file mode 100644 index 000000000..ead433466 --- /dev/null +++ b/Examples/test-suite/go/cpp_static_runme.go @@ -0,0 +1,13 @@ +package main + +import . "./cpp_static" + +func main() { + StaticFunctionTestStatic_func() + StaticFunctionTestStatic_func_2(1) + StaticFunctionTestStatic_func_3(1, 2) + SetStaticMemberTestStatic_int(10) + if GetStaticMemberTestStatic_int() != 10 { + panic(GetStaticMemberTestStatic_int()) + } +} diff --git a/Examples/test-suite/go/default_args_runme.go b/Examples/test-suite/go/default_args_runme.go new file mode 100644 index 000000000..38243ac44 --- /dev/null +++ b/Examples/test-suite/go/default_args_runme.go @@ -0,0 +1,26 @@ +package main + +import "./default_args" + +func main() { + if default_args.StaticsStaticmethod() != 60 { + panic(0) + } + + if default_args.Cfunc1(1) != 2 { + panic(0) + } + + if default_args.Cfunc2(1) != 3 { + panic(0) + } + + if default_args.Cfunc3(1) != 4 { + panic(0) + } + + f := default_args.NewFoo() + + f.Newname() + f.Newname(1) +} diff --git a/Examples/test-suite/go/default_constructor_runme.go b/Examples/test-suite/go/default_constructor_runme.go new file mode 100644 index 000000000..e5e325475 --- /dev/null +++ b/Examples/test-suite/go/default_constructor_runme.go @@ -0,0 +1,35 @@ +package main + +import dc "./default_constructor" + +func main() { + a := dc.NewA() + dc.DeleteA(a) + + aa := dc.NewAA() + dc.DeleteAA(aa) + + cc := dc.NewCC() + dc.DeleteCC(cc) + + e := dc.NewE() + dc.DeleteE(e) + + ee := dc.NewEE() + dc.DeleteEE(ee) + + f := dc.NewF() + f.Destroy() + + ff := dc.NewFFF() + ff.Destroy() + + g := dc.NewG() + + dc.GDestroy(g) + + gg := dc.NewGG() + dc.DeleteGG(gg) + + dc.NewHH(1, 1) +} diff --git a/Examples/test-suite/go/director_abstract_runme.go b/Examples/test-suite/go/director_abstract_runme.go new file mode 100644 index 000000000..37279383a --- /dev/null +++ b/Examples/test-suite/go/director_abstract_runme.go @@ -0,0 +1,62 @@ +package main + +import "./director_abstract" + +type MyFoo struct{} + +func (p *MyFoo) Ping() string { + return "MyFoo::ping()" +} + +func f1() { + a := director_abstract.NewDirectorFoo(&MyFoo{}) + + if a.Ping() != "MyFoo::ping()" { + panic(a.Ping()) + } + + if a.Pong() != "Foo::pong();MyFoo::ping()" { + panic(a.Pong()) + } +} + +type MyExample1 struct{} + +func (p *MyExample1) Color(r, g, b byte) int { + return int(r) +} + +type MyExample2 struct{} + +func (p *MyExample2) Color(r, g, b byte) int { + return int(g) +} + +type MyExample3 struct{} + +func (p *MyExample3) Color(r, g, b byte) int { + return int(b) +} + +func f2() { + me1 := director_abstract.NewDirectorExample1(&MyExample1{}) + if director_abstract.Example1Get_color(me1, 1, 2, 3) != 1 { + println(director_abstract.Example1Get_color(me1, 1, 2, 3)) + panic(0) + } + + me2 := director_abstract.NewDirectorExample2(&MyExample2{}, 1, 2) + if director_abstract.Example2Get_color(me2, 1, 2, 3) != 2 { + panic(0) + } + + me3 := director_abstract.NewDirectorExample3_i(&MyExample3{}) + if director_abstract.Example3_iGet_color(me3, 1, 2, 3) != 3 { + panic(0) + } +} + +func main() { + f1() + f2() +} diff --git a/Examples/test-suite/go/director_basic_runme.go b/Examples/test-suite/go/director_basic_runme.go new file mode 100644 index 000000000..1995452ce --- /dev/null +++ b/Examples/test-suite/go/director_basic_runme.go @@ -0,0 +1,115 @@ +package main + +import "./director_basic" + +type GoFoo struct{} + +func (p *GoFoo) Ping() string { + return "GoFoo::ping()" +} + +func f1() { + a := director_basic.NewDirectorFoo(&GoFoo{}) + + if a.Ping() != "GoFoo::ping()" { + panic(a.Ping()) + } + + if a.Pong() != "Foo::pong();GoFoo::ping()" { + panic(a.Pong()) + } + + b := director_basic.NewFoo() + + if b.Ping() != "Foo::ping()" { + panic(b.Ping()) + } + + if b.Pong() != "Foo::pong();Foo::ping()" { + panic(b.Pong()) + } + + a1 := director_basic.NewA1(1) + + if a1.Rg(2) != 2 { + panic(0) + } +} + +type GoClass struct { + cmethod int +} + +func (p *GoClass) Method(uintptr) { + p.cmethod = 7 +} +func (p *GoClass) Vmethod(b director_basic.Bar) director_basic.Bar { + b.SetX(b.GetX() + 31) + return b +} + +var bc director_basic.Bar + +func f2() { + b := director_basic.NewBar(3) + d := director_basic.NewMyClass() + pc := &GoClass{0} + c := director_basic.NewDirectorMyClass(pc) + + cc := director_basic.MyClassGet_self(c) + dd := director_basic.MyClassGet_self(d) + + bc = cc.Cmethod(b) + bd := dd.Cmethod(b) + + cc.Method(b.Swigcptr()) + if pc.cmethod != 7 { + panic(pc.cmethod) + } + + if bc.GetX() != 34 { + panic(bc.GetX()) + } + + if bd.GetX() != 16 { + panic(bd.GetX()) + } +} + +type GoMulti struct { + GoClass +} + +func (p *GoMulti) Vmethod(b director_basic.Bar) director_basic.Bar { + b.SetX(b.GetX() + 31) + return b +} +func (p *GoMulti) Ping() string { + return "GoFoo::ping()" +} + +func f3() { + for i := 0; i < 100; i++ { + p := &GoMulti{GoClass{0}} + gomult := director_basic.NewDirectorFoo(p) + gomult.Pong() + director_basic.DeleteDirectorFoo(gomult) + } + + p := &GoMulti{GoClass{0}} + gomult := director_basic.NewDirectorMyClass(p) + fgomult := director_basic.NewDirectorFoo(gomult) + + p1 := director_basic.FooGet_self(fgomult.(director_basic.Foo)) + p2 := director_basic.MyClassGet_self(gomult.(director_basic.MyClass)) + + p1.Ping() + p2.Vmethod(bc) +} + + +func main() { + f1() + f2() + f3() +} diff --git a/Examples/test-suite/go/director_classic_runme.go b/Examples/test-suite/go/director_classic_runme.go new file mode 100644 index 000000000..45e89eac5 --- /dev/null +++ b/Examples/test-suite/go/director_classic_runme.go @@ -0,0 +1,135 @@ +package main + +import "fmt" +import . "./director_classic" + +type TargetLangPerson struct{} // From Person +func (p *TargetLangPerson) Id() string { + return "TargetLangPerson" +} + +type TargetLangChild struct{} // Form Child +func (p *TargetLangChild) Id() string { + return "TargetLangChild" +} + +type TargetLangGrandChild struct{} // From Grandchild +func (p *TargetLangGrandChild) Id() string { + return "TargetLangGrandChild" +} + +// Semis - don't override id() in target language + +type TargetLangSemiPerson struct{} // From Person + +type TargetLangSemiChild struct{} // From Child + +type TargetLangSemiGrandChild struct{} // From GrandChild + +// Orphans - don't override id() in C++ + +type TargetLangOrphanPerson struct{} // From OrphanPerson +func (p *TargetLangOrphanPerson) Id() string { + return "TargetLangOrphanPerson" +} + +type TargetLangOrphanChild struct{} // From OrphanChild +func (p *TargetLangOrphanChild) Id() string { + return "TargetLangOrphanChild" +} + +func check(person Person, expected string) { + debug := false + + // Normal target language polymorphic call + ret := person.Id() + if debug { + fmt.Println(ret) + } + if ret != expected { + panic("Failed. Received: " + ret + " Expected: " + expected) + } + + // Polymorphic call from C++ + caller := NewCaller() + caller.SetCallback(person) + ret = caller.Call() + if debug { + fmt.Println(ret) + } + if ret != expected { + panic("Failed. Received: " + ret + " Expected: " + expected) + } + + // Polymorphic call of object created in target language and + // passed to C++ and back again + baseclass := caller.BaseClass() + ret = baseclass.Id() + if debug { + fmt.Println(ret) + } + if ret != expected { + panic("Failed. Received: " + ret + " Expected: " + expected) + } + + caller.ResetCallback() + if debug { + fmt.Println("----------------------------------------") + } +} + +func main() { + person := NewPerson() + check(person, "Person") + DeletePerson(person) + + person = NewChild() + check(person, "Child") + DeletePerson(person) + + person = NewGrandChild() + check(person, "GrandChild") + DeletePerson(person) + + person = NewDirectorPerson(&TargetLangPerson{}) + check(person, "TargetLangPerson") + DeleteDirectorPerson(person) + + person = NewDirectorChild(&TargetLangChild{}) + check(person, "TargetLangChild") + DeleteDirectorChild(person.(Child)) + + person = NewDirectorGrandChild(&TargetLangGrandChild{}) + check(person, "TargetLangGrandChild") + DeleteDirectorGrandChild(person.(GrandChild)) + + // Semis - don't override id() in target language + person = NewDirectorPerson(&TargetLangSemiPerson{}) + check(person, "Person") + DeleteDirectorPerson(person) + + person = NewDirectorChild(&TargetLangSemiChild{}) + check(person, "Child") + DeleteDirectorChild(person.(Child)) + + person = NewDirectorGrandChild(&TargetLangSemiGrandChild{}) + check(person, "GrandChild") + DeleteDirectorGrandChild(person.(GrandChild)) + + // Orphans - don't override id() in C++ + person = NewOrphanPerson() + check(person, "Person") + DeleteOrphanPerson(person.(OrphanPerson)) + + person = NewOrphanChild() + check(person, "Child") + DeleteOrphanChild(person.(OrphanChild)) + + person = NewDirectorOrphanPerson(&TargetLangOrphanPerson{}) + check(person, "TargetLangOrphanPerson") + DeleteDirectorOrphanPerson(person.(OrphanPerson)) + + person = NewDirectorOrphanChild(&TargetLangOrphanChild{}) + check(person, "TargetLangOrphanChild") + DeleteDirectorOrphanChild(person.(OrphanChild)) +} diff --git a/Examples/test-suite/go/director_default_runme.go b/Examples/test-suite/go/director_default_runme.go new file mode 100644 index 000000000..2f963b239 --- /dev/null +++ b/Examples/test-suite/go/director_default_runme.go @@ -0,0 +1,11 @@ +package main + +import . "./director_default" + +func main() { + NewFoo() + NewFoo(1) + + NewBar() + NewBar(1) +} diff --git a/Examples/test-suite/go/director_detect_runme.go b/Examples/test-suite/go/director_detect_runme.go new file mode 100644 index 000000000..9f1ad94a9 --- /dev/null +++ b/Examples/test-suite/go/director_detect_runme.go @@ -0,0 +1,46 @@ +package main + +import "./director_detect" + +type MyBar struct { + val int +} // From director_detect.Bar + +func NewMyBar() director_detect.Bar { + return director_detect.NewDirectorBar(&MyBar{2}) +} + +func (p *MyBar) Get_value() int { + p.val++ + return p.val +} + +func (p *MyBar) Get_class() director_detect.A { + p.val++ + return director_detect.NewA() +} + +func (p *MyBar) Just_do_it() { + p.val++ +} + +func (p *MyBar) Clone() director_detect.Bar { + return director_detect.NewDirectorBar(&MyBar{p.val}) +} + +func main() { + b := NewMyBar() + + f := b.Baseclass() + + v := f.Get_value() + _ = f.Get_class() + f.Just_do_it() + + c := b.DirectorInterface().(*MyBar).Clone() + vc := c.Get_value() + + if (v != 3) || (b.DirectorInterface().(*MyBar).val != 5) || (vc != 6) { + panic("Bad virtual detection") + } +} diff --git a/Examples/test-suite/go/director_enum_runme.go b/Examples/test-suite/go/director_enum_runme.go new file mode 100644 index 000000000..e0dad900b --- /dev/null +++ b/Examples/test-suite/go/director_enum_runme.go @@ -0,0 +1,17 @@ +package main + +import "./director_enum" + +type MyFoo struct{} // From director_enum.Foo +func (p *MyFoo) Say_hi(val director_enum.EnumDirectorHelloe) director_enum.EnumDirectorHelloe { + return val +} + +func main() { + b := director_enum.NewFoo() + a := director_enum.NewDirectorFoo(&MyFoo{}) + + if a.Say_hi(director_enum.Hello) != b.Say_hello(director_enum.Hi) { + panic(0) + } +} diff --git a/Examples/test-suite/go/director_exception_runme.go b/Examples/test-suite/go/director_exception_runme.go new file mode 100644 index 000000000..29df3e40b --- /dev/null +++ b/Examples/test-suite/go/director_exception_runme.go @@ -0,0 +1,95 @@ +package main + +import . "./director_exception" + +type Exception struct { + msg string +} + +func NewException(a, b string) *Exception { + return &Exception{a + b} +} + +type MyFoo struct{} // From Foo +func (p *MyFoo) Ping() string { + panic("MyFoo::ping() EXCEPTION") +} + +type MyFoo2 struct{} // From Foo +func (p *MyFoo2) Ping() bool { + return true // should return a string +} + +type MyFoo3 struct{} // From Foo +func (p *MyFoo3) Ping() string { + panic(NewException("foo", "bar")) +} + +func main() { + // Check that the NotImplementedError raised by MyFoo.ping() + // is returned by MyFoo.pong(). + ok := false + a := NewDirectorFoo(&MyFoo{}) + b := Launder(a) + func() { + defer func() { + e := recover() + if e.(string) == "MyFoo::ping() EXCEPTION" { + ok = true + } else { + panic("Unexpected error message: " + e.(string)) + } + }() + b.Pong() + }() + if !ok { + panic(0) + } + + // Check that if the method has the wrong return type it is + // not called. + ok = false + a = NewDirectorFoo(&MyFoo2{}) + b = Launder(a) + e := b.Pong() + if e != "Foo::pong();"+"Foo::ping()" { + panic(e) + } + + // Check that the director can return an exception which + // requires two arguments to the constructor, without mangling + // it. + ok = false + a = NewDirectorFoo(&MyFoo3{}) + b = Launder(a) + func() { + defer func() { + e := recover() + if e.(*Exception).msg == "foobar" { + ok = true + } else { + panic("Unexpected error message: " + e.(string)) + } + }() + b.Pong() + }() + if !ok { + panic(0) + } + + func() { + defer func() { + e := recover() + _ = e.(Exception2) + }() + panic(NewException2()) + }() + + func() { + defer func() { + e := recover() + _ = e.(Exception1) + }() + panic(NewException1()) + }() +} diff --git a/Examples/test-suite/go/director_extend_runme.go b/Examples/test-suite/go/director_extend_runme.go new file mode 100644 index 000000000..70e2ab41b --- /dev/null +++ b/Examples/test-suite/go/director_extend_runme.go @@ -0,0 +1,18 @@ +// Test case from bug #1506850 "When threading is enabled, the +// interpreter will infinitely wait on a mutex the second time this +// type of extended method is called. Attached is an example program +// that waits on the mutex to be unlocked." + +package main + +import . "./director_extend" + +func main() { + m := NewSpObject() + if m.Dummy() != 666 { + panic("1st call") + } + if m.Dummy() != 666 { + panic("2nd call") + } +} diff --git a/Examples/test-suite/go/director_finalizer_runme.go b/Examples/test-suite/go/director_finalizer_runme.go new file mode 100644 index 000000000..96fcf860e --- /dev/null +++ b/Examples/test-suite/go/director_finalizer_runme.go @@ -0,0 +1,37 @@ +package main + +import . "./director_finalizer" + +type MyFoo struct{} // From Foo +func DeleteMyFoo(p Foo) { + p.OrStatus(2) + DeleteFoo(p) +} + +func main() { + ResetStatus() + + a := NewDirectorFoo(&MyFoo{}) + DeleteMyFoo(a) + + if GetStatus() != 3 { + panic(0) + } + + ResetStatus() + + a = NewDirectorFoo(&MyFoo{}) + Launder(a) + + if GetStatus() != 0 { + panic(0) + } + + DeleteMyFoo(a) + + if GetStatus() != 3 { + panic(0) + } + + ResetStatus() +} diff --git a/Examples/test-suite/go/director_frob_runme.go b/Examples/test-suite/go/director_frob_runme.go new file mode 100644 index 000000000..a6afedf69 --- /dev/null +++ b/Examples/test-suite/go/director_frob_runme.go @@ -0,0 +1,12 @@ +package main + +import . "./director_frob" + +func main() { + foo := NewBravo() + s := foo.Abs_method() + + if s != "Bravo::abs_method()" { + panic(s) + } +} diff --git a/Examples/test-suite/go/director_nested_runme.go b/Examples/test-suite/go/director_nested_runme.go new file mode 100644 index 000000000..2d3bc77e1 --- /dev/null +++ b/Examples/test-suite/go/director_nested_runme.go @@ -0,0 +1,79 @@ +package main + +import . "./director_nested" + +type A struct{} // From FooBar_int +func (p *A) Do_step() string { + return "A::do_step;" +} +func (p *A) Get_value() string { + return "A::get_value" +} + +func f1() { + a := NewDirectorFooBar_int(&A{}) + if a.Step() != "Bar::step;Foo::advance;Bar::do_advance;A::do_step;" { + panic("Bad A virtual resolution") + } +} + +type B struct{} // From FooBar_int +func (p *B) Do_advance() string { + return "B::do_advance;" + p.Do_step() +} +func (p *B) Do_step() string { + return "B::do_step;" +} +func (p *B) Get_value() int { + return 1 +} + +func f2() { + b := NewDirectorFooBar_int(&B{}) + + if b.Step() != "Bar::step;Foo::advance;B::do_advance;B::do_step;" { + panic("Bad B virtual resolution") + } +} + +type C struct { + fbi FooBar_int +} // From FooBar_int + +func (p *C) Do_advance() string { + return "C::do_advance;" + DirectorFooBar_intDo_advance(p.fbi) +} + +func (p *C) Do_step() string { + return "C::do_step;" +} + +func (p *C) Get_value() int { + return 2 +} + +func (p *C) Get_name() string { + return DirectorFooBar_intGet_name(p.fbi) + " hello" +} + +func f3() { + m := &C{nil} + cc := NewDirectorFooBar_int(m) + m.fbi = cc + c := FooBar_intGet_self(cc) + c.Advance() + + if c.Get_name() != "FooBar::get_name hello" { + panic(0) + } + + if c.Name() != "FooBar::get_name hello" { + panic(0) + } +} + +func main() { + f1() + f2() + f3() +} diff --git a/Examples/test-suite/go/director_profile_runme.go b/Examples/test-suite/go/director_profile_runme.go new file mode 100644 index 000000000..87edcbe26 --- /dev/null +++ b/Examples/test-suite/go/director_profile_runme.go @@ -0,0 +1,49 @@ +package main + +import "fmt" +import "./director_profile" + +type MyB struct{} // From director_profile.B +func (p *MyB) Vfi(a int) int { + return a + 3 +} + +func main() { + _ = director_profile.NewA() + myb := director_profile.NewDirectorB(&MyB{}) + b := director_profile.BGet_self(myb) + + fi := func(a int) int { + return b.Fi(a) + } + + i := 50000 + a := 1 + for i != 0 { + a = fi(a) // 1 + a = fi(a) // 2 + a = fi(a) // 3 + a = fi(a) // 4 + a = fi(a) // 5 + a = fi(a) // 6 + a = fi(a) // 7 + a = fi(a) // 8 + a = fi(a) // 9 + a = fi(a) // 10 + a = fi(a) // 1 + a = fi(a) // 2 + a = fi(a) // 3 + a = fi(a) // 4 + a = fi(a) // 5 + a = fi(a) // 6 + a = fi(a) // 7 + a = fi(a) // 8 + a = fi(a) // 9 + a = fi(a) // 20 + i -= 1 + } + + if false { + fmt.Println(a) + } +} diff --git a/Examples/test-suite/go/director_protected_runme.go b/Examples/test-suite/go/director_protected_runme.go new file mode 100644 index 000000000..3ffc1fbfa --- /dev/null +++ b/Examples/test-suite/go/director_protected_runme.go @@ -0,0 +1,48 @@ +package main + +import . "./director_protected" + +type FooBar struct{} // From Bar +func (p *FooBar) Ping() string { + return "FooBar::ping();" +} + +type FooBar2 struct{} // From Bar +func (p *FooBar2) Ping() string { + return "FooBar2::ping();" +} +func (p *FooBar2) Pang() string { + return "FooBar2::pang();" +} + +func main() { + b := NewBar() + f := b.Create() + fb := NewDirectorBar(&FooBar{}) + fb2 := NewDirectorBar(&FooBar2{}) + + s := fb.Used() + if s != "Foo::pang();Bar::pong();Foo::pong();FooBar::ping();" { + panic(0) + } + + s = fb2.Used() + if s != "FooBar2::pang();Bar::pong();Foo::pong();FooBar2::ping();" { + panic(0) + } + + s = b.Pong() + if s != "Bar::pong();Foo::pong();Bar::ping();" { + panic(0) + } + + s = f.Pong() + if s != "Bar::pong();Foo::pong();Bar::ping();" { + panic(0) + } + + s = fb.Pong() + if s != "Bar::pong();Foo::pong();FooBar::ping();" { + panic(0) + } +} diff --git a/Examples/test-suite/go/director_string_runme.go b/Examples/test-suite/go/director_string_runme.go new file mode 100644 index 000000000..c5201ab96 --- /dev/null +++ b/Examples/test-suite/go/director_string_runme.go @@ -0,0 +1,39 @@ +package main + +import . "./director_string" + +type B struct { // From A + abi A + smem string +} + +func NewB(s string) A { + p := &B{nil, ""} + ret := NewDirectorA(p, s) + p.abi = ret + return ret +} + +func (p *B) Get_first() string { + return DirectorAGet_first(p.abi) + " world!" +} + +func (p *B) Process_text(s string) { + DirectorAProcess_text(p.abi, s) + p.smem = "hello" +} + +func main() { + b := NewB("hello") + + b.Get(0) + if b.Get_first() != "hello world!" { + panic(b.Get_first()) + } + + b.Call_process_func() + + if b.DirectorInterface().(*B).smem != "hello" { + panic(b.DirectorInterface().(*B).smem) + } +} diff --git a/Examples/test-suite/go/director_thread_runme.go b/Examples/test-suite/go/director_thread_runme.go new file mode 100644 index 000000000..ddfacedbe --- /dev/null +++ b/Examples/test-suite/go/director_thread_runme.go @@ -0,0 +1,28 @@ +package main + +import . "./director_thread" + +type Derived struct { + abi Foo +} // From Foo +func (p *Derived) Do_foo() { + p.abi.SetVal(p.abi.GetVal() - 1) +} + +func main() { + + // FIXME: This test fails until we fix callbacks from a + // different thread. + return + + p := &Derived{nil} + d := NewDirectorFoo(p) + p.abi = d + d.Run() + + if d.GetVal() >= 0 { + panic(d.GetVal()) + } + + d.Stop() +} diff --git a/Examples/test-suite/go/director_unroll_runme.go b/Examples/test-suite/go/director_unroll_runme.go new file mode 100644 index 000000000..6d2894a72 --- /dev/null +++ b/Examples/test-suite/go/director_unroll_runme.go @@ -0,0 +1,21 @@ +package main + +import "./director_unroll" + +type MyFoo struct{} // From director_unroll.Foo +func (p *MyFoo) Ping() string { + return "MyFoo::ping()" +} + +func main() { + a := director_unroll.NewDirectorFoo(&MyFoo{}) + + b := director_unroll.NewBar() + + b.Set(a) + c := b.Get() + + if c.Ping() != "MyFoo::ping()" { + panic(c.Ping()) + } +} diff --git a/Examples/test-suite/go/disown_runme.go b/Examples/test-suite/go/disown_runme.go new file mode 100644 index 000000000..3e853de59 --- /dev/null +++ b/Examples/test-suite/go/disown_runme.go @@ -0,0 +1,10 @@ +package main + +import . "./disown" + +func main() { + a := NewA() + + b := NewB() + b.Acquire(a) +} diff --git a/Examples/test-suite/go/dynamic_cast_runme.go b/Examples/test-suite/go/dynamic_cast_runme.go new file mode 100644 index 000000000..476734805 --- /dev/null +++ b/Examples/test-suite/go/dynamic_cast_runme.go @@ -0,0 +1,16 @@ +package main + +import "./dynamic_cast" + +func main() { + f := dynamic_cast.NewFoo() + b := dynamic_cast.NewBar() + + _ = f.Blah() + y := b.Blah() + + a := dynamic_cast.Do_test(dynamic_cast.FooToBar(y)) + if a != "Bar::test" { + panic("Failed!!") + } +} diff --git a/Examples/test-suite/go/empty_runme.go b/Examples/test-suite/go/empty_runme.go new file mode 100644 index 000000000..f74285cb0 --- /dev/null +++ b/Examples/test-suite/go/empty_runme.go @@ -0,0 +1,6 @@ +package main + +import _ "./empty" + +func main() { +} diff --git a/Examples/test-suite/go/enum_template_runme.go b/Examples/test-suite/go/enum_template_runme.go new file mode 100644 index 000000000..269fe7d5b --- /dev/null +++ b/Examples/test-suite/go/enum_template_runme.go @@ -0,0 +1,11 @@ +package main + +import "./enum_template" + +func main() { + if enum_template.MakeETest() != 1 { + panic(0) + } + + enum_template.TakeETest(0) +} diff --git a/Examples/test-suite/go/enums_runme.go b/Examples/test-suite/go/enums_runme.go new file mode 100644 index 000000000..ab193f74b --- /dev/null +++ b/Examples/test-suite/go/enums_runme.go @@ -0,0 +1,25 @@ +package main + +import "./enums" + +func main() { + enums.Bar2(1) + enums.Bar3(1) + enums.Bar1(1) + + if enums.GetEnumInstance() != 2 { + panic(0) + } + + if enums.GetSlap() != 10 { + panic(0) + } + + if enums.GetMine() != 11 { + panic(0) + } + + if enums.GetThigh() != 12 { + panic(0) + } +} diff --git a/Examples/test-suite/go/exception_order_runme.go b/Examples/test-suite/go/exception_order_runme.go new file mode 100644 index 000000000..626a826f8 --- /dev/null +++ b/Examples/test-suite/go/exception_order_runme.go @@ -0,0 +1,58 @@ +package main + +import "strings" +import . "./exception_order" + +func main() { + a := NewA() + + func() { + defer func() { + e := recover() + if strings.Index(e.(string), "E1") == -1 { + panic(e.(string)) + } + }() + a.Foo() + }() + + func() { + defer func() { + e := recover() + if strings.Index(e.(string), "E2") == -1 { + panic(e.(string)) + } + }() + a.Bar() + }() + + func() { + defer func() { + e := recover() + if e.(string) != "postcatch unknown" { + panic("bad exception order") + } + }() + a.Foobar() + }() + + func() { + defer func() { + e := recover() + if strings.Index(e.(string), "E1") == -1 { + panic(e.(string)) + } + }() + a.Barfoo(1) + }() + + func() { + defer func() { + e := recover() + if strings.Index(e.(string), "E2") == -1 { + panic(e.(string)) + } + }() + a.Barfoo(2) + }() +} diff --git a/Examples/test-suite/go/extend_placement_runme.go b/Examples/test-suite/go/extend_placement_runme.go new file mode 100644 index 000000000..f74831c7d --- /dev/null +++ b/Examples/test-suite/go/extend_placement_runme.go @@ -0,0 +1,47 @@ +package main + +import "./extend_placement" + +func main() { + foo := extend_placement.NewFoo() + foo = extend_placement.NewFoo(1) + foo = extend_placement.NewFoo(1, 1) + foo.Spam() + foo.Spam("hello") + foo.Spam(1) + foo.Spam(1, 1) + foo.Spam(1, 1, 1) + foo.Spam(extend_placement.NewFoo()) + foo.Spam(extend_placement.NewFoo(), float64(1.0)) + + bar := extend_placement.NewBar() + bar = extend_placement.NewBar(1) + bar.Spam() + bar.Spam("hello") + bar.Spam(1) + bar.Spam(1, 1) + bar.Spam(1, 1, 1) + bar.Spam(extend_placement.NewBar()) + bar.Spam(extend_placement.NewBar(), float64(1.0)) + + footi := extend_placement.NewFooTi() + footi = extend_placement.NewFooTi(1) + footi = extend_placement.NewFooTi(1, 1) + footi.Spam() + footi.Spam("hello") + footi.Spam(1) + footi.Spam(1, 1) + footi.Spam(1, 1, 1) + footi.Spam(extend_placement.NewFoo()) + footi.Spam(extend_placement.NewFoo(), float64(1.0)) + + barti := extend_placement.NewBarTi() + barti = extend_placement.NewBarTi(1) + barti.Spam() + barti.Spam("hello") + barti.Spam(1) + barti.Spam(1, 1) + barti.Spam(1, 1, 1) + barti.Spam(extend_placement.NewBar()) + barti.Spam(extend_placement.NewBar(), float64(1.0)) +} diff --git a/Examples/test-suite/go/extend_template_ns_runme.go b/Examples/test-suite/go/extend_template_ns_runme.go new file mode 100644 index 000000000..164a31b26 --- /dev/null +++ b/Examples/test-suite/go/extend_template_ns_runme.go @@ -0,0 +1,14 @@ +package main + +import . "./extend_template_ns" + +func main() { + f := NewFoo_One() + if f.Test1(37) != 37 { + panic(0) + } + + if f.Test2(42) != 42 { + panic(0) + } +} diff --git a/Examples/test-suite/go/extend_template_runme.go b/Examples/test-suite/go/extend_template_runme.go new file mode 100644 index 000000000..5adb4b3c2 --- /dev/null +++ b/Examples/test-suite/go/extend_template_runme.go @@ -0,0 +1,14 @@ +package main + +import "./extend_template" + +func main() { + f := extend_template.NewFoo_0() + if f.Test1(37) != 37 { + panic(0) + } + + if f.Test2(42) != 42 { + panic(0) + } +} diff --git a/Examples/test-suite/go/extend_variable_runme.go b/Examples/test-suite/go/extend_variable_runme.go new file mode 100644 index 000000000..c6428c467 --- /dev/null +++ b/Examples/test-suite/go/extend_variable_runme.go @@ -0,0 +1,9 @@ +package main + +import . "./extend_variable" + +func main() { + if FooBar != 42 { + panic(0) + } +} diff --git a/Examples/test-suite/go/extern_c_runme.go b/Examples/test-suite/go/extern_c_runme.go new file mode 100644 index 000000000..0fb5b21cc --- /dev/null +++ b/Examples/test-suite/go/extern_c_runme.go @@ -0,0 +1,7 @@ +package main + +import "./extern_c" + +func main() { + extern_c.RealFunction(2) +} diff --git a/Examples/test-suite/go/friends_runme.go b/Examples/test-suite/go/friends_runme.go new file mode 100644 index 000000000..80177bae8 --- /dev/null +++ b/Examples/test-suite/go/friends_runme.go @@ -0,0 +1,50 @@ +package main + +import "./friends" + +func main() { + a := friends.NewA(2) + + if friends.Get_val1(a).(int) != 2 { + panic(0) + } + if friends.Get_val2(a) != 4 { + panic(0) + } + if friends.Get_val3(a) != 6 { + panic(0) + } + + // nice overload working fine + if friends.Get_val1(1, 2, 3).(int) != 1 { + panic(0) + } + + b := friends.NewB(3) + + // David's case + if friends.Mix(a, b) != 5 { + panic(0) + } + + di := friends.NewD_d(2) + dd := friends.NewD_d(3.3) + + // incredible template overloading working just fine + if friends.Get_val1(di).(float64) != 2 { + panic(0) + } + if friends.Get_val1(dd).(float64) != 3.3 { + panic(0) + } + + friends.Set(di, float64(4.0)) + friends.Set(dd, float64(1.3)) + + if friends.Get_val1(di).(float64) != 4 { + panic(0) + } + if friends.Get_val1(dd).(float64) != 1.3 { + panic(0) + } +} diff --git a/Examples/test-suite/go/fvirtual_runme.go b/Examples/test-suite/go/fvirtual_runme.go new file mode 100644 index 000000000..8810d5cbb --- /dev/null +++ b/Examples/test-suite/go/fvirtual_runme.go @@ -0,0 +1,13 @@ +package main + +import . "./fvirtual" + +func main() { + sw := NewNodeSwitch() + n := NewNode() + i := sw.AddChild(n) + + if i != 2 { + panic("addChild") + } +} diff --git a/Examples/test-suite/go/global_ns_arg_runme.go b/Examples/test-suite/go/global_ns_arg_runme.go new file mode 100644 index 000000000..f4c8a7ed5 --- /dev/null +++ b/Examples/test-suite/go/global_ns_arg_runme.go @@ -0,0 +1,8 @@ +package main + +import . "./global_ns_arg" + +func main() { + Foo(1) + Bar() +} diff --git a/Examples/test-suite/go/grouping_runme.go b/Examples/test-suite/go/grouping_runme.go new file mode 100644 index 000000000..c63d6fb12 --- /dev/null +++ b/Examples/test-suite/go/grouping_runme.go @@ -0,0 +1,19 @@ +package main + +import "./grouping" + +func main() { + x := grouping.Test1(42) + if x != 42 { + panic(0) + } + + grouping.Test2(42) + + x = grouping.Do_unary(37, grouping.NEGATE) + if x != -37 { + panic(0) + } + + grouping.SetTest3(42) +} diff --git a/Examples/test-suite/go/import_nomodule_runme.go b/Examples/test-suite/go/import_nomodule_runme.go new file mode 100644 index 000000000..a6bbd7de5 --- /dev/null +++ b/Examples/test-suite/go/import_nomodule_runme.go @@ -0,0 +1,12 @@ +package main + +import . "./import_nomodule" + +func main() { + f := Create_Foo() + Test1(f, 42) + Delete_Foo(f) + + b := NewBar() + Test1(b, 37) +} diff --git a/Examples/test-suite/go/imports_runme.go b/Examples/test-suite/go/imports_runme.go new file mode 100644 index 000000000..896036cbf --- /dev/null +++ b/Examples/test-suite/go/imports_runme.go @@ -0,0 +1,17 @@ +// This is the import runtime testcase. + +package main + +import "imports_b" +import "imports_a" + +func main() { + x := imports_b.NewB() + x.Hello() + + _ = imports_a.NewA() + + c := imports_b.NewC() + _ = c.Get_a(c) + _ = c.Get_a_type(c) +} diff --git a/Examples/test-suite/go/inctest_runme.go b/Examples/test-suite/go/inctest_runme.go new file mode 100644 index 000000000..f8a2c116c --- /dev/null +++ b/Examples/test-suite/go/inctest_runme.go @@ -0,0 +1,18 @@ +package main + +import "./inctest" + +func main() { + inctest.NewA() + inctest.NewB() + + // Check the import in subdirectory worked + if inctest.Importtest1(5) != 15 { + panic("import test 1 failed") + } + + a := []byte("black") + if inctest.Importtest2(string(a)) != "white" { + panic("import test 2 failed") + } +} diff --git a/Examples/test-suite/go/inherit_missing_runme.go b/Examples/test-suite/go/inherit_missing_runme.go new file mode 100644 index 000000000..ba9a2a516 --- /dev/null +++ b/Examples/test-suite/go/inherit_missing_runme.go @@ -0,0 +1,26 @@ +package main + +import "./inherit_missing" + +func main() { + a := inherit_missing.New_Foo() + b := inherit_missing.NewBar() + c := inherit_missing.NewSpam() + + x := inherit_missing.Do_blah(a) + if x != "Foo::blah" { + panic(x) + } + + x = inherit_missing.Do_blah(b) + if x != "Bar::blah" { + panic(x) + } + + x = inherit_missing.Do_blah(c) + if x != "Spam::blah" { + panic(x) + } + + inherit_missing.Delete_Foo(a) +} diff --git a/Examples/test-suite/go/input_runme.go b/Examples/test-suite/go/input_runme.go new file mode 100644 index 000000000..207bdaa28 --- /dev/null +++ b/Examples/test-suite/go/input_runme.go @@ -0,0 +1,14 @@ +package main + +import . "./input" + +func main() { + f := NewFoo() + if f.Foo(2) != 4 { + panic(0) + } + + if Sfoo("Hello") != "Hello world" { + panic(0) + } +} diff --git a/Examples/test-suite/go/keyword_rename_runme.go b/Examples/test-suite/go/keyword_rename_runme.go new file mode 100644 index 000000000..e36bc5968 --- /dev/null +++ b/Examples/test-suite/go/keyword_rename_runme.go @@ -0,0 +1,8 @@ +package main + +import "./keyword_rename" + +func main() { + keyword_rename.Xgo(1) + keyword_rename.Xchan(1) +} diff --git a/Examples/test-suite/go/li_attribute_runme.go b/Examples/test-suite/go/li_attribute_runme.go new file mode 100644 index 000000000..5d2c3d0c3 --- /dev/null +++ b/Examples/test-suite/go/li_attribute_runme.go @@ -0,0 +1,90 @@ +package main + +import "./li_attribute" + +func main() { + aa := li_attribute.NewA(1, 2, 3) + + if aa.GetA() != 1 { + panic(0) + } + aa.SetA(3) + if aa.GetA() != 3 { + panic(aa.GetA()) + } + + if aa.GetB() != 2 { + panic(aa.GetB()) + } + aa.SetB(5) + if aa.GetB() != 5 { + panic(0) + } + + if aa.GetD() != aa.GetB() { + panic(0) + } + + if aa.GetC() != 3 { + panic(0) + } + + pi := li_attribute.NewParam_i(7) + if pi.GetValue() != 7 { + panic(0) + } + pi.SetValue(3) + if pi.GetValue() != 3 { + panic(0) + } + + b := li_attribute.NewB(aa) + + if b.GetA().GetC() != 3 { + panic(0) + } + + // class/struct attribute with get/set methods using + // return/pass by reference + myFoo := li_attribute.NewMyFoo() + myFoo.SetX(8) + myClass := li_attribute.NewMyClass() + myClass.SetFoo(myFoo) + if myClass.GetFoo().GetX() != 8 { + panic(0) + } + + // class/struct attribute with get/set methods using + // return/pass by value + myClassVal := li_attribute.NewMyClassVal() + if myClassVal.GetReadWriteFoo().GetX() != -1 { + panic(0) + } + if myClassVal.GetReadOnlyFoo().GetX() != -1 { + panic(0) + } + myClassVal.SetReadWriteFoo(myFoo) + if myClassVal.GetReadWriteFoo().GetX() != 8 { + panic(0) + } + if myClassVal.GetReadOnlyFoo().GetX() != 8 { + panic(0) + } + + // string attribute with get/set methods using return/pass by + // value + myStringyClass := li_attribute.NewMyStringyClass("initial string") + if myStringyClass.GetReadWriteString() != "initial string" { + panic(0) + } + if myStringyClass.GetReadOnlyString() != "initial string" { + panic(0) + } + myStringyClass.SetReadWriteString("changed string") + if myStringyClass.GetReadWriteString() != "changed string" { + panic(0) + } + if myStringyClass.GetReadOnlyString() != "changed string" { + panic(0) + } +} diff --git a/Examples/test-suite/go/li_carrays_runme.go b/Examples/test-suite/go/li_carrays_runme.go new file mode 100644 index 000000000..0cbe92cd8 --- /dev/null +++ b/Examples/test-suite/go/li_carrays_runme.go @@ -0,0 +1,14 @@ +package main + +import . "./li_carrays" + +func main() { + d := NewDoubleArray(10) + + d.Setitem(0, 7) + d.Setitem(5, d.Getitem(0)+3) + + if d.Getitem(5)+d.Getitem(0) != 17 { + panic(0) + } +} diff --git a/Examples/test-suite/go/li_cdata_runme.go b/Examples/test-suite/go/li_cdata_runme.go new file mode 100644 index 000000000..f71a3a2c3 --- /dev/null +++ b/Examples/test-suite/go/li_cdata_runme.go @@ -0,0 +1,13 @@ +package main + +import . "./li_cdata" + +func main() { + s := "ABC abc" + m := Malloc(256) + Memmove(m, s, len(s)) + ss := Cdata(m, 7) + if string(ss) != "ABC abc" { + panic("failed") + } +} diff --git a/Examples/test-suite/go/li_cmalloc_runme.go b/Examples/test-suite/go/li_cmalloc_runme.go new file mode 100644 index 000000000..45f47b45f --- /dev/null +++ b/Examples/test-suite/go/li_cmalloc_runme.go @@ -0,0 +1,25 @@ +package main + +import . "./li_cmalloc" + +func main() { + p := Malloc_int() + Free_int(p) + + ok := false + func() { + defer func() { + if recover() != nil { + ok = true + } + }() + p = Calloc_int(-1) + if p == nil { + ok = true + } + Free_int(p) + }() + if !ok { + panic(0) + } +} diff --git a/Examples/test-suite/go/li_cpointer_runme.go b/Examples/test-suite/go/li_cpointer_runme.go new file mode 100644 index 000000000..57493b122 --- /dev/null +++ b/Examples/test-suite/go/li_cpointer_runme.go @@ -0,0 +1,14 @@ +package main + +import . "./li_cpointer" + +func main() { + p := New_intp() + Intp_assign(p, 3) + + if Intp_value(p) != 3 { + panic(0) + } + + Delete_intp(p) +} diff --git a/Examples/test-suite/go/li_std_map_runme.go b/Examples/test-suite/go/li_std_map_runme.go new file mode 100644 index 000000000..66e74dd60 --- /dev/null +++ b/Examples/test-suite/go/li_std_map_runme.go @@ -0,0 +1,30 @@ +package main + +import "./li_std_map" + +func main() { + a1 := li_std_map.NewA(3) + a2 := li_std_map.NewA(7) + + _ = li_std_map.NewPairii(1, 2) + p1 := li_std_map.NewPairA(1, a1) + m := li_std_map.NewMapA() + m.Set(1, a1) + m.Set(2, a2) + + _ = li_std_map.P_identa(p1) + _ = li_std_map.M_identa(m) + + m = li_std_map.NewMapA() + m.Set(1, a1) + m.Set(2, a2) + + mii := li_std_map.NewIntIntMap() + + mii.Set(1, 1) + mii.Set(1, 2) + + if mii.Get(1) != 2 { + panic(0) + } +} diff --git a/Examples/test-suite/go/member_pointer_runme.go b/Examples/test-suite/go/member_pointer_runme.go new file mode 100644 index 000000000..9a55bc4b9 --- /dev/null +++ b/Examples/test-suite/go/member_pointer_runme.go @@ -0,0 +1,49 @@ +// Example using pointers to member functions + +package main + +import "fmt" +import . "./member_pointer" + +func check(what string, expected float64, actual float64) { + if expected != actual { + panic(fmt.Sprintf("Failed: %s Expected: %f Actual; %f", what, expected, actual)) + } +} + +func main() { + // Get the pointers + + area_pt := Areapt() + perim_pt := Perimeterpt() + + // Create some objects + + s := NewSquare(10) + + // Do some calculations + + check("Square area ", 100.0, Do_op(s, area_pt)) + check("Square perim", 40.0, Do_op(s, perim_pt)) + + _ = GetAreavar() + _ = GetPerimetervar() + + // Try the variables + check("Square area ", 100.0, Do_op(s, GetAreavar())) + check("Square perim", 40.0, Do_op(s, GetPerimetervar())) + + // Modify one of the variables + SetAreavar(perim_pt) + + check("Square perimeter", 40.0, Do_op(s, GetAreavar())) + + // Try the constants + + _ = AREAPT + _ = PERIMPT + _ = NULLPT + + check("Square area ", 100.0, Do_op(s, AREAPT)) + check("Square perim", 40.0, Do_op(s, PERIMPT)) +} diff --git a/Examples/test-suite/go/memberin_extend_c_runme.go b/Examples/test-suite/go/memberin_extend_c_runme.go new file mode 100644 index 000000000..ec8b11e60 --- /dev/null +++ b/Examples/test-suite/go/memberin_extend_c_runme.go @@ -0,0 +1,11 @@ +package main + +import "./memberin_extend_c" + +func main() { + t := memberin_extend_c.NewPerson() + t.SetName("Fred Bloggs") + if t.GetName() != "FRED BLOGGS" { + panic("name wrong") + } +} diff --git a/Examples/test-suite/go/minherit_runme.go b/Examples/test-suite/go/minherit_runme.go new file mode 100644 index 000000000..c69fe92c1 --- /dev/null +++ b/Examples/test-suite/go/minherit_runme.go @@ -0,0 +1,82 @@ +package main + +import "fmt" +import "./minherit" + +func main() { + a := minherit.NewFoo() + b := minherit.NewBar() + c := minherit.NewFooBar() + d := minherit.NewSpam() + + if a.Xget() != 1 { + panic("1 Bad attribute value") + } + + if b.Yget() != 2 { + panic("2 Bad attribute value") + } + + if c.Xget() != 1 || c.Yget() != 2 || c.Zget() != 3 { + panic("3 Bad attribute value") + } + + if d.Xget() != 1 || d.Yget() != 2 || d.Zget() != 3 || d.Wget() != 4 { + panic("4 Bad attribute value") + } + + if minherit.Xget(a) != 1 { + panic(fmt.Sprintf("5 Bad attribute value %d", minherit.Xget(a))) + } + + if minherit.Yget(b) != 2 { + panic(fmt.Sprintf("6 Bad attribute value %d", minherit.Yget(b))) + } + + if minherit.Xget(c) != 1 || minherit.Yget(c.SwigGetBar()) != 2 || minherit.Zget(c) != 3 { + panic(fmt.Sprintf("7 Bad attribute value %d %d %d", minherit.Xget(c), minherit.Yget(c.SwigGetBar()), minherit.Zget(c))) + } + + if minherit.Xget(d) != 1 || minherit.Yget(d.SwigGetBar()) != 2 || minherit.Zget(d) != 3 || minherit.Wget(d) != 4 { + panic(fmt.Sprintf("8 Bad attribute value %d %d %d %d", minherit.Xget(d), minherit.Yget(d.SwigGetBar()), minherit.Zget(d), minherit.Wget(d))) + } + + // Cleanse all of the pointers and see what happens + + aa := minherit.ToFooPtr(a) + bb := minherit.ToBarPtr(b) + cc := minherit.ToFooBarPtr(c) + dd := minherit.ToSpamPtr(d) + + if aa.Xget() != 1 { + panic("9 Bad attribute value") + } + + if bb.Yget() != 2 { + panic("10 Bad attribute value") + } + + if cc.Xget() != 1 || cc.Yget() != 2 || cc.Zget() != 3 { + panic("11 Bad attribute value") + } + + if dd.Xget() != 1 || dd.Yget() != 2 || dd.Zget() != 3 || dd.Wget() != 4 { + panic("12 Bad attribute value") + } + + if minherit.Xget(aa) != 1 { + panic(fmt.Sprintf("13 Bad attribute value %d", minherit.Xget(aa))) + } + + if minherit.Yget(bb) != 2 { + panic(fmt.Sprintf("14 Bad attribute value %d", minherit.Yget(bb))) + } + + if minherit.Xget(cc) != 1 || minherit.Yget(cc.SwigGetBar()) != 2 || minherit.Zget(cc) != 3 { + panic(fmt.Sprintf("15 Bad attribute value %d %d %d", minherit.Xget(cc), minherit.Yget(cc.SwigGetBar()), minherit.Zget(cc))) + } + + if minherit.Xget(dd) != 1 || minherit.Yget(dd.SwigGetBar()) != 2 || minherit.Zget(dd) != 3 || minherit.Wget(dd) != 4 { + panic(fmt.Sprintf("16 Bad attribute value %d %d %d %d", minherit.Xget(dd), minherit.Yget(dd.SwigGetBar()), minherit.Zget(dd), minherit.Wget(dd))) + } +} diff --git a/Examples/test-suite/go/mod_runme.go b/Examples/test-suite/go/mod_runme.go new file mode 100644 index 000000000..581c83918 --- /dev/null +++ b/Examples/test-suite/go/mod_runme.go @@ -0,0 +1,10 @@ +package main + +import "mod_a" +import "mod_b" + +func main() { + c := mod_b.NewC() + d := mod_b.NewD() + d.DoSomething(mod_a.SwigcptrA(c.Swigcptr())) +} diff --git a/Examples/test-suite/go/multi_import_runme.go b/Examples/test-suite/go/multi_import_runme.go new file mode 100644 index 000000000..973af1e7b --- /dev/null +++ b/Examples/test-suite/go/multi_import_runme.go @@ -0,0 +1,29 @@ +package main + +import "multi_import_a" +import "multi_import_b" + +func main() { + x := multi_import_b.NewXXX() + if x.Testx() != 0 { + panic(0) + } + + y := multi_import_b.NewYYY() + if y.Testx() != 0 { + panic(0) + } + if y.Testy() != 1 { + panic(0) + } + + z := multi_import_a.NewZZZ() + if z.Testx() != 0 { + println("z.Testx", z.Testx(), z.Testz()) + panic(0) + } + if z.Testz() != 2 { + println("z.Testz", z.Testz()) + panic(0) + } +} diff --git a/Examples/test-suite/go/namespace_class_runme.go b/Examples/test-suite/go/namespace_class_runme.go new file mode 100644 index 000000000..2ed5567f7 --- /dev/null +++ b/Examples/test-suite/go/namespace_class_runme.go @@ -0,0 +1,19 @@ +package main + +import . "./namespace_class" + +func main() { + EulerT3DToFrame(1, 1, 1) + + _ = NewBooT_i() + _ = NewBooT_H() + + f1 := NewFooT_i() + f1.Quack(1) + + f2 := NewFooT_d() + f2.Moo(1) + + f3 := NewFooT_H() + f3.Foo(Hi) +} diff --git a/Examples/test-suite/go/namespace_typemap_runme.go b/Examples/test-suite/go/namespace_typemap_runme.go new file mode 100644 index 000000000..95311a37a --- /dev/null +++ b/Examples/test-suite/go/namespace_typemap_runme.go @@ -0,0 +1,116 @@ +package main + +import . "./namespace_typemap" + +func main() { + if Stest1("hello") != "hello" { + panic(0) + } + + if Stest2("hello") != "hello" { + panic(0) + } + + if Stest3("hello") != "hello" { + panic(0) + } + + if Stest4("hello") != "hello" { + panic(0) + } + + if Stest5("hello") != "hello" { + panic(0) + } + + if Stest6("hello") != "hello" { + panic(0) + } + + if Stest7("hello") != "hello" { + panic(0) + } + + if Stest8("hello") != "hello" { + panic(0) + } + + if Stest9("hello") != "hello" { + panic(0) + } + + if Stest10("hello") != "hello" { + panic(0) + } + + if Stest11("hello") != "hello" { + panic(0) + } + + if Stest12("hello") != "hello" { + panic(0) + } + + c := cmplx(float64(2), float64(3)) + r := real(c) + + if Ctest1(c) != r { + println(Ctest1(c)) + panic(Ctest1(c)) + } + + if Ctest2(c) != r { + panic(0) + } + + if Ctest3(c) != r { + panic(0) + } + + if Ctest4(c) != r { + panic(0) + } + + if Ctest5(c) != r { + panic(0) + } + + if Ctest6(c) != r { + panic(0) + } + + if Ctest7(c) != r { + panic(0) + } + + if Ctest8(c) != r { + panic(0) + } + + if Ctest9(c) != r { + panic(0) + } + + if Ctest10(c) != r { + panic(0) + } + + if Ctest11(c) != r { + panic(0) + } + + if Ctest12(c) != r { + panic(0) + } + + ok := false + func() { + defer func() { + ok = recover() != nil + }() + Ttest1(-14) + }() + if !ok { + panic(0) + } +} diff --git a/Examples/test-suite/go/namespace_virtual_method_runme.go b/Examples/test-suite/go/namespace_virtual_method_runme.go new file mode 100644 index 000000000..3f8e774c6 --- /dev/null +++ b/Examples/test-suite/go/namespace_virtual_method_runme.go @@ -0,0 +1,7 @@ +package main + +import "./namespace_virtual_method" + +func main() { + _ = namespace_virtual_method.NewSpam() +} diff --git a/Examples/test-suite/go/naturalvar_runme.go b/Examples/test-suite/go/naturalvar_runme.go new file mode 100644 index 000000000..e3723e6ab --- /dev/null +++ b/Examples/test-suite/go/naturalvar_runme.go @@ -0,0 +1,17 @@ +package main + +import . "./naturalvar" + +func main() { + f := NewFoo() + b := NewBar() + + b.SetF(f) + + SetS("hello") + b.SetS("hello") + + if b.GetS() != GetS() { + panic(0) + } +} diff --git a/Examples/test-suite/go/nested_workaround_runme.go b/Examples/test-suite/go/nested_workaround_runme.go new file mode 100644 index 000000000..5737aaaf7 --- /dev/null +++ b/Examples/test-suite/go/nested_workaround_runme.go @@ -0,0 +1,19 @@ +package main + +import . "./nested_workaround" + +func main() { + inner := NewInner(5) + outer := NewOuter() + newInner := outer.DoubleInnerValue(inner) + if newInner.GetValue() != 10 { + panic(0) + } + + outer = NewOuter() + inner = outer.CreateInner(3) + newInner = outer.DoubleInnerValue(inner) + if outer.GetInnerValue(newInner) != 6 { + panic(0) + } +} diff --git a/Examples/test-suite/go/overload_complicated_runme.go b/Examples/test-suite/go/overload_complicated_runme.go new file mode 100644 index 000000000..e3911c218 --- /dev/null +++ b/Examples/test-suite/go/overload_complicated_runme.go @@ -0,0 +1,62 @@ +package main + +import . "./overload_complicated" + +func main() { + var pInt *int + + // Check the correct constructors are available + p := NewPop(pInt) + + p = NewPop(pInt, false) + + // Check overloaded in const only and pointers/references + // which target languages cannot disambiguate + if p.Hip(false) != 701 { + panic("Test 1 failed") + } + + if p.Hip(pInt) != 702 { + panic("Test 2 failed") + } + + // Reverse the order for the above + if p.Hop(pInt) != 805 { + panic("Test 3 failed") + } + + if p.Hop(false) != 801 { + panic("Test 4 failed") + } + + // Few more variations and order shuffled + if p.Pop(false) != 901 { + panic("Test 5 failed") + } + + if p.Pop(pInt) != 902 { + panic("Test 6 failed") + } + + if p.Pop() != 905 { + panic("Test 7 failed") + } + + // Overload on const only + if p.Bop(pInt) != 1001 { + panic("Test 8 failed") + } + + if p.Bip(pInt) != 2001 { + panic("Test 9 failed") + } + + // Globals + if Muzak(false) != 3001 { + panic("Test 10 failed") + } + + if Muzak(pInt) != 3002 { + panic("Test 11 failed") + } +} diff --git a/Examples/test-suite/go/overload_copy_runme.go b/Examples/test-suite/go/overload_copy_runme.go new file mode 100644 index 000000000..d35ff70b1 --- /dev/null +++ b/Examples/test-suite/go/overload_copy_runme.go @@ -0,0 +1,8 @@ +package main + +import . "./overload_copy" + +func main() { + f := NewFoo() + _ = NewFoo(f) +} diff --git a/Examples/test-suite/go/overload_extend_runme.go b/Examples/test-suite/go/overload_extend_runme.go new file mode 100644 index 000000000..228dfe89c --- /dev/null +++ b/Examples/test-suite/go/overload_extend_runme.go @@ -0,0 +1,22 @@ +package main + +import "./overload_extend" + +func main() { + f := overload_extend.NewFoo() + if f.Test().(int) != 0 { + panic(0) + } + if f.Test(3).(int) != 1 { + panic(0) + } + if f.Test("hello").(int) != 2 { + panic(0) + } + if f.Test(float64(3), float64(2)).(float64) != 5 { + panic(0) + } + if f.Test(float64(3.0)).(float64) != 1003 { + panic(0) + } +} diff --git a/Examples/test-suite/go/overload_extendc_runme.go b/Examples/test-suite/go/overload_extendc_runme.go new file mode 100644 index 000000000..aec8935f5 --- /dev/null +++ b/Examples/test-suite/go/overload_extendc_runme.go @@ -0,0 +1,33 @@ +package main + +import "./overload_extendc" + +func main() { + f := overload_extendc.NewFoo() + if f.Test(3) != 1 { + panic(0) + } + if f.Test("hello") != 2 { + panic(0) + } + if f.Test(float64(3.5), float64(2.5)) != 3 { + panic(0) + } + if f.Test("hello", 20) != 1020 { + panic(0) + } + if f.Test("hello", 20, 100) != 120 { + panic(0) + } + + // C default args + if f.Test(f) != 30 { + panic(0) + } + if f.Test(f, 100) != 120 { + panic(0) + } + if f.Test(f, 100, 200) != 300 { + panic(0) + } +} diff --git a/Examples/test-suite/go/overload_rename_runme.go b/Examples/test-suite/go/overload_rename_runme.go new file mode 100644 index 000000000..dca5843c3 --- /dev/null +++ b/Examples/test-suite/go/overload_rename_runme.go @@ -0,0 +1,10 @@ +package main + +import "./overload_rename" + +func main() { + _ = overload_rename.NewFoo(float32(1)) + _ = overload_rename.NewFoo(float32(1), float32(1)) + _ = overload_rename.NewFoo_int(float32(1), 1) + _ = overload_rename.NewFoo_int(float32(1), 1, float32(1)) +} diff --git a/Examples/test-suite/go/overload_simple_runme.go b/Examples/test-suite/go/overload_simple_runme.go new file mode 100644 index 000000000..58fe46dab --- /dev/null +++ b/Examples/test-suite/go/overload_simple_runme.go @@ -0,0 +1,125 @@ +package main + +import . "./overload_simple" + +func main() { + if Foofn(3) != "foo:int" { + panic("foo(int)") + } + + if Foofn(float64(3.0)) != "foo:double" { + panic("foo(double)") + } + + if Foofn("hello") != "foo:char *" { + panic("foo(char *)") + } + + f := NewFoo() + b := NewBar() + + if Foofn(f) != "foo:Foo *" { + panic("foo(Foo *)") + } + + if Foofn(b) != "foo:Bar *" { + panic("foo(Bar *)") + } + + v := Malloc_void(32) + + if Foofn(v) != "foo:void *" { + panic("foo(void *)") + } + s := NewSpam() + + if s.Foofn(3) != "foo:int" { + panic("Spam::foo(int)") + } + + if s.Foofn(float64(3.0)) != "foo:double" { + panic("Spam::foo(double)") + } + + if s.Foofn("hello") != "foo:char *" { + panic("Spam::foo(char *)") + } + + if s.Foofn(f) != "foo:Foo *" { + panic("Spam::foo(Foo *)") + } + + if s.Foofn(b) != "foo:Bar *" { + panic("Spam::foo(Bar *)") + } + + if s.Foofn(v) != "foo:void *" { + panic("Spam::foo(void *)") + } + + if SpamBar(3) != "bar:int" { + panic("Spam::bar(int)") + } + + if SpamBar(float64(3.0)) != "bar:double" { + panic("Spam::bar(double)") + } + + if SpamBar("hello") != "bar:char *" { + panic("Spam::bar(char *)") + } + + if SpamBar(f) != "bar:Foo *" { + panic("Spam::bar(Foo *)") + } + + if SpamBar(b) != "bar:Bar *" { + panic("Spam::bar(Bar *)") + } + + if SpamBar(v) != "bar:void *" { + panic("Spam::bar(void *)") + } + + // Test constructors + + s = NewSpam() + if s.GetXtype() != "none" { + panic("Spam()") + } + + s = NewSpam(3) + if s.GetXtype() != "int" { + panic("Spam(int)") + } + + s = NewSpam(float64(3.4)) + if s.GetXtype() != "double" { + panic("Spam(double)") + } + + s = NewSpam("hello") + if s.GetXtype() != "char *" { + panic("Spam(char *)") + } + + s = NewSpam(f) + if s.GetXtype() != "Foo *" { + panic("Spam(Foo *)") + } + + s = NewSpam(b) + if s.GetXtype() != "Bar *" { + panic("Spam(Bar *)") + } + + s = NewSpam(v) + if s.GetXtype() != "void *" { + panic("Spam(void *)") + } + + Free_void(v) + + a := NewClassA() + _ = a.Method1(1) +} diff --git a/Examples/test-suite/go/overload_subtype_runme.go b/Examples/test-suite/go/overload_subtype_runme.go new file mode 100644 index 000000000..dc56d1ca7 --- /dev/null +++ b/Examples/test-suite/go/overload_subtype_runme.go @@ -0,0 +1,16 @@ +package main + +import . "./overload_subtype" + +func main() { + f := NewFoo() + b := NewBar() + + if Spam(f) != 1 { + panic("foo") + } + + if Spam(b) != 2 { + panic("bar") + } +} diff --git a/Examples/test-suite/go/overload_template_fast_runme.go b/Examples/test-suite/go/overload_template_fast_runme.go new file mode 100644 index 000000000..8fc7c364c --- /dev/null +++ b/Examples/test-suite/go/overload_template_fast_runme.go @@ -0,0 +1,187 @@ +package main + +import . "./overload_template_fast" + +func main() { + _ = Foo() + + _ = Maximum(3, 4) + _ = Maximum(float64(3.4), float64(5.2)) + + // mix 1 + if Mix1("hi") != 101 { + panic("mix1(const char*)") + } + + if Mix1(float64(1.0), float64(1.0)) != 102 { + panic("mix1(double, const double &)") + } + + if Mix1(float64(1.0)) != 103 { + panic("mix1(double)") + } + + // mix 2 + if Mix2("hi") != 101 { + panic("mix2(const char*)") + } + + if Mix2(float64(1.0), float64(1.0)) != 102 { + panic("mix2(double, const double &)") + } + + if Mix2(float64(1.0)) != 103 { + panic("mix2(double)") + } + + // mix 3 + if Mix3("hi") != 101 { + panic("mix3(const char*)") + } + + if Mix3(float64(1.0), float64(1.0)) != 102 { + panic("mix3(double, const double &)") + } + + if Mix3(float64(1.0)) != 103 { + panic("mix3(double)") + } + + // Combination 1 + if Overtparams1(100) != 10 { + panic("overtparams1(int)") + } + + if Overtparams1(float64(100.0), 100) != 20 { + panic("overtparams1(double, int)") + } + + // Combination 2 + if Overtparams2(float64(100.0), 100) != 40 { + panic("overtparams2(double, int)") + } + + // Combination 3 + if Overloaded() != 60 { + panic("overloaded()") + } + + if Overloaded(float64(100.0), 100) != 70 { + panic("overloaded(double, int)") + } + + // Combination 4 + if Overloadedagain("hello") != 80 { + panic("overloadedagain(const char *)") + } + + if Overloadedagain() != 90 { + panic("overloadedagain(double)") + } + + // specializations + if Specialization(10) != 202 { + panic("specialization(int)") + } + + if Specialization(float64(10.0)) != 203 { + panic("specialization(double)") + } + + if Specialization(10, 10) != 204 { + panic("specialization(int, int)") + } + + if Specialization(float64(10.0), float64(10.0)) != 205 { + panic("specialization(double, double)") + } + + if Specialization("hi", "hi") != 201 { + panic("specialization(const char *, const char *)") + } + + // simple specialization + Xyz() + Xyz_int() + Xyz_double() + + // a bit of everything + if Overload("hi") != 0 { + panic("overload()") + } + + if Overload(1) != 10 { + panic("overload(int t)") + } + + if Overload(1, 1) != 20 { + panic("overload(int t, const int &)") + } + + if Overload(1, "hello") != 30 { + panic("overload(int t, const char *)") + } + + k := NewKlass() + if Overload(k) != 10 { + panic("overload(Klass t)") + } + + if Overload(k, k) != 20 { + panic("overload(Klass t, const Klass &)") + } + + if Overload(k, "hello") != 30 { + panic("overload(Klass t, const char *)") + } + + if Overload(float64(10.0), "hi") != 40 { + panic("overload(double t, const char *)") + } + + if Overload() != 50 { + panic("overload(const char *)") + } + + + // everything put in a namespace + if Nsoverload("hi") != 1000 { + panic("nsoverload()") + } + + if Nsoverload(1) != 1010 { + panic("nsoverload(int t)") + } + + if Nsoverload(1, 1) != 1020 { + panic("nsoverload(int t, const int &)") + } + + if Nsoverload(1, "hello") != 1030 { + panic("nsoverload(int t, const char *)") + } + + if Nsoverload(k) != 1010 { + panic("nsoverload(Klass t)") + } + + if Nsoverload(k, k) != 1020 { + panic("nsoverload(Klass t, const Klass &)") + } + + if Nsoverload(k, "hello") != 1030 { + panic("nsoverload(Klass t, const char *)") + } + + if Nsoverload(float64(10.0), "hi") != 1040 { + panic("nsoverload(double t, const char *)") + } + + if Nsoverload() != 1050 { + panic("nsoverload(const char *)") + } + + AFoo(1) + b := NewB() + b.Foo(1) +} diff --git a/Examples/test-suite/go/overload_template_runme.go b/Examples/test-suite/go/overload_template_runme.go new file mode 100644 index 000000000..124402f37 --- /dev/null +++ b/Examples/test-suite/go/overload_template_runme.go @@ -0,0 +1,188 @@ +package main + +import . "./overload_template" + +func main() { + _ = Foo() + + _ = Maximum(3, 4) + _ = Maximum(float64(3.4), float64(5.2)) + + // mix 1 + if Mix1("hi") != 101 { + panic("mix1(const char*)") + } + + if Mix1(float64(1.0), float64(1.0)) != 102 { + panic("mix1(double, const double &)") + } + + if Mix1(float64(1.0)) != 103 { + panic("mix1(double)") + } + + // mix 2 + if Mix2("hi") != 101 { + panic("mix2(const char*)") + } + + if Mix2(float64(1.0), float64(1.0)) != 102 { + panic("mix2(double, const double &)") + } + + if Mix2(float64(1.0)) != 103 { + panic("mix2(double)") + } + + // mix 3 + if Mix3("hi") != 101 { + panic("mix3(const char*)") + } + + if Mix3(float64(1.0), float64(1.0)) != 102 { + panic("mix3(double, const double &)") + } + + if Mix3(float64(1.0)) != 103 { + panic("mix3(double)") + } + + // Combination 1 + if Overtparams1(100) != 10 { + panic("overtparams1(int)") + } + + if Overtparams1(float64(100.0), 100) != 20 { + panic("overtparams1(double, int)") + } + + // Combination 2 + if Overtparams2(float64(100.0), 100) != 40 { + panic("overtparams2(double, int)") + } + + // Combination 3 + if Overloaded() != 60 { + panic("overloaded()") + } + + if Overloaded(float64(100.0), 100) != 70 { + panic("overloaded(double, int)") + } + + // Combination 4 + if Overloadedagain("hello") != 80 { + panic("overloadedagain(const char *)") + } + + if Overloadedagain() != 90 { + panic("overloadedagain(double)") + } + + // specializations + if Specialization(10) != 202 { + panic("specialization(int)") + } + + if Specialization(float64(10.0)) != 203 { + panic("specialization(double)") + } + + if Specialization(10, 10) != 204 { + panic("specialization(int, int)") + } + + if Specialization(float64(10.0), float64(10.0)) != 205 { + panic("specialization(double, double)") + } + + if Specialization("hi", "hi") != 201 { + panic("specialization(const char *, const char *)") + } + + + // simple specialization + Xyz() + Xyz_int() + Xyz_double() + + // a bit of everything + if Overload("hi") != 0 { + panic("overload()") + } + + if Overload(1) != 10 { + panic("overload(int t)") + } + + if Overload(1, 1) != 20 { + panic("overload(int t, const int &)") + } + + if Overload(1, "hello") != 30 { + panic("overload(int t, const char *)") + } + + k := NewKlass() + if Overload(k) != 10 { + panic("overload(Klass t)") + } + + if Overload(k, k) != 20 { + panic("overload(Klass t, const Klass &)") + } + + if Overload(k, "hello") != 30 { + panic("overload(Klass t, const char *)") + } + + if Overload(float64(10.0), "hi") != 40 { + panic("overload(double t, const char *)") + } + + if Overload() != 50 { + panic("overload(const char *)") + } + + + // everything put in a namespace + if Nsoverload("hi") != 1000 { + panic("nsoverload()") + } + + if Nsoverload(1) != 1010 { + panic("nsoverload(int t)") + } + + if Nsoverload(1, 1) != 1020 { + panic("nsoverload(int t, const int &)") + } + + if Nsoverload(1, "hello") != 1030 { + panic("nsoverload(int t, const char *)") + } + + if Nsoverload(k) != 1010 { + panic("nsoverload(Klass t)") + } + + if Nsoverload(k, k) != 1020 { + panic("nsoverload(Klass t, const Klass &)") + } + + if Nsoverload(k, "hello") != 1030 { + panic("nsoverload(Klass t, const char *)") + } + + if Nsoverload(float64(10.0), "hi") != 1040 { + panic("nsoverload(double t, const char *)") + } + + if Nsoverload() != 1050 { + panic("nsoverload(const char *)") + } + + AFoo(1) + b := NewB() + b.Foo(1) +} diff --git a/Examples/test-suite/go/preproc_runme.go b/Examples/test-suite/go/preproc_runme.go new file mode 100644 index 000000000..a15062241 --- /dev/null +++ b/Examples/test-suite/go/preproc_runme.go @@ -0,0 +1,21 @@ +package main + +import "./preproc" + +func main() { + if preproc.GetEndif() != 1 { + panic(0) + } + + if preproc.GetDefine() != 1 { + panic(0) + } + + if preproc.GetDefined() != 1 { + panic(0) + } + + if 2*preproc.One != preproc.Two { + panic(0) + } +} diff --git a/Examples/test-suite/go/primitive_ref_runme.go b/Examples/test-suite/go/primitive_ref_runme.go new file mode 100644 index 000000000..973806955 --- /dev/null +++ b/Examples/test-suite/go/primitive_ref_runme.go @@ -0,0 +1,57 @@ +package main + +import . "./primitive_ref" + +func main() { + if Ref_int(3) != 3 { + panic(0) + } + + if Ref_uint(3) != 3 { + panic(0) + } + + if Ref_short(3) != 3 { + panic(0) + } + + if Ref_ushort(3) != 3 { + panic(0) + } + + if Ref_long(3) != 3 { + panic(0) + } + + if Ref_ulong(3) != 3 { + panic(0) + } + + if Ref_schar(3) != 3 { + panic(0) + } + + if Ref_uchar(3) != 3 { + panic(0) + } + + if Ref_float(3.5) != 3.5 { + panic(0) + } + + if Ref_double(3.5) != 3.5 { + panic(0) + } + + if Ref_bool(true) != true { + panic(0) + } + + if Ref_char('x') != 'x' { + panic(0) + } + + if Ref_over(0) != 0 { + panic(0) + } +} diff --git a/Examples/test-suite/go/profiletest_runme.go b/Examples/test-suite/go/profiletest_runme.go new file mode 100644 index 000000000..30b6cee69 --- /dev/null +++ b/Examples/test-suite/go/profiletest_runme.go @@ -0,0 +1,38 @@ +package main + +import "fmt" +import "./profiletest" + +func main() { + a := profiletest.NewA() + if false { + fmt.Println(a) + } + + b := profiletest.NewB() + fn := func(a profiletest.A) profiletest.A { return b.Fn(a) } + i := 50000 + for i != 0 { + a = fn(a) //1 + a = fn(a) //2 + a = fn(a) //3 + a = fn(a) //4 + a = fn(a) //5 + a = fn(a) //6 + a = fn(a) //7 + a = fn(a) //8 + a = fn(a) //9 + a = fn(a) //10 + a = fn(a) //1 + a = fn(a) //2 + a = fn(a) //3 + a = fn(a) //4 + a = fn(a) //5 + a = fn(a) //6 + a = fn(a) //7 + a = fn(a) //8 + a = fn(a) //9 + a = fn(a) //20 + i -= 1 + } +} diff --git a/Examples/test-suite/go/refcount_runme.go b/Examples/test-suite/go/refcount_runme.go new file mode 100644 index 000000000..fdb271cc6 --- /dev/null +++ b/Examples/test-suite/go/refcount_runme.go @@ -0,0 +1,32 @@ +package main + +import . "./refcount" + +// very innocent example + +func main() { + a := NewA3() + _ = NewB(a) + b2 := BCreate(a) + + if a.Ref_count() != 3 { + panic("This program will crash... now") + } + + rca := b2.Get_rca() + // _ = BCreate(rca) + _ = rca + + if a.Ref_count() != 4 { + panic("This program will crash... now") + } + + /* Requires smart pointer support. + v := NewVector_A(2) + v.Set(0, a) + v.Set(1, a) + + _ = v.Get(0) + DeleteVector_A(v) + */ +} diff --git a/Examples/test-suite/go/reference_global_vars_runme.go b/Examples/test-suite/go/reference_global_vars_runme.go new file mode 100644 index 000000000..b8cbb304a --- /dev/null +++ b/Examples/test-suite/go/reference_global_vars_runme.go @@ -0,0 +1,98 @@ +package main + +import . "./reference_global_vars" + +func main() { + // const class reference variable + if GetconstTC().GetNum() != 33 { + panic(0) + } + + // primitive reference variables + SetVar_bool(Createref_bool(false)) + if Value_bool(GetVar_bool()) != false { + println(1, GetVar_bool(), Value_bool(GetVar_bool())) + panic(0) + } + + SetVar_bool(Createref_bool(true)) + if Value_bool(GetVar_bool()) != true { + println(2, GetVar_bool(), Value_bool(GetVar_bool())) + panic(0) + } + + SetVar_char(Createref_char('w')) + if Value_char(GetVar_char()) != 'w' { + println(3, GetVar_char(), Value_char(GetVar_char())) + panic(0) + } + + SetVar_unsigned_char(Createref_unsigned_char(10)) + if Value_unsigned_char(GetVar_unsigned_char()) != 10 { + println(4, GetVar_unsigned_char(), Value_unsigned_char(GetVar_unsigned_char())) + panic(0) + } + + SetVar_signed_char(Createref_signed_char(10)) + if Value_signed_char(GetVar_signed_char()) != 10 { + panic(0) + } + + SetVar_short(Createref_short(10)) + if Value_short(GetVar_short()) != 10 { + panic(0) + } + + SetVar_unsigned_short(Createref_unsigned_short(10)) + if Value_unsigned_short(GetVar_unsigned_short()) != 10 { + panic(0) + } + + SetVar_int(Createref_int(10)) + if Value_int(GetVar_int()) != 10 { + panic(0) + } + + SetVar_unsigned_int(Createref_unsigned_int(10)) + if Value_unsigned_int(GetVar_unsigned_int()) != 10 { + panic(0) + } + + SetVar_long(Createref_long(10)) + if Value_long(GetVar_long()) != 10 { + panic(0) + } + + SetVar_unsigned_long(Createref_unsigned_long(10)) + if Value_unsigned_long(GetVar_unsigned_long()) != 10 { + panic(0) + } + + SetVar_long_long(Createref_long_long(0x6FFFFFFFFFFFFFF8)) + if Value_long_long(GetVar_long_long()) != 0x6FFFFFFFFFFFFFF8 { + panic(0) + } + + //ull = abs(0xFFFFFFF2FFFFFFF0) + ull := uint64(55834574864) + SetVar_unsigned_long_long(Createref_unsigned_long_long(ull)) + if Value_unsigned_long_long(GetVar_unsigned_long_long()) != ull { + panic(0) + } + + SetVar_float(Createref_float(10.5)) + if Value_float(GetVar_float()) != 10.5 { + panic(0) + } + + SetVar_double(Createref_double(10.5)) + if Value_double(GetVar_double()) != 10.5 { + panic(0) + } + + // class reference variable + SetVar_TestClass(Createref_TestClass(NewTestClass(20))) + if Value_TestClass(GetVar_TestClass()).GetNum() != 20 { + panic(0) + } +} diff --git a/Examples/test-suite/go/rename_scope_runme.go b/Examples/test-suite/go/rename_scope_runme.go new file mode 100644 index 000000000..995f8c64d --- /dev/null +++ b/Examples/test-suite/go/rename_scope_runme.go @@ -0,0 +1,18 @@ +package main + +import . "./rename_scope" + +func main() { + a := NewNatural_UP() + b := NewNatural_BP() + + if a.Rtest() != 1 { + panic(0) + } + + if b.Rtest() != 1 { + panic(0) + } + + _ = Equals +} diff --git a/Examples/test-suite/go/rename_strip_encoder_runme.go b/Examples/test-suite/go/rename_strip_encoder_runme.go new file mode 100644 index 000000000..1d0bcb660 --- /dev/null +++ b/Examples/test-suite/go/rename_strip_encoder_runme.go @@ -0,0 +1,9 @@ +package main + +import . "./rename_strip_encoder" + +func main() { + _ = NewSomeWidget() + a := NewAnotherWidget() + a.DoSomething() +} diff --git a/Examples/test-suite/go/ret_by_value_runme.go b/Examples/test-suite/go/ret_by_value_runme.go new file mode 100644 index 000000000..44743d2b7 --- /dev/null +++ b/Examples/test-suite/go/ret_by_value_runme.go @@ -0,0 +1,14 @@ +package main + +import "./ret_by_value" + +func main() { + a := ret_by_value.Get_test() + if a.GetMyInt() != 100 { + panic(0) + } + + if a.GetMyShort() != 200 { + panic(0) + } +} diff --git a/Examples/test-suite/go/return_const_value_runme.go b/Examples/test-suite/go/return_const_value_runme.go new file mode 100644 index 000000000..790921b74 --- /dev/null +++ b/Examples/test-suite/go/return_const_value_runme.go @@ -0,0 +1,15 @@ +package main + +import "./return_const_value" + +func main() { + p := return_const_value.Foo_ptrGetPtr() + if p.GetVal() != 17 { + panic("Runtime test1 failed") + } + + p = return_const_value.Foo_ptrGetConstPtr() + if p.GetVal() != 17 { + panic("Runtime test2 failed") + } +} diff --git a/Examples/test-suite/go/smart_pointer_extend_runme.go b/Examples/test-suite/go/smart_pointer_extend_runme.go new file mode 100644 index 000000000..ee5ce0538 --- /dev/null +++ b/Examples/test-suite/go/smart_pointer_extend_runme.go @@ -0,0 +1,40 @@ +package main + +import . "./smart_pointer_extend" + +func main() { + f := NewFoo() + b := NewBar(f) + + if b.Extension() != f.Extension() { + panic(0) + } + + b2 := NewCBase() + d := NewCDerived() + p := NewCPtr() + + if b2.Bar() != p.Bar() { + panic(0) + } + + if d.Foo() != p.Foo() { + panic(0) + } + + if CBaseHello() != p.Hello() { + panic(0) + } + + d2 := NewDFoo() + + dp := NewDPtrFoo(d2) + + if DFooSExt(1) != dp.SExt(1) { + panic(0) + } + + if d2.Ext(1) != dp.Ext(1) { + panic(0) + } +} diff --git a/Examples/test-suite/go/smart_pointer_member_runme.go b/Examples/test-suite/go/smart_pointer_member_runme.go new file mode 100644 index 000000000..d0da83cef --- /dev/null +++ b/Examples/test-suite/go/smart_pointer_member_runme.go @@ -0,0 +1,30 @@ +package main + +import "fmt" +import . "./smart_pointer_member" + +func main() { + f := NewFoos() + f.SetY(1) + + if f.GetY() != 1 { + panic(0) + } + + b := NewBar(f) + b.SetY(2) + + if f.GetY() != 2 { + fmt.Println(f.GetY()) + fmt.Println(b.GetY()) + panic(0) + } + + if b.GetX() != f.GetX() { + panic(0) + } + + if b.GetZ() != GetFoosZ() { + panic(0) + } +} diff --git a/Examples/test-suite/go/smart_pointer_multi_runme.go b/Examples/test-suite/go/smart_pointer_multi_runme.go new file mode 100644 index 000000000..d1a5f92f4 --- /dev/null +++ b/Examples/test-suite/go/smart_pointer_multi_runme.go @@ -0,0 +1,20 @@ +package main + +import . "./smart_pointer_multi" + +func main() { + f := NewFoo() + b := NewBar(f) + s := NewSpam(b) + g := NewGrok(b) + + s.SetX(3) + if s.Getx() != 3 { + panic(0) + } + + g.SetX(4) + if g.Getx() != 4 { + panic(0) + } +} diff --git a/Examples/test-suite/go/smart_pointer_multi_typedef_runme.go b/Examples/test-suite/go/smart_pointer_multi_typedef_runme.go new file mode 100644 index 000000000..f71740bbb --- /dev/null +++ b/Examples/test-suite/go/smart_pointer_multi_typedef_runme.go @@ -0,0 +1,20 @@ +package main + +import . "./smart_pointer_multi_typedef" + +func main() { + f := NewFoo() + b := NewBar(f) + s := NewSpam(b) + g := NewGrok(b) + + s.SetX(3) + if s.Getx() != 3 { + panic(0) + } + + g.SetX(4) + if g.Getx() != 4 { + panic(0) + } +} diff --git a/Examples/test-suite/go/smart_pointer_overload_runme.go b/Examples/test-suite/go/smart_pointer_overload_runme.go new file mode 100644 index 000000000..0a06aa080 --- /dev/null +++ b/Examples/test-suite/go/smart_pointer_overload_runme.go @@ -0,0 +1,28 @@ +package main + +import . "./smart_pointer_overload" + +func main() { + f := NewFoo() + b := NewBar(f) + + if f.Test(3) != 1 { + panic(0) + } + if f.Test(float64(3.5)) != 2 { + panic(0) + } + if f.Test("hello") != 3 { + panic(0) + } + + if b.Test(3) != 1 { + panic(0) + } + if b.Test(float64(3.5)) != 2 { + panic(0) + } + if b.Test("hello") != 3 { + panic(0) + } +} diff --git a/Examples/test-suite/go/smart_pointer_rename_runme.go b/Examples/test-suite/go/smart_pointer_rename_runme.go new file mode 100644 index 000000000..678c305c8 --- /dev/null +++ b/Examples/test-suite/go/smart_pointer_rename_runme.go @@ -0,0 +1,20 @@ +package main + +import . "./smart_pointer_rename" + +func main() { + f := NewFoo() + b := NewBar(f) + + if b.Test() != 3 { + panic(0) + } + + if b.Ftest1(1) != 1 { + panic(0) + } + + if b.Ftest2(2, 3) != 2 { + panic(0) + } +} diff --git a/Examples/test-suite/go/smart_pointer_simple_runme.go b/Examples/test-suite/go/smart_pointer_simple_runme.go new file mode 100644 index 000000000..328654225 --- /dev/null +++ b/Examples/test-suite/go/smart_pointer_simple_runme.go @@ -0,0 +1,19 @@ +package main + +import . "./smart_pointer_simple" + +func main() { + f := NewFoo() + b := NewBar(f) + + b.SetX(3) + if b.Getx() != 3 { + panic(0) + } + + fp := b.X__deref__() + fp.SetX(4) + if fp.Getx() != 4 { + panic(0) + } +} diff --git a/Examples/test-suite/go/smart_pointer_templatevariables_runme.go b/Examples/test-suite/go/smart_pointer_templatevariables_runme.go new file mode 100644 index 000000000..bf58ba52c --- /dev/null +++ b/Examples/test-suite/go/smart_pointer_templatevariables_runme.go @@ -0,0 +1,22 @@ +package main + +import . "./smart_pointer_templatevariables" + +func main() { + d := NewDiffImContainerPtr_D(Create(1234, 5678)) + + if d.GetId() != 1234 { + panic(0) + } + //if (d.xyz != 5678): + // panic(0) + + d.SetId(4321) + //d.xyz = 8765 + + if d.GetId() != 4321 { + panic(0) + } + //if (d.xyz != 8765): + // panic(0) +} diff --git a/Examples/test-suite/go/smart_pointer_typedef_runme.go b/Examples/test-suite/go/smart_pointer_typedef_runme.go new file mode 100644 index 000000000..a67a0ccda --- /dev/null +++ b/Examples/test-suite/go/smart_pointer_typedef_runme.go @@ -0,0 +1,19 @@ +package main + +import . "./smart_pointer_typedef" + +func main() { + f := NewFoo() + b := NewBar(f) + + b.SetX(3) + if b.Getx() != 3 { + panic(0) + } + + fp := b.X__deref__() + fp.SetX(4) + if fp.Getx() != 4 { + panic(0) + } +} diff --git a/Examples/test-suite/go/sneaky1_runme.go b/Examples/test-suite/go/sneaky1_runme.go new file mode 100644 index 000000000..ee38ae21b --- /dev/null +++ b/Examples/test-suite/go/sneaky1_runme.go @@ -0,0 +1,10 @@ +package main + +import "./sneaky1" + +func main() { + _ = sneaky1.Add(3, 4) + _ = sneaky1.Subtract(3, 4) + _ = sneaky1.Mul(3, 4) + _ = sneaky1.Divide(3, 4) +} diff --git a/Examples/test-suite/go/special_variable_macros_runme.go b/Examples/test-suite/go/special_variable_macros_runme.go new file mode 100644 index 000000000..366575551 --- /dev/null +++ b/Examples/test-suite/go/special_variable_macros_runme.go @@ -0,0 +1,25 @@ +package main + +import "./special_variable_macros" + +func main() { + name := special_variable_macros.NewNames() + if special_variable_macros.TestFred(name) != "none" { + panic("test failed") + } + if special_variable_macros.TestJack(name) != "$specialname" { + panic("test failed") + } + if special_variable_macros.TestJill(name) != "jilly" { + panic("test failed") + } + if special_variable_macros.TestMary(name) != "SWIGTYPE_p_NameWrap" { + panic("test failed") + } + if special_variable_macros.TestJim(name) != "multiname num" { + panic("test failed") + } + if special_variable_macros.TestJohn(special_variable_macros.NewPairIntBool(10, false)) != 123 { + panic("test failed") + } +} diff --git a/Examples/test-suite/go/static_const_member_2_runme.go b/Examples/test-suite/go/static_const_member_2_runme.go new file mode 100644 index 000000000..0d345c3d6 --- /dev/null +++ b/Examples/test-suite/go/static_const_member_2_runme.go @@ -0,0 +1,18 @@ +package main + +import . "./static_const_member_2" + +func main() { + _ = NewTest_int() + + _ = CavityPackFlagsForward_field + _ = Test_intCurrent_profile + _ = Test_intRightIndex + _ = CavityPackFlagsBackward_field + _ = Test_intLeftIndex + // _ = GetTest_int_Cavity_flags() + + if GetFooBAZ().GetVal() != 2*GetFooBAR().GetVal() { + panic(0) + } +} diff --git a/Examples/test-suite/go/struct_initialization_runme.go b/Examples/test-suite/go/struct_initialization_runme.go new file mode 100644 index 000000000..58ac25010 --- /dev/null +++ b/Examples/test-suite/go/struct_initialization_runme.go @@ -0,0 +1,29 @@ +package main + +import . "./struct_initialization" + +func main() { + if GetInstanceC1().GetX() != 10 { + panic(0) + } + + if GetInstanceD1().GetX() != 10 { + panic(0) + } + + if GetInstanceD2().GetX() != 20 { + panic(0) + } + + if GetInstanceD3().GetX() != 30 { + panic(0) + } + + if GetInstanceE1().GetX() != 1 { + panic(0) + } + + if GetInstanceF1().GetX() != 1 { + panic(0) + } +} diff --git a/Examples/test-suite/go/struct_rename_runme.go b/Examples/test-suite/go/struct_rename_runme.go new file mode 100644 index 000000000..845dac5be --- /dev/null +++ b/Examples/test-suite/go/struct_rename_runme.go @@ -0,0 +1,7 @@ +package main + +import "./struct_rename" + +func main() { + _ = struct_rename.NewBar() +} diff --git a/Examples/test-suite/go/struct_value_runme.go b/Examples/test-suite/go/struct_value_runme.go new file mode 100644 index 000000000..d0b60bd23 --- /dev/null +++ b/Examples/test-suite/go/struct_value_runme.go @@ -0,0 +1,17 @@ +package main + +import "./struct_value" + +func main() { + b := struct_value.NewBar() + + b.GetA().SetX(3) + if b.GetA().GetX() != 3 { + panic(0) + } + + b.GetB().SetX(3) + if b.GetB().GetX() != 3 { + panic(0) + } +} diff --git a/Examples/test-suite/go/template_default_arg_runme.go b/Examples/test-suite/go/template_default_arg_runme.go new file mode 100644 index 000000000..5be7f6d56 --- /dev/null +++ b/Examples/test-suite/go/template_default_arg_runme.go @@ -0,0 +1,107 @@ +package main + +import "./template_default_arg" + +func main() { + helloInt := template_default_arg.NewHello_int() + helloInt.Foo(template_default_arg.Hello_intHi) + + x := template_default_arg.NewX_int() + if x.Meth(float64(20.0), 200).(int) != 200 { + panic("X_int test 1 failed") + } + if x.Meth(20).(int) != 20 { + panic("X_int test 2 failed") + } + if x.Meth().(int) != 0 { + panic("X_int test 3 failed") + } + + y := template_default_arg.NewY_unsigned() + if y.Meth(float64(20.0), uint(200)).(uint) != 200 { + panic("Y_unsigned test 1 failed") + } + if y.Meth(uint(20)).(uint) != 20 { + panic("Y_unsigned test 2 failed") + } + if y.Meth().(uint) != 0 { + panic("Y_unsigned test 3 failed") + } + + _ = template_default_arg.NewX_longlong() + _ = template_default_arg.NewX_longlong(float64(20.0)) + _ = template_default_arg.NewX_longlong(float64(20.0), int64(200)) + + _ = template_default_arg.NewX_int() + _ = template_default_arg.NewX_int(float64(20.0)) + _ = template_default_arg.NewX_int(float64(20.0), 200) + + _ = template_default_arg.NewX_hello_unsigned() + _ = template_default_arg.NewX_hello_unsigned(float64(20.0)) + _ = template_default_arg.NewX_hello_unsigned(float64(20.0), template_default_arg.NewHello_int()) + + yy := template_default_arg.NewY_hello_unsigned() + yy.Meth(float64(20.0), template_default_arg.NewHello_int()) + yy.Meth(template_default_arg.NewHello_int()) + yy.Meth() + + fz := template_default_arg.NewFoo_Z_8() + xz := template_default_arg.NewX_Foo_Z_8() + _ = xz.Meth(fz) + + + // Templated functions + + // plain function: int ott(Foo) + if template_default_arg.Ott(template_default_arg.NewFoo_int()) != 30 { + panic("ott test 1 failed") + } + + // %template(ott) ott + if template_default_arg.Ott() != 10 { + panic("ott test 2 failed") + } + if template_default_arg.Ott(1) != 10 { + panic("ott test 3 failed") + } + if template_default_arg.Ott(1, 1) != 10 { + panic("ott test 4 failed") + } + + if template_default_arg.Ott("hi") != 20 { + panic("ott test 5 failed") + } + if template_default_arg.Ott("hi", 1) != 20 { + panic("ott test 6 failed") + } + if template_default_arg.Ott("hi", 1, 1) != 20 { + panic("ott test 7 failed") + } + + // %template(ott) ott + if template_default_arg.Ottstring(template_default_arg.NewHello_int(), "hi") != 40 { + panic("ott test 8 failed") + } + + if template_default_arg.Ottstring(template_default_arg.NewHello_int()) != 40 { + panic("ott test 9 failed") + } + + // %template(ott) ott + if template_default_arg.Ottint(template_default_arg.NewHello_int(), 1) != 50 { + panic("ott test 10 failed") + } + + if template_default_arg.Ottint(template_default_arg.NewHello_int()) != 50 { + panic("ott test 11 failed") + } + + // %template(ott) ott + if template_default_arg.Ott(template_default_arg.NewHello_int(), float64(1.0)) != 60 { + panic("ott test 12 failed") + } + + if template_default_arg.Ott(template_default_arg.NewHello_int()) != 60 { + panic("ott test 13 failed") + } +} diff --git a/Examples/test-suite/go/template_extend1_runme.go b/Examples/test-suite/go/template_extend1_runme.go new file mode 100644 index 000000000..5d6d376f5 --- /dev/null +++ b/Examples/test-suite/go/template_extend1_runme.go @@ -0,0 +1,16 @@ +package main + +import "./template_extend1" + +func main() { + a := template_extend1.NewLBaz() + b := template_extend1.NewDBaz() + + if a.Foo() != "lBaz::foo" { + panic(0) + } + + if b.Foo() != "dBaz::foo" { + panic(0) + } +} diff --git a/Examples/test-suite/go/template_extend2_runme.go b/Examples/test-suite/go/template_extend2_runme.go new file mode 100644 index 000000000..312410e27 --- /dev/null +++ b/Examples/test-suite/go/template_extend2_runme.go @@ -0,0 +1,16 @@ +package main + +import "./template_extend2" + +func main() { + a := template_extend2.NewLBaz() + b := template_extend2.NewDBaz() + + if a.Foo() != "lBaz::foo" { + panic(0) + } + + if b.Foo() != "dBaz::foo" { + panic(0) + } +} diff --git a/Examples/test-suite/go/template_inherit_runme.go b/Examples/test-suite/go/template_inherit_runme.go new file mode 100644 index 000000000..c0aca77c4 --- /dev/null +++ b/Examples/test-suite/go/template_inherit_runme.go @@ -0,0 +1,72 @@ +package main + +import . "./template_inherit" + +func main() { + a := NewFooInt() + b := NewFooDouble() + c := NewBarInt() + d := NewBarDouble() + e := NewFooUInt() + f := NewBarUInt() + + if a.Blah() != "Foo" { + panic(0) + } + + if b.Blah() != "Foo" { + panic(0) + } + + if e.Blah() != "Foo" { + panic(0) + } + + if c.Blah() != "Bar" { + panic(0) + } + + if d.Blah() != "Bar" { + panic(0) + } + + if f.Blah() != "Bar" { + panic(0) + } + + if c.Foomethod() != "foomethod" { + panic(0) + } + + if d.Foomethod() != "foomethod" { + panic(0) + } + + if f.Foomethod() != "foomethod" { + panic(0) + } + + if Invoke_blah_int(a) != "Foo" { + panic(0) + } + + if Invoke_blah_int(c) != "Bar" { + panic(0) + } + + if Invoke_blah_double(b) != "Foo" { + panic(0) + } + + if Invoke_blah_double(d) != "Bar" { + panic(0) + } + + if Invoke_blah_uint(e) != "Foo" { + panic(0) + } + + if Invoke_blah_uint(f) != "Bar" { + panic(0) + } +} diff --git a/Examples/test-suite/go/template_ns4_runme.go b/Examples/test-suite/go/template_ns4_runme.go new file mode 100644 index 000000000..4caf8f587 --- /dev/null +++ b/Examples/test-suite/go/template_ns4_runme.go @@ -0,0 +1,10 @@ +package main + +import . "./template_ns4" + +func main() { + d := Make_Class_DD() + if d.Test() != "test" { + panic(0) + } +} diff --git a/Examples/test-suite/go/template_ns_runme.go b/Examples/test-suite/go/template_ns_runme.go new file mode 100644 index 000000000..5d463f814 --- /dev/null +++ b/Examples/test-suite/go/template_ns_runme.go @@ -0,0 +1,26 @@ +package main + +import . "./template_ns" + +func main() { + p1 := NewPairii(2, 3) + p2 := NewPairii(p1) + + if p2.GetFirst() != 2 { + panic(0) + } + if p2.GetSecond() != 3 { + panic(0) + } + + p3 := NewPairdd(float64(3.5), float64(2.5)) + p4 := NewPairdd(p3) + + if p4.GetFirst() != 3.5 { + panic(0) + } + + if p4.GetSecond() != 2.5 { + panic(0) + } +} diff --git a/Examples/test-suite/go/template_opaque_runme.go b/Examples/test-suite/go/template_opaque_runme.go new file mode 100644 index 000000000..c22b71946 --- /dev/null +++ b/Examples/test-suite/go/template_opaque_runme.go @@ -0,0 +1,9 @@ +package main + +import "./template_opaque" + +func main() { + v := template_opaque.NewOpaqueVectorType(10) + + template_opaque.FillVector(v) +} diff --git a/Examples/test-suite/go/template_ref_type_runme.go b/Examples/test-suite/go/template_ref_type_runme.go new file mode 100644 index 000000000..e4bf626fb --- /dev/null +++ b/Examples/test-suite/go/template_ref_type_runme.go @@ -0,0 +1,9 @@ +package main + +import "./template_ref_type" + +func main() { + xr := template_ref_type.NewXC() + y := template_ref_type.NewY() + y.Find(xr) +} diff --git a/Examples/test-suite/go/template_rename_runme.go b/Examples/test-suite/go/template_rename_runme.go new file mode 100644 index 000000000..757ac7355 --- /dev/null +++ b/Examples/test-suite/go/template_rename_runme.go @@ -0,0 +1,16 @@ +package main + +import "./template_rename" + +func main() { + i := template_rename.NewIFoo() + d := template_rename.NewDFoo() + + _ = i.Blah_test(4) + _ = i.Spam_test(5) + _ = i.Groki_test(6) + + _ = d.Blah_test(7) + _ = d.Spam(8) + _ = d.Grok_test(9) +} diff --git a/Examples/test-suite/go/template_static_runme.go b/Examples/test-suite/go/template_static_runme.go new file mode 100644 index 000000000..7fa50760a --- /dev/null +++ b/Examples/test-suite/go/template_static_runme.go @@ -0,0 +1,7 @@ +package main + +import . "./template_static" + +func main() { + FooBar_double(1) +} diff --git a/Examples/test-suite/go/template_tbase_template_runme.go b/Examples/test-suite/go/template_tbase_template_runme.go new file mode 100644 index 000000000..9a52e2fac --- /dev/null +++ b/Examples/test-suite/go/template_tbase_template_runme.go @@ -0,0 +1,10 @@ +package main + +import . "./template_tbase_template" + +func main() { + a := Make_Class_dd() + if a.Test() != "test" { + panic(0) + } +} diff --git a/Examples/test-suite/go/template_type_namespace_runme.go b/Examples/test-suite/go/template_type_namespace_runme.go new file mode 100644 index 000000000..a3712ff59 --- /dev/null +++ b/Examples/test-suite/go/template_type_namespace_runme.go @@ -0,0 +1,8 @@ +package main + +import . "./template_type_namespace" + +func main() { + if Foo().Get(0) == "" { + } +} diff --git a/Examples/test-suite/go/template_typedef_cplx3_runme.go b/Examples/test-suite/go/template_typedef_cplx3_runme.go new file mode 100644 index 000000000..f827d7a1e --- /dev/null +++ b/Examples/test-suite/go/template_typedef_cplx3_runme.go @@ -0,0 +1,29 @@ +package main + +import . "./template_typedef_cplx3" + +func main() { + // this is OK + + + s := NewSin() + s.Get_base_value() + s.Get_value() + s.Get_arith_value() + My_func_r(s) + Make_Multiplies_double_double_double_double(s, s) + + z := NewCSin() + z.Get_base_value() + z.Get_value() + z.Get_arith_value() + My_func_c(z) + Make_Multiplies_complex_complex_complex_complex(z, z) + + // Here we fail + d := Make_Identity_double() + My_func_r(d) + + c := Make_Identity_complex() + My_func_c(c) +} diff --git a/Examples/test-suite/go/template_typedef_cplx4_runme.go b/Examples/test-suite/go/template_typedef_cplx4_runme.go new file mode 100644 index 000000000..9021cf135 --- /dev/null +++ b/Examples/test-suite/go/template_typedef_cplx4_runme.go @@ -0,0 +1,29 @@ +package main + +import . "./template_typedef_cplx4" + +func main() { + // this is OK + + + s := NewSin() + s.Get_base_value() + s.Get_value() + s.Get_arith_value() + My_func_r(s) + Make_Multiplies_double_double_double_double(s, s) + + z := NewCSin() + z.Get_base_value() + z.Get_value() + z.Get_arith_value() + My_func_c(z) + Make_Multiplies_complex_complex_complex_complex(z, z) + + // Here we fail + d := Make_Identity_double() + My_func_r(d) + + c := Make_Identity_complex() + My_func_c(c) +} diff --git a/Examples/test-suite/go/template_typedef_import_runme.go b/Examples/test-suite/go/template_typedef_import_runme.go new file mode 100644 index 000000000..8528b9a93 --- /dev/null +++ b/Examples/test-suite/go/template_typedef_import_runme.go @@ -0,0 +1,30 @@ +package main + +import "template_typedef_cplx2" +import "template_typedef_import" + +func main() { + // this is OK + + + s := template_typedef_import.NewSin() + s.Get_base_value() + s.Get_value() + s.Get_arith_value() + template_typedef_import.My_func_r(s) + template_typedef_cplx2.Make_Multiplies_double_double_double_double(s, s) + + z := template_typedef_import.NewCSin() + z.Get_base_value() + z.Get_value() + z.Get_arith_value() + template_typedef_import.My_func_c(z) + template_typedef_cplx2.Make_Multiplies_complex_complex_complex_complex(z, z) + + // Here we fail + d := template_typedef_cplx2.Make_Identity_double() + template_typedef_import.My_func_r(d) + + c := template_typedef_cplx2.Make_Identity_complex() + template_typedef_import.My_func_c(c) +} diff --git a/Examples/test-suite/go/threads_exception_runme.go b/Examples/test-suite/go/threads_exception_runme.go new file mode 100644 index 000000000..742a827bd --- /dev/null +++ b/Examples/test-suite/go/threads_exception_runme.go @@ -0,0 +1,66 @@ +package main + +import "strings" +import "./threads_exception" + +func main() { + t := threads_exception.NewTest() + + error := true + func() { + defer func() { + error = recover() == nil + }() + t.Unknown() + }() + if error { + panic(0) + } + + error = true + func() { + defer func() { + error = strings.Index(recover().(string), "int exception") == -1 + }() + t.Simple() + }() + if error { + panic(0) + } + + error = true + func() { + defer func() { + error = recover().(string) != "I died." + }() + t.Message() + }() + if error { + panic(0) + } + + error = true + func() { + defer func() { + e := recover().(string) + error = strings.Index(e, "Exc exception") == -1 + }() + t.Hosed() + }() + if error { + panic(0) + } + + for i := 1; i < 4; i++ { + error = true + func() { + defer func() { + error = recover() == nil + }() + t.Multi(i) + }() + if error { + panic(0) + } + } +} diff --git a/Examples/test-suite/go/typedef_class_runme.go b/Examples/test-suite/go/typedef_class_runme.go new file mode 100644 index 000000000..ec25162de --- /dev/null +++ b/Examples/test-suite/go/typedef_class_runme.go @@ -0,0 +1,11 @@ +package main + +import "./typedef_class" + +func main() { + a := typedef_class.NewRealA() + a.SetA(3) + + b := typedef_class.NewB() + b.TestA(a) +} diff --git a/Examples/test-suite/go/typedef_inherit_runme.go b/Examples/test-suite/go/typedef_inherit_runme.go new file mode 100644 index 000000000..49097999c --- /dev/null +++ b/Examples/test-suite/go/typedef_inherit_runme.go @@ -0,0 +1,31 @@ +package main + +import "./typedef_inherit" + +func main() { + a := typedef_inherit.NewFoo() + b := typedef_inherit.NewBar() + + x := typedef_inherit.Do_blah(a) + if x != "Foo::blah" { + panic(x) + } + + x = typedef_inherit.Do_blah(b) + if x != "Bar::blah" { + panic(x) + } + + c := typedef_inherit.NewSpam() + d := typedef_inherit.NewGrok() + + x = typedef_inherit.Do_blah2(c) + if x != "Spam::blah" { + panic(x) + } + + x = typedef_inherit.Do_blah2(d) + if x != "Grok::blah" { + panic(x) + } +} diff --git a/Examples/test-suite/go/typedef_scope_runme.go b/Examples/test-suite/go/typedef_scope_runme.go new file mode 100644 index 000000000..1c4314427 --- /dev/null +++ b/Examples/test-suite/go/typedef_scope_runme.go @@ -0,0 +1,16 @@ +package main + +import "./typedef_scope" + +func main() { + b := typedef_scope.NewBar() + x := b.Test1(42, "hello") + if x != 42 { + panic("Failed!!") + } + + xb := b.Test2(42, "hello") + if xb != "hello" { + panic("Failed!!") + } +} diff --git a/Examples/test-suite/go/typemap_namespace_runme.go b/Examples/test-suite/go/typemap_namespace_runme.go new file mode 100644 index 000000000..45184fd1e --- /dev/null +++ b/Examples/test-suite/go/typemap_namespace_runme.go @@ -0,0 +1,13 @@ +package main + +import . "./typemap_namespace" + +func main() { + if Test1("hello") != "hello" { + panic(0) + } + + if Test2("hello") != "hello" { + panic(0) + } +} diff --git a/Examples/test-suite/go/typemap_ns_using_runme.go b/Examples/test-suite/go/typemap_ns_using_runme.go new file mode 100644 index 000000000..877e44b3a --- /dev/null +++ b/Examples/test-suite/go/typemap_ns_using_runme.go @@ -0,0 +1,9 @@ +package main + +import "./typemap_ns_using" + +func main() { + if typemap_ns_using.Spam(37) != 37 { + panic(0) + } +} diff --git a/Examples/test-suite/go/typemap_out_optimal_runme.go b/Examples/test-suite/go/typemap_out_optimal_runme.go new file mode 100644 index 000000000..7cbd0ad9b --- /dev/null +++ b/Examples/test-suite/go/typemap_out_optimal_runme.go @@ -0,0 +1,8 @@ +package main + +import . "./typemap_out_optimal" + +func main() { + SetXXDebug(false) + _ = XXCreate() +} diff --git a/Examples/test-suite/go/typename_runme.go b/Examples/test-suite/go/typename_runme.go new file mode 100644 index 000000000..0bc15f11a --- /dev/null +++ b/Examples/test-suite/go/typename_runme.go @@ -0,0 +1,13 @@ +package main + +import "./typename" + +func main() { + f := typename.NewFoo() + b := typename.NewBar() + + var x float64 = typename.TwoFoo(f) + var y int = typename.TwoBar(b) + _ = x + _ = y +} diff --git a/Examples/test-suite/go/unions_runme.go b/Examples/test-suite/go/unions_runme.go new file mode 100644 index 000000000..ba9c27b17 --- /dev/null +++ b/Examples/test-suite/go/unions_runme.go @@ -0,0 +1,51 @@ +// This is the union runtime testcase. It ensures that values within a +// union embedded within a struct can be set and read correctly. + +package main + +import "./unions" + +func main() { + // Create new instances of SmallStruct and BigStruct for later use + small := unions.NewSmallStruct() + small.SetJill(200) + + big := unions.NewBigStruct() + big.SetSmallstruct(small) + big.SetJack(300) + + // Use SmallStruct then BigStruct to setup EmbeddedUnionTest. + // Ensure values in EmbeddedUnionTest are set correctly for each. + eut := unions.NewEmbeddedUnionTest() + + // First check the SmallStruct in EmbeddedUnionTest + eut.SetNumber(1) + eut.GetUni().SetSmall(small) + Jill1 := eut.GetUni().GetSmall().GetJill() + if Jill1 != 200 { + panic("Runtime test1 failed") + } + + Num1 := eut.GetNumber() + if Num1 != 1 { + panic("Runtime test2 failed") + } + + // Secondly check the BigStruct in EmbeddedUnionTest + eut.SetNumber(2) + eut.GetUni().SetBig(big) + Jack1 := eut.GetUni().GetBig().GetJack() + if Jack1 != 300 { + panic("Runtime test3 failed") + } + + Jill2 := eut.GetUni().GetBig().GetSmallstruct().GetJill() + if Jill2 != 200 { + panic("Runtime test4 failed") + } + + Num2 := eut.GetNumber() + if Num2 != 2 { + panic("Runtime test5 failed") + } +} diff --git a/Examples/test-suite/go/using1_runme.go b/Examples/test-suite/go/using1_runme.go new file mode 100644 index 000000000..8cc571288 --- /dev/null +++ b/Examples/test-suite/go/using1_runme.go @@ -0,0 +1,9 @@ +package main + +import "./using1" + +func main() { + if using1.Spam(37) != 37 { + panic(0) + } +} diff --git a/Examples/test-suite/go/using2_runme.go b/Examples/test-suite/go/using2_runme.go new file mode 100644 index 000000000..f679b0c40 --- /dev/null +++ b/Examples/test-suite/go/using2_runme.go @@ -0,0 +1,9 @@ +package main + +import "./using2" + +func main() { + if using2.Spam(37) != 37 { + panic(0) + } +} diff --git a/Examples/test-suite/go/using_composition_runme.go b/Examples/test-suite/go/using_composition_runme.go new file mode 100644 index 000000000..1602e9627 --- /dev/null +++ b/Examples/test-suite/go/using_composition_runme.go @@ -0,0 +1,44 @@ +package main + +import . "./using_composition" + +func main() { + f := NewFooBar() + if f.Blah(3).(int) != 3 { + panic("FooBar::blah(int)") + } + + if f.Blah(float64(3.5)).(float64) != 3.5 { + panic("FooBar::blah(double)") + } + + if f.Blah("hello").(string) != "hello" { + panic("FooBar::blah(char *)") + } + + f2 := NewFooBar2() + if f2.Blah(3).(int) != 3 { + panic("FooBar2::blah(int)") + } + + if f2.Blah(float64(3.5)).(float64) != 3.5 { + panic("FooBar2::blah(double)") + } + + if f2.Blah("hello").(string) != "hello" { + panic("FooBar2::blah(char *)") + } + + f3 := NewFooBar3() + if f3.Blah(3).(int) != 3 { + panic("FooBar3::blah(int)") + } + + if f3.Blah(float64(3.5)).(float64) != 3.5 { + panic("FooBar3::blah(double)") + } + + if f3.Blah("hello").(string) != "hello" { + panic("FooBar3::blah(char *)") + } +} diff --git a/Examples/test-suite/go/using_extend_runme.go b/Examples/test-suite/go/using_extend_runme.go new file mode 100644 index 000000000..144fac47d --- /dev/null +++ b/Examples/test-suite/go/using_extend_runme.go @@ -0,0 +1,30 @@ +package main + +import . "./using_extend" + +func main() { + f := NewFooBar() + if f.Blah(3).(int) != 3 { + panic("blah(int)") + } + + if f.Blah(float64(3.5)).(float64) != 3.5 { + panic("blah(double)") + } + + if f.Blah("hello").(string) != "hello" { + panic("blah(char *)") + } + + if f.Blah(3, 4).(int) != 7 { + panic("blah(int,int)") + } + + if f.Blah(float64(3.5), float64(7.5)).(float64) != (3.5 + 7.5) { + panic("blah(double,double)") + } + + if f.Duh(3) != 3 { + panic("duh(int)") + } +} diff --git a/Examples/test-suite/go/using_inherit_runme.go b/Examples/test-suite/go/using_inherit_runme.go new file mode 100644 index 000000000..669ed4d5f --- /dev/null +++ b/Examples/test-suite/go/using_inherit_runme.go @@ -0,0 +1,59 @@ +package main + +import . "./using_inherit" + +func main() { + b := NewBar() + if b.Test(3).(int) != 3 { + panic("Bar::test(int)") + } + + if b.Test(float64(3.5)).(float64) != 3.5 { + panic("Bar::test(double)") + } + + b2 := NewBar2() + if b2.Test(3).(int) != 6 { + panic("Bar2::test(int)") + } + + if b2.Test(float64(3.5)).(float64) != 7.0 { + panic("Bar2::test(double)") + } + + b3 := NewBar3() + if b3.Test(3).(int) != 6 { + panic("Bar3::test(int)") + } + + if b3.Test(float64(3.5)).(float64) != 7.0 { + panic("Bar3::test(double)") + } + + b4 := NewBar4() + if b4.Test(3).(int) != 6 { + panic("Bar4::test(int)") + } + + if b4.Test(float64(3.5)).(float64) != 7.0 { + panic("Bar4::test(double)") + } + + bf1 := NewFred1() + if bf1.Test(3).(int) != 3 { + panic("Fred1::test(int)") + } + + if bf1.Test(float64(3.5)).(float64) != 7.0 { + panic("Fred1::test(double)") + } + + bf2 := NewFred2() + if bf2.Test(3).(int) != 3 { + panic("Fred2::test(int)") + } + + if bf2.Test(float64(3.5)).(float64) != 7.0 { + panic("Fred2::test(double)") + } +} diff --git a/Examples/test-suite/go/using_private_runme.go b/Examples/test-suite/go/using_private_runme.go new file mode 100644 index 000000000..d683ef856 --- /dev/null +++ b/Examples/test-suite/go/using_private_runme.go @@ -0,0 +1,20 @@ +package main + +import . "./using_private" + +func main() { + f := NewFooBar() + f.SetX(3) + + if f.Blah(4) != 4 { + panic("blah(int)") + } + + if f.Defaulted() != -1 { + panic("defaulted()") + } + + if f.Defaulted(222) != 222 { + panic("defaulted(222)") + } +} diff --git a/Examples/test-suite/go/using_protected_runme.go b/Examples/test-suite/go/using_protected_runme.go new file mode 100644 index 000000000..65edb5001 --- /dev/null +++ b/Examples/test-suite/go/using_protected_runme.go @@ -0,0 +1,12 @@ +package main + +import . "./using_protected" + +func main() { + f := NewFooBar() + f.SetX(3) + + if f.Blah(4) != 4 { + panic("blah(int)") + } +} diff --git a/Examples/test-suite/go/varargs_runme.go b/Examples/test-suite/go/varargs_runme.go new file mode 100644 index 000000000..4009c3ed3 --- /dev/null +++ b/Examples/test-suite/go/varargs_runme.go @@ -0,0 +1,26 @@ +package main + +import "./varargs" + +func main() { + if varargs.Test("Hello") != "Hello" { + panic("Failed") + } + + f := varargs.NewFoo("Greetings") + if f.GetStr() != "Greetings" { + panic("Failed") + } + + if f.Test("Hello") != "Hello" { + panic("Failed") + } + + if varargs.Test_def("Hello", 1) != "Hello" { + panic("Failed") + } + + if varargs.Test_def("Hello") != "Hello" { + panic("Failed") + } +} diff --git a/Examples/test-suite/go/virtual_derivation_runme.go b/Examples/test-suite/go/virtual_derivation_runme.go new file mode 100644 index 000000000..48a7033a2 --- /dev/null +++ b/Examples/test-suite/go/virtual_derivation_runme.go @@ -0,0 +1,12 @@ +package main + +import . "./virtual_derivation" + +// very innocent example + +func main() { + b := NewB(3) + if b.Get_a() != b.Get_b() { + panic("something is really wrong") + } +} diff --git a/Examples/test-suite/go/virtual_poly_runme.go b/Examples/test-suite/go/virtual_poly_runme.go new file mode 100644 index 000000000..7048ba8cf --- /dev/null +++ b/Examples/test-suite/go/virtual_poly_runme.go @@ -0,0 +1,43 @@ +package main + +import "./virtual_poly" + +func main() { + d := virtual_poly.NewNDouble(3.5) + i := virtual_poly.NewNInt(2) + + // the copy methods return the right polymorphic types + dc := d.Copy() + ic := i.Copy() + + if d.Get() != dc.Get() { + panic(0) + } + + if i.Get() != ic.Get() { + panic(0) + } + + virtual_poly.Incr(ic) + + if (i.Get() + 1) != ic.Get() { + panic(0) + } + + dr := d.Ref_this() + if d.Get() != dr.Get() { + panic(0) + } + + + // 'narrowing' also works + ddc := virtual_poly.NDoubleNarrow(d.Nnumber()) + if d.Get() != ddc.Get() { + panic(0) + } + + dic := virtual_poly.NIntNarrow(i.Nnumber()) + if i.Get() != dic.Get() { + panic(0) + } +} diff --git a/Examples/test-suite/go/voidtest_runme.go b/Examples/test-suite/go/voidtest_runme.go new file mode 100644 index 000000000..0a685f081 --- /dev/null +++ b/Examples/test-suite/go/voidtest_runme.go @@ -0,0 +1,26 @@ +package main + +import "./voidtest" + +func main() { + voidtest.Globalfunc() + f := voidtest.NewFoo() + f.Memberfunc() + + voidtest.FooStaticmemberfunc() + + v1 := voidtest.Vfunc1(f.Swigcptr()) + v2 := voidtest.Vfunc2(f) + if v1 != v2 { + panic(0) + } + + v3 := voidtest.Vfunc3(v1) + + v4 := voidtest.Vfunc1(f.Swigcptr()) + if v4 != v1 { + panic(0) + } + + v3.Memberfunc() +} diff --git a/Examples/test-suite/go/wrapmacro_runme.go b/Examples/test-suite/go/wrapmacro_runme.go new file mode 100644 index 000000000..4d3791be8 --- /dev/null +++ b/Examples/test-suite/go/wrapmacro_runme.go @@ -0,0 +1,11 @@ +package main + +import "./wrapmacro" + +func main() { + a := 2 + b := -1 + wrapmacro.Maximum(a, b) + wrapmacro.Maximum(a/7.0, -b*256) + wrapmacro.GUINT16_SWAP_LE_BE_CONSTANT(1) +} diff --git a/Examples/test-suite/keyword_rename.i b/Examples/test-suite/keyword_rename.i index da9328868..6a6082ff9 100644 --- a/Examples/test-suite/keyword_rename.i +++ b/Examples/test-suite/keyword_rename.i @@ -27,6 +27,10 @@ KW(synchronized, final) KW(string, out) struct sealed {int i;}; +/* Go Keywords */ +KW(go, defer) +KW(chan, fallthrough) + %} diff --git a/Examples/test-suite/minherit.i b/Examples/test-suite/minherit.i index fed8b029c..82d1f3cce 100644 --- a/Examples/test-suite/minherit.i +++ b/Examples/test-suite/minherit.i @@ -6,7 +6,7 @@ %module(ruby_minherit="1") minherit -#if defined(SWIGPYTHON) || defined(SWIGRUBY) || defined(SWIGOCAML) || defined(SWIGOCTAVE) || defined(SWIGPERL) +#if defined(SWIGPYTHON) || defined(SWIGRUBY) || defined(SWIGOCAML) || defined(SWIGOCTAVE) || defined(SWIGPERL) || defined(SWIGGO) %inline %{ diff --git a/Examples/test-suite/name_warnings.i b/Examples/test-suite/name_warnings.i index 4032f20e1..3455c03bf 100644 --- a/Examples/test-suite/name_warnings.i +++ b/Examples/test-suite/name_warnings.i @@ -40,7 +40,9 @@ namespace std #endif virtual ~A() {} +#ifndef SWIGGO // func is a keyword in Go. virtual int func() = 0; +#endif private: typedef complex False; }; diff --git a/Examples/test-suite/namespace_typemap.i b/Examples/test-suite/namespace_typemap.i index 984b93a6f..4952aa7ad 100644 --- a/Examples/test-suite/namespace_typemap.i +++ b/Examples/test-suite/namespace_typemap.i @@ -70,6 +70,15 @@ namespace test { delete $1; } #endif +#ifdef SWIGGO +%typemap(go) test::test_complex * "complex128" +%typemap(in) test::test_complex * { + $1 = new test_complex(__real__ $input, __imag__ $input); +} +%typemap(freearg) test::test_complex * { + delete $1; +} +#endif namespace test { class string_class; @@ -97,6 +106,15 @@ namespace test { delete $1; } #endif +#ifdef SWIGGO + %typemap(go) string_class * "string" + %typemap(in) string_class * { + $1 = new string_class($input.p); + } + %typemap(freearg) string_class * { + delete $1; + } +#endif } %inline %{ @@ -240,6 +258,14 @@ namespace Split { } } #endif +#ifdef SWIGGO + %typemap(in) PosInteger { + $1 = $input; + if ($1 < 0) { + _swig_gopanic("domain error"); + } + } +#endif } %inline %{ diff --git a/Examples/test-suite/null_pointer.i b/Examples/test-suite/null_pointer.i index 59d554c2b..0bd7a9b92 100644 --- a/Examples/test-suite/null_pointer.i +++ b/Examples/test-suite/null_pointer.i @@ -1,5 +1,7 @@ %module null_pointer +%warnfilter(SWIGWARN_PARSE_KEYWORD) func; // 'func' is a Go keyword, renamed as 'Xfunc' + %inline { struct A {}; diff --git a/Examples/test-suite/overload_simple.i b/Examples/test-suite/overload_simple.i index be7602083..b08777854 100644 --- a/Examples/test-suite/overload_simple.i +++ b/Examples/test-suite/overload_simple.i @@ -14,6 +14,8 @@ %warnfilter(SWIGWARN_LANG_OVERLOAD_SHADOW) fid; #endif +%warnfilter(SWIGWARN_PARSE_KEYWORD) type; // 'type' is a Go keyword, renamed as 'Xtype' + #ifndef SWIG_NO_OVERLOAD %immutable Spam::type; diff --git a/Examples/test-suite/return_const_value.i b/Examples/test-suite/return_const_value.i index 1d688d175..473878521 100644 --- a/Examples/test-suite/return_const_value.i +++ b/Examples/test-suite/return_const_value.i @@ -4,6 +4,8 @@ It was reported in bug 899332 by Jermey Brown (jhbrown94) */ %module return_const_value +%ignore Foo_ptr::operator=(const Foo_ptr&); + %inline %{ class Foo { @@ -35,7 +37,12 @@ public: { f._own = 0; } - + + Foo_ptr& operator=(const Foo_ptr& f) { + _ptr = f._ptr; + _own = f._own; + f._own = 0; + } ~Foo_ptr() { if(_own) delete _ptr; diff --git a/Examples/test-suite/rname.i b/Examples/test-suite/rname.i index dde71f203..31b99833d 100644 --- a/Examples/test-suite/rname.i +++ b/Examples/test-suite/rname.i @@ -22,7 +22,12 @@ %rename (newname) Base::oldname(double d) const; /* Rename derived class method only */ +#ifndef SWIGGO %rename (func) Derived::fn(Base baseValue, Base* basePtr, Base& baseRef); +#else +/* func is a keyword in Go. */ +%rename (Xfunc) Derived::fn(Base baseValue, Base* basePtr, Base& baseRef); +#endif %inline %{ class Bar { diff --git a/Examples/test-suite/typemap_namespace.i b/Examples/test-suite/typemap_namespace.i index b3fa1a733..6bf53e989 100644 --- a/Examples/test-suite/typemap_namespace.i +++ b/Examples/test-suite/typemap_namespace.i @@ -25,9 +25,12 @@ namespace Foo { %typemap(jstype) Str1 * = char *; %typemap(javain) Str1 * = char *; %typemap(javaout) Str1 * = char *; +#endif +#ifdef SWIGGO + %typemap(go) Str1 * = char *; #endif %typemap(in) Str1 * = char *; -#if !(defined(SWIGCSHARP) || defined(SWIGLUA) || defined(SWIGPHP) || defined(SWIGMZSCHEME) || defined(SWIGOCAML)) +#if !(defined(SWIGCSHARP) || defined(SWIGLUA) || defined(SWIGPHP) || defined(SWIGMZSCHEME) || defined(SWIGOCAML) || defined(SWIGGO)) %typemap(freearg) Str1 * = char *; #endif %typemap(typecheck) Str1 * = char *; diff --git a/Examples/test-suite/typemap_subst.i b/Examples/test-suite/typemap_subst.i index d5a8416db..1b1f8a3f4 100644 --- a/Examples/test-suite/typemap_subst.i +++ b/Examples/test-suite/typemap_subst.i @@ -61,8 +61,8 @@ $1 = ($ltype) temp; } -/* Java and C# modules don't use SWIG's runtime type system */ -#if !defined(SWIGJAVA) && !defined(SWIGCSHARP) +/* Java, C# and Go modules don't use SWIG's runtime type system */ +#if !defined(SWIGJAVA) && !defined(SWIGCSHARP) && !defined(SWIGGO) %inline %{ void foo(const struct xyzzy **TEST) {} %} diff --git a/Examples/test-suite/union_parameter.i b/Examples/test-suite/union_parameter.i index bb010d3fa..ed7bcacf8 100644 --- a/Examples/test-suite/union_parameter.i +++ b/Examples/test-suite/union_parameter.i @@ -1,5 +1,7 @@ %module union_parameter +%warnfilter(SWIGWARN_PARSE_KEYWORD) type; // 'type' is a Go keyword, renamed as 'Xtype' + %inline %{ typedef unsigned char Uint8; diff --git a/Lib/go/cdata.i b/Lib/go/cdata.i new file mode 100644 index 000000000..c3307945a --- /dev/null +++ b/Lib/go/cdata.i @@ -0,0 +1,135 @@ +/* ----------------------------------------------------------------------------- + * cdata.i + * + * SWIG library file containing macros for manipulating raw C data as strings. + * ----------------------------------------------------------------------------- */ + +%{ +typedef struct SWIGCDATA { + char *data; + int len; +} SWIGCDATA; +%} + +%typemap(go) SWIGCDATA %{ []byte %} +%typemap(out) SWIGCDATA (swigcdata argp) { + argp = _swig_makegobyteslice($1.data, $1.len); + $result.data = (char*)argp.data; + $result.len = (int)argp.len; +} + +/* The makegobyteslice function. */ + +%insert(runtime) %{ +typedef struct { + char *data; + int len; +} swigcdata; + +%} + +#ifndef SWIGGO_GCCGO +%insert(runtime) %{ +extern +#ifdef __cplusplus +"C" +#endif +void _swig_gc_makegobyteslice(void *, int); +static swigcdata _swig_makegobyteslice(const char *data, int len) { + struct { + const char *data; + int len; + swigcdata ret; + } a; + a.data = data; + a.len = len; + crosscall2(_swig_gc_makegobyteslice, &a, (int) sizeof a); + return a.ret; +} +%} + +%insert(gc_header) %{ +typedef struct { + byte *data; + int32 len; +} swigcdata; +extern void ·_swig_internal_makegobyteslice(void); +#pragma dynexport _swig_gc_makegobyteslice _swig_gc_makegobyteslice +void _swig_gc_makegobyteslice(void *a, int32 n) { + cgocallback(·_swig_internal_makegobyteslice, a, n); +} +void ·_swig_allocategobyteslice(byte *data, int32 len, swigcdata ret) { + ret.data = mal(len); + mcpy(ret.data, data, len); + ret.len = len; + FLUSH(&ret); +} +%} + +%insert(go_header) %{ +type swigcdata struct { data *byte; len int } +func _swig_allocategobyteslice(*byte, int) swigcdata +func _swig_internal_makegobyteslice(data *byte, len int) swigcdata { + return _swig_allocategobyteslice(data, len) +} +%} + +#else + +%insert(runtime) %{ +static swigcdata _swig_makegobyteslice(const char *data, int len) { + swigcdata ret; + ret.data = (char*)__go_alloc(len); + memcpy(ret.data, data, len); + ret.len = (int)len; + return ret; +} + +%} + +#endif + +/* ----------------------------------------------------------------------------- + * %cdata(TYPE [, NAME]) + * + * Convert raw C data to a binary string. + * ----------------------------------------------------------------------------- */ + +%define %cdata(TYPE,NAME...) + +%insert("header") { +#if #NAME == "" +static SWIGCDATA cdata_##TYPE(TYPE *ptr, int nelements) { +#else +static SWIGCDATA cdata_##NAME(TYPE *ptr, int nelements) { +#endif + SWIGCDATA d; + d.data = (char *) ptr; +#if #TYPE != "void" + d.len = nelements*sizeof(TYPE); +#else + d.len = nelements; +#endif + return d; +} +} + +%typemap(default) int nelements "$1 = 1;" + +#if #NAME == "" +SWIGCDATA cdata_##TYPE(TYPE *ptr, int nelements); +#else +SWIGCDATA cdata_##NAME(TYPE *ptr, int nelements); +#endif +%enddef + +%typemap(default) int nelements; + +%rename(cdata) ::cdata_void(void *ptr, int nelements); + +%cdata(void); + +/* Memory move function. Due to multi-argument typemaps this appears + to be wrapped as + void memmove(void *data, const char *s); */ +void memmove(void *data, char *indata, int inlen); diff --git a/Lib/go/exception.i b/Lib/go/exception.i new file mode 100644 index 000000000..5abd306a4 --- /dev/null +++ b/Lib/go/exception.i @@ -0,0 +1,7 @@ +%typemap(throws,noblock=1) (...) { + SWIG_exception(SWIG_RuntimeError,"unknown exception"); +} + +%insert("runtime") %{ +#define SWIG_exception(code, msg) _swig_gopanic(msg) +%} diff --git a/Lib/go/go.swg b/Lib/go/go.swg new file mode 100644 index 000000000..b1b8860df --- /dev/null +++ b/Lib/go/go.swg @@ -0,0 +1,514 @@ +/* ------------------------------------------------------------ + * go.swg + * + * Go configuration module. + * ------------------------------------------------------------ */ + +/* Basic types */ + +%typemap(go) bool, const bool & "bool" +%typemap(go) char, const char & "byte" +%typemap(go) signed char, const signed char & "int8" +%typemap(go) unsigned char, const unsigned char & "byte" +%typemap(go) short, const short & "int16" +%typemap(go) unsigned short, const unsigned short & "uint16" +%typemap(go) int, const int & "int" +%typemap(go) unsigned int, const unsigned int & "uint" +#if SWIGGO_LONG_TYPE_SIZE == 32 +%typemap(go) long, const long & "int32" +%typemap(go) unsigned long, const unsigned long & "uint32" +#elif SWIGGO_LONG_TYPE_SIZE == 64 +%typemap(go) long, const long & "int64" +%typemap(go) unsigned long, const unsigned long & "uint64" +#else +#error "SWIGGO_LONG_TYPE_SIZE not 32 or 64" +#endif +%typemap(go) long long, const long long & "int64" +%typemap(go) unsigned long long, const unsigned long long & "uint64" +%typemap(go) float, const float & "float32" +%typemap(go) double, const double & "float64" + +%typemap(in) bool, + char, + signed char, + unsigned char, + short, + unsigned short, + int, + unsigned int, + long, + unsigned long, + long long, + unsigned long long, + float, + double +%{ $1 = ($1_ltype)$input; %} + +%typemap(in) const bool &, + const char &, + const signed char &, + const unsigned char &, + const short &, + const unsigned short &, + const int &, + const unsigned int &, + const long &, + const unsigned long &, + const long long &, + const unsigned long long &, + const float &, + const double & +%{ $1 = ($1_ltype)&$input; %} + +%typemap(out) bool, + char, + signed char, + unsigned char, + short, + unsigned short, + int, + unsigned int, + long, + unsigned long, + long long, + unsigned long long, + float, + double +%{ $result = $1; %} + +%typemap(out) const bool &, + const char &, + const signed char &, + const unsigned char &, + const short &, + const unsigned short &, + const int &, + const unsigned int &, + const long &, + const unsigned long &, + const long long &, + const unsigned long long &, + const float &, + const double & +%{ $result = ($*1_ltype)*$1; %} + +%typemap(out) void "" + +%typemap(directorin) bool, + char, + signed char, + unsigned char, + short, + unsigned short, + int, + unsigned int, + long, + unsigned long, + long long, + unsigned long long, + float, + double +%{ $input = ($1_ltype)$1_name; %} + +%typemap(directorin) const bool &, + const char &, + const signed char &, + const unsigned char &, + const short &, + const unsigned short &, + const int &, + const unsigned int &, + const long &, + const unsigned long &, + const long long &, + const unsigned long long &, + const float &, + const double & +%{ $input = ($*1_ltype)$1_name; %} + +%typemap(directorout) bool, + char, + signed char, + unsigned char, + short, + unsigned short, + int, + unsigned int, + long, + unsigned long, + long long, + unsigned long long, + float, + double +%{ $result = ($1_ltype)$input; %} + +%typemap(directorout) const bool &, + const char &, + const signed char &, + const unsigned char &, + const short &, + const unsigned short &, + const int &, + const unsigned int &, + const long &, + const unsigned long &, + const long long &, + const unsigned long long &, + const float &, + const double & +%{ + $result = ($1_ltype)_swig_allocate(sizeof($*1_ltype)); + *$result = *($1_ltype)$input; +%} + +/* The size_t type. */ + +#if SWIGGO_LONG_TYPE_SIZE == 32 +%typemap(go) size_t, const size_t & %{int%} +#else +%typemap(go) size_t, const size_t & %{int64%} +#endif + +%typemap(in) size_t +%{ $1 = (size_t)$input; %} + +%typemap(in) const size_t & +%{ $1 = ($1_ltype)&$input; %} + +%typemap(out) size_t +%{ $result = $1; %} + +%typemap(out) const size_t & +%{ $result = ($*1_ltype)*$1; %} + +%typemap(directorin) size_t +%{ $input = (size_t)$1_name; %} + +%typemap(directorin) const size_t & +%{ $input = ($*1_ltype)$1_name; %} + +%typemap(directorout) size_t +%{ $result = ($1_ltype)$input; %} + +%typemap(directorout) const size_t & +%{ + $result = ($1_ltype)_swig_allocate(sizeof($*1_ltype)); + *$result = *($1_ltype)$input; +%} + +/* Member pointers. */ + +%typemap(go) SWIGTYPE (CLASS::*) +%{$gotypename%} + +%typemap(in) SWIGTYPE (CLASS::*) +%{ $1 = *($&1_ltype)$input; %} + +%typemap(out) SWIGTYPE (CLASS::*) +%{ + $result = _swig_allocate(sizeof($1_ltype)); + *($&1_ltype)$result = $1; +%} + +%typemap(directorin) SWIGTYPE (CLASS::*) +%{ $input = *($&1_ltype)$1_name; %} + +%typemap(directorout) SWIGTYPE (CLASS::*) +%{ + $result = _swig_allocate(sizeof($1_ltype)); + *($&1_ltype)$result = $input; +%} + +/* Pointers. */ + +/* We can't translate pointers using a typemap, so that is handled in + the C++ code. */ +%typemap(go) SWIGTYPE * +%{$gotypename%} + +%typemap(in) SWIGTYPE * +%{ $1 = *($&1_ltype)&$input; %} + +%typemap(out) SWIGTYPE * +%{ *($&1_ltype)&$result = $1; %} + +%typemap(directorin) SWIGTYPE * +%{ $input = ($1_ltype)$1_name; %} + +%typemap(directorout) SWIGTYPE * +%{ $result = ($1_ltype)$input; %} + +%apply SWIGTYPE * { SWIGTYPE *const } + +/* Pointer references. */ + +%typemap(go) SWIGTYPE *const& +%{$gotypename%} + +%typemap(in) SWIGTYPE *const& ($*1_ltype temp = 0) +%{ + temp = *($1_ltype)&$input; + $1 = ($1_ltype)&temp; +%} + +%typemap(out) SWIGTYPE *const& +%{ *($1_ltype)&$result = *$1; %} + +/* Function pointers are translated by the code in go.cxx into + _swig_fnptr. Member pointers are translated to _swig_memberptr. */ + +%insert(go_header) %{ +type _swig_fnptr *byte +type _swig_memberptr *byte +%} + +/* References. */ + +/* Converting a C++ reference to Go has to be handled in the C++ + code. */ +%typemap(go) SWIGTYPE & +%{$gotypename%} + +%typemap(in) SWIGTYPE & +%{ $1 = *($&1_ltype)&$input; %} + +%typemap(out) SWIGTYPE & +%{ *($&1_ltype)&$result = $1; %} + +%typemap(directorin) SWIGTYPE & +%{ $input = ($1_ltype)&$1_name; %} + +%typemap(directorout) SWIGTYPE & +%{ *($&1_ltype)&$result = $input; %} + +/* C arrays turn into Go pointers. If we know the length we can use a + slice. */ + +%typemap(go) SWIGTYPE [] +%{$gotypename%} + +%typemap(in) SWIGTYPE [] +%{ $1 = *($&1_ltype)&$input; %} + +%typemap(out) SWIGTYPE [] +%{ *($&1_ltype)&$result = $1; %} + +%typemap(directorin) SWIGTYPE [] +%{ $input = *($1_ltype)&$1_name; %} + +%typemap(directorout) SWIGTYPE [] +%{ *($&1_ltype)&$result = $input; %} + +/* Strings. */ + +%typemap(go) + char *, char *&, char[ANY], char[], + signed char *, signed char *&, signed char[ANY], signed char[], + unsigned char *, unsigned char *&, unsigned char[ANY], unsigned char[] +"string" + +/* Needed to avoid confusion with the way the go module handles + references. */ +%typemap(go) char&, unsigned char& "*byte" +%typemap(go) signed char& "*int8" + +%typemap(in) + char *, char[ANY], char[], + signed char *, signed char[ANY], signed char[], + unsigned char *, unsigned char[ANY], unsigned char[] +%{ $1 = ($1_ltype)$input.p; %} + +%typemap(in) char *&, signed char *&, unsigned char *& +%{ $1 = ($1_ltype)$input.p; %} + +%typemap(out) + char *, char *&, char[ANY], char[], + signed char *, signed char *&, signed char[ANY], signed char[], + unsigned char *, unsigned char *&, unsigned char[ANY], unsigned char[] +%{ $result = _swig_makegostring((char*)$1, $1 ? strlen((char*)$1) : 0); %} + +%typemap(directorin) + char *, char *&, char[ANY], char[], + signed char *, signed char *&, signed char[ANY], signed char[], + unsigned char *, unsigned char *&, unsigned char[ANY], unsigned char[] +%{ + $input = _swig_makegostring((char*)$1_name, $1_name ? strlen((char*)$1_name) : 0); +%} + +%typemap(directorout) + char *, char *&, char[ANY], char[], + signed char *, signed char *&, signed char[ANY], signed char[], + unsigned char *, unsigned char *&, unsigned char[ANY], unsigned char[] +%{ $result = ($1_ltype)$input.p; %} + +/* Enums. We can't do the right thing for enums in typemap(go) so we + deliberately don't define them. The right thing would be to + capitalize the name. This is instead done in go.cxx. */ + +%typemap(go) enum SWIGTYPE +%{$gotypename%} + +%typemap(in) enum SWIGTYPE +%{ $1 = ($1_ltype)$input; %} + +%typemap(out) enum SWIGTYPE +%{ $result = $1; %} + +%typemap(directorin) enum SWIGTYPE +%{ $input = ($1_ltype)$1_name; %} + +%typemap(directorout) enum SWIGTYPE +%{ $result = ($1_ltype)$input; %} + +/* Arbitrary type. This is a type passed by value in the C/C++ code. + We convert it to a pointer for the Go code. Note that all basic + types are explicitly handled above. */ + +%typemap(go) SWIGTYPE +%{$gotypename%} + +%typemap(in) SWIGTYPE ($&1_type argp) +%{ + argp = ($&1_ltype)$input; + if (argp == NULL) { + _swig_gopanic("Attempt to dereference null $1_type"); + } + $1 = ($1_ltype)*argp; +%} + +%typemap(out) SWIGTYPE +#ifdef __cplusplus +%{ *($&1_ltype*)&$result = new $1_ltype($1); %} +#else +{ + $&1_ltype $1ptr = ($&1_ltype)malloc(sizeof($1_ltype)); + memmove($1ptr, &$1, sizeof($1_type)); + *($&1_ltype*)&$result = $1ptr; +} +#endif + +%typemap(directorin) SWIGTYPE +%{ $input = ($&1_ltype)&$1_name; %} + +%typemap(directorout) SWIGTYPE +%{ $result = *($&1_ltype)$input; %} + +/* Exception handling */ + +%typemap(throws) char * +%{ _swig_gopanic($1); %} + +%typemap(throws) SWIGTYPE, SWIGTYPE &, SWIGTYPE *, SWIGTYPE [], SWIGTYPE [ANY] +%{ + (void)$1; + _swig_gopanic("C++ $1_type exception thrown"); +%} + +/* Typecheck typemaps. The purpose of these is merely to issue a + warning for overloaded C++ functions * that cannot be overloaded in + Go as more than one C++ type maps to a single Go type. */ + +%typecheck(SWIG_TYPECHECK_BOOL) /* Go bool */ + bool, + const bool & + "" + +%typecheck(SWIG_TYPECHECK_CHAR) /* Go byte */ + char, + const char &, + unsigned char, + const unsigned char & + "" + +%typecheck(SWIG_TYPECHECK_INT8) /* Go int8 */ + signed char, + const signed char & + "" + +%typecheck(SWIG_TYPECHECK_INT16) /* Go int16 */ + short, + const short & + "" + +%typecheck(SWIG_TYPECHECK_INT16) /* Go uint16 */ + unsigned short, + const unsigned short & + "" + +%typecheck(SWIG_TYPECHECK_INT32) /* Go int */ + int, + const int & + "" + +%typecheck(SWIG_TYPECHECK_INT32) /* Go uint */ + unsigned int, + const unsigned int & + "" + +#if SWIGGO_LONG_TYPE_SIZE == 32 +%typecheck(SWIG_TYPECHECK_INT32) /* Go int32 */ + long, + const long & + "" + +%typecheck(SWIG_TYPECHECK_INT32) /* Go uint32 */ + unsigned long, + const unsigned long & + "" +#endif + +%typecheck(SWIG_TYPECHECK_INT64) /* Go int64 */ +#if SWIGGO_LONG_TYPE_SIZE == 64 + long, + const long &, +#endif + long long, + const long long & + "" + +%typecheck(SWIG_TYPECHECK_INT64) /* Go uint64 */ +#if SWIGGO_LONG_TYPE_SIZE == 64 + unsigned long, + const unsigned long &, +#endif + unsigned long long, + const unsigned long long & + "" + +%typecheck(SWIG_TYPECHECK_FLOAT) /* Go float32 */ + float, + const float & + "" + +%typecheck(SWIG_TYPECHECK_DOUBLE) /* Go float64 */ + double, + const double & + "" + +%typecheck(SWIG_TYPECHECK_STRING) /* Go string */ + char *, + char *&, + char[ANY], + char [], + signed char *, + signed char *&, + signed char[ANY], + signed char [], + unsigned char *, + unsigned char *&, + unsigned char[ANY], + unsigned char [] + "" + +%typecheck(SWIG_TYPECHECK_POINTER) + SWIGTYPE, + SWIGTYPE *, + SWIGTYPE &, + SWIGTYPE *const&, + SWIGTYPE [], + SWIGTYPE (CLASS::*) + "" +/* Go keywords. */ +%include + +%include diff --git a/Lib/go/gokw.swg b/Lib/go/gokw.swg new file mode 100644 index 000000000..e7506d053 --- /dev/null +++ b/Lib/go/gokw.swg @@ -0,0 +1,31 @@ +/* Rename keywords. */ + +#define GOKW(x) %keywordwarn("'" `x` "' is a Go keyword, renaming to 'X"`x`"'",rename="X%s") `x` + +GOKW(break); +GOKW(case); +GOKW(chan); +GOKW(const); +GOKW(continue); +GOKW(default); +GOKW(defer); +GOKW(else); +GOKW(fallthrough); +GOKW(for); +GOKW(func); +GOKW(go); +GOKW(goto); +GOKW(if); +GOKW(import); +GOKW(interface); +GOKW(map); +GOKW(package); +GOKW(range); +GOKW(return); +GOKW(select); +GOKW(struct); +GOKW(switch); +GOKW(type); +GOKW(var); + +#undef GOKW diff --git a/Lib/go/goruntime.swg b/Lib/go/goruntime.swg new file mode 100644 index 000000000..5a51fd4b6 --- /dev/null +++ b/Lib/go/goruntime.swg @@ -0,0 +1,208 @@ +/* ------------------------------------------------------------ + * goruntime.swg + * + * Go runtime code for the various generated files. + * ------------------------------------------------------------ */ + +%insert(runtime) %{ +#include +#include +#include + +typedef struct { char *p; int n; } _gostring_; +typedef struct { void* array; unsigned int len; unsigned int cap; } _goslice_; + +%} + +#ifndef SWIGGO_GCCGO +/* Boilerplate for C/C++ code when using 6g/8g. This code is compiled + with gcc. */ +%insert(runtime) %{ + +#define __goswig_size_assert_eq(x, y, name) typedef char name[(x-y)*(x-y)*-2+1]; +#define __goswig_size_assert(t, n) __goswig_size_assert_eq(sizeof(t), n, _goswig_sizeof_##t##_is_not_##n) + +__goswig_size_assert(char, 1) +__goswig_size_assert(short, 2) +__goswig_size_assert(int, 4) +typedef long long __goswig_long_long; +__goswig_size_assert(__goswig_long_long, 8) +__goswig_size_assert(float, 4) +__goswig_size_assert(double, 8) + +extern +#ifdef __cplusplus +"C" +#endif +void crosscall2(void (*fn)(void *, int), void *, int); + +extern +#ifdef __cplusplus +"C" +#endif +void _swig_gc_allocate(void *, int); +static void *_swig_allocate(int len) { + struct { + int len; + void *ret; + } a; + a.len = len; + crosscall2(_swig_gc_allocate, &a, (int) sizeof a); + return a.ret; +} + +extern +#ifdef __cplusplus +"C" +#endif +void _swig_gc_makegostring(void *, int); +static _gostring_ _swig_makegostring(const char *p, size_t l) { + struct { + const char *p; + int l; + _gostring_ ret; + } a; + a.p = p; + a.l = l; + crosscall2(_swig_gc_makegostring, &a, (int) sizeof a); + return a.ret; +} + +extern +#ifdef __cplusplus +"C" +#endif +void _swig_gc_gopanic(void *, int); +static void _swig_gopanic(const char *p) { + struct { + const char *p; + int l; + } a; + a.p = p; + a.l = strlen(p); + crosscall2(_swig_gc_gopanic, &a, (int) sizeof a); +} + +%} + +/* Boilerplate for C code when using 6g/8g. This code is compiled + with 6c/8c. */ +%insert(gc_header) %{ +#include "runtime.h" +#include "cgocall.h" + +#pragma dynimport initcgo initcgo "libcgo.so" +#pragma dynimport libcgo_thread_start libcgo_thread_start "libcgo.so" +#pragma dynimport libcgo_set_scheduler libcgo_set_scheduler "libcgo.so" + +#ifdef _64BIT +#define SWIG_PARM_SIZE 8 +#else +#define SWIG_PARM_SIZE 4 +#endif +%} + +/* 6g/8g C boilerplate that is only needed once in a program. This + only gets added to the file if nothing is imported. */ +%insert(gc_once) %{ + +extern void ·_swig_internal_allocate(void); +#pragma dynexport _swig_gc_allocate _swig_gc_allocate +void _swig_gc_allocate(void *a, int32 n) { + cgocallback(·_swig_internal_allocate, a, n); +} + +void ·_swig_allocatememory(int32 len, byte *ret) { + ret = mal(len); + FLUSH(&ret); +} + +extern void ·_swig_internal_makegostring(void); +#pragma dynexport _swig_gc_makegostring _swig_gc_makegostring +void _swig_gc_makegostring(void *a, int32 n) { + cgocallback(·_swig_internal_makegostring, a, n); +} + +void ·_swig_allocatestring(byte *p, int32 l, String ret) { + ret.str = mal(l+1); + mcpy(ret.str, p, l); + ret.len = l; + FLUSH(&ret); +} + +extern void ·_swig_internal_gopanic(void); +#pragma dynexport _swig_gc_gopanic _swig_gc_gopanic +void _swig_gc_gopanic(void *a, int32 n) { + cgocallback(·_swig_internal_gopanic, a, n); +} + +%} + +/* Go code that is only needed once in a program. This is only added + to the file if nothing is imported. */ +%insert(go_once) %{ +func _swig_allocatememory(int) *byte +func _swig_internal_allocate(len int) *byte { + return _swig_allocatememory(len) +} + +func _swig_allocatestring(*byte, int) string +func _swig_internal_makegostring(p *byte, l int) string { + return _swig_allocatestring(p, l) +} + +func _swig_internal_gopanic(p *byte, l int) { + panic(_swig_allocatestring(p, l)) +} +%} + +#else + +/* Boilerplate for C/C++ code when using gccgo. */ +%insert(runtime) %{ +#define SWIGGO_GCCGO + +extern +#ifdef __cplusplus +"C" +#endif +void *__go_alloc (size_t); + +static void *_swig_allocate(int len) { + return __go_alloc(len); +} + +static _gostring_ _swig_makegostring(const char *p, size_t l) { + _gostring_ ret; + ret.p = (char*)__go_alloc(l); + memcpy(ret.p, p, l); + ret.n = l; + return ret; +} + +extern +#ifdef __cplusplus +"C" +#endif +void __go_panic_msg(const char *); +#define _swig_gopanic __go_panic_msg + +%} + +#endif + +%insert(runtime) %{ +#define SWIG_contract_assert(expr, msg) \ + if (!(expr)) { _swig_gopanic(msg); } else +%} + +#ifdef __cplusplus +/* We don't need a Swig::Director class, but the Swig testsuite + expects one. */ +%insert(runtime) %{ +namespace Swig { + typedef int Director; +} +%} + +#endif diff --git a/Lib/go/std_common.i b/Lib/go/std_common.i new file mode 100644 index 000000000..c010facac --- /dev/null +++ b/Lib/go/std_common.i @@ -0,0 +1,4 @@ +%include + +%apply size_t { std::size_t }; +%apply const size_t& { const std::size_t& }; diff --git a/Lib/go/std_deque.i b/Lib/go/std_deque.i new file mode 100644 index 000000000..cb98f6c2f --- /dev/null +++ b/Lib/go/std_deque.i @@ -0,0 +1 @@ +%include diff --git a/Lib/go/std_except.i b/Lib/go/std_except.i new file mode 100644 index 000000000..789a335f7 --- /dev/null +++ b/Lib/go/std_except.i @@ -0,0 +1,29 @@ +/* ----------------------------------------------------------------------------- + * std_except.i + * + * Typemaps used by the STL wrappers that throw exceptions. + * These typemaps are used when methods are declared with an STL exception specification, such as + * size_t at() const throw (std::out_of_range); + * ----------------------------------------------------------------------------- */ + +%{ +#include +%} + +namespace std +{ + %ignore exception; + struct exception {}; +} + +%typemap(throws) std::bad_exception %{_swig_gopanic($1.what());%} +%typemap(throws) std::domain_error %{_swig_gopanic($1.what());%} +%typemap(throws) std::exception %{_swig_gopanic($1.what());%} +%typemap(throws) std::invalid_argument %{_swig_gopanic($1.what());%} +%typemap(throws) std::length_error %{_swig_gopanic($1.what());%} +%typemap(throws) std::logic_error %{_swig_gopanic($1.what());%} +%typemap(throws) std::out_of_range %{_swig_gopanic($1.what());%} +%typemap(throws) std::overflow_error %{_swig_gopanic($1.what());%} +%typemap(throws) std::range_error %{_swig_gopanic($1.what());%} +%typemap(throws) std::runtime_error %{_swig_gopanic($1.what());%} +%typemap(throws) std::underflow_error %{_swig_gopanic($1.what());%} diff --git a/Lib/go/std_map.i b/Lib/go/std_map.i new file mode 100644 index 000000000..e37a9e676 --- /dev/null +++ b/Lib/go/std_map.i @@ -0,0 +1,64 @@ +/* ----------------------------------------------------------------------------- + * std_map.i + * + * SWIG typemaps for std::map + * ----------------------------------------------------------------------------- */ + +%include + +// ------------------------------------------------------------------------ +// std::map +// ------------------------------------------------------------------------ + +// "map" is a keyword in Go. +#define map cmap + +%{ +#define map cmap +#include +#include +#include +%} + +// exported class + +namespace std { + + template class map { + // add typemaps here + public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef K key_type; + typedef T mapped_type; + map(); + map(const map &); + + unsigned int size() const; + bool empty() const; + void clear(); + %extend { + const T& get(const K& key) throw (std::out_of_range) { + std::map::iterator i = self->find(key); + if (i != self->end()) + return i->second; + else + throw std::out_of_range("key not found"); + } + void set(const K& key, const T& x) { + (*self)[key] = x; + } + void del(const K& key) throw (std::out_of_range) { + std::map::iterator i = self->find(key); + if (i != self->end()) + self->erase(i); + else + throw std::out_of_range("key not found"); + } + bool has_key(const K& key) { + std::map::iterator i = self->find(key); + return i != self->end(); + } + } + }; +} diff --git a/Lib/go/std_pair.i b/Lib/go/std_pair.i new file mode 100644 index 000000000..fe45ee676 --- /dev/null +++ b/Lib/go/std_pair.i @@ -0,0 +1,34 @@ +/* ----------------------------------------------------------------------------- + * std_pair.i + * + * SWIG typemaps for std::pair + * ----------------------------------------------------------------------------- */ + +%include +%include + +// ------------------------------------------------------------------------ +// std::pair +// ------------------------------------------------------------------------ + +%{ +#include +%} + +namespace std { + + template struct pair { + + pair(); + pair(T first, U second); + pair(const pair& p); + + template pair(const pair &p); + + T first; + U second; + }; + + // add specializations here + +} diff --git a/Lib/go/std_string.i b/Lib/go/std_string.i new file mode 100644 index 000000000..3c94cbe10 --- /dev/null +++ b/Lib/go/std_string.i @@ -0,0 +1,55 @@ +/* ----------------------------------------------------------------------------- + * std_string.i + * + * Typemaps for std::string and const std::string& + * These are mapped to a Go string and are passed around by value. + * + * To use non-const std::string references use the following %apply. Note + * that they are passed by value. + * %apply const std::string & {std::string &}; + * ----------------------------------------------------------------------------- */ + +%{ +#include +%} + +namespace std { + +%naturalvar string; + +class string; + +%typemap(go) string, const string & "string" + +%typemap(in) string +%{ $1.assign($input.p, $input.n); %} + +%typemap(directorout) string +%{ $result.assign($input.p, $input.n); %} + +%typemap(out) string +%{ $result = _swig_makegostring($1.data(), $1.length()); %} + +%typemap(directorin) string +%{ $input = _swig_makegostring($1_name.data(), $1_name.length()); %} + +%typemap(in) const string & +%{ + std::string $1_str($input.p, $input.n); + $1 = &$1_str; +%} + +%typemap(directorout,warning=SWIGWARN_TYPEMAP_THREAD_UNSAFE_MSG) const string & +%{ + static std::string $1_str; + $1_str.assign($input.p, $input.n); + $result = &$1_str; +%} + +%typemap(out) const string & +%{ $result = _swig_makegostring((*$1).data(), (*$1).length()); %} + +%typemap(directorin) const string & +%{ $input = _swig_makegostring($1_name.data(), $1_name.length()); %} + +} diff --git a/Lib/go/std_vector.i b/Lib/go/std_vector.i new file mode 100644 index 000000000..f4ce8431c --- /dev/null +++ b/Lib/go/std_vector.i @@ -0,0 +1,78 @@ +/* ----------------------------------------------------------------------------- + * std_vector.i + * ----------------------------------------------------------------------------- */ + +%{ +#include +#include +%} + +namespace std { + + template class vector { + public: + typedef size_t size_type; + typedef T value_type; + typedef const value_type& const_reference; + vector(); + vector(size_type n); + size_type size() const; + size_type capacity() const; + void reserve(size_type n); + %rename(isEmpty) empty; + bool empty() const; + void clear(); + %rename(add) push_back; + void push_back(const value_type& x); + %extend { + const_reference get(int i) throw (std::out_of_range) { + int size = int(self->size()); + if (i>=0 && isize()); + if (i>=0 && i class vector { + public: + typedef size_t size_type; + typedef bool value_type; + typedef bool const_reference; + vector(); + vector(size_type n); + size_type size() const; + size_type capacity() const; + void reserve(size_type n); + %rename(isEmpty) empty; + bool empty() const; + void clear(); + %rename(add) push_back; + void push_back(const value_type& x); + %extend { + const_reference get(int i) throw (std::out_of_range) { + int size = int(self->size()); + if (i>=0 && isize()); + if (i>=0 && i +%include +%include +%include +%include diff --git a/Lib/go/typemaps.i b/Lib/go/typemaps.i new file mode 100644 index 000000000..17da80c23 --- /dev/null +++ b/Lib/go/typemaps.i @@ -0,0 +1,335 @@ +/* ----------------------------------------------------------------------------- + * typemaps.i + * + * Pointer and reference handling typemap library + * + * These mappings provide support for input/output arguments and common + * uses for C/C++ pointers and C++ references. + * ----------------------------------------------------------------------------- */ + +/* +INPUT typemaps +-------------- + +These typemaps remap a C pointer or C++ reference to be an "INPUT" value which is +passed by value instead of reference. + +The following typemaps can be applied to turn a pointer or reference into a simple +input value. That is, instead of passing a pointer or reference to an object, +you would use a real value instead. + + bool *INPUT, bool &INPUT + signed char *INPUT, signed char &INPUT + unsigned char *INPUT, unsigned char &INPUT + short *INPUT, short &INPUT + unsigned short *INPUT, unsigned short &INPUT + int *INPUT, int &INPUT + unsigned int *INPUT, unsigned int &INPUT + long *INPUT, long &INPUT + unsigned long *INPUT, unsigned long &INPUT + long long *INPUT, long long &INPUT + unsigned long long *INPUT, unsigned long long &INPUT + float *INPUT, float &INPUT + double *INPUT, double &INPUT + +To use these, suppose you had a C function like this : + + double fadd(double *a, double *b) { + return *a+*b; + } + +You could wrap it with SWIG as follows : + + %include + double fadd(double *INPUT, double *INPUT); + +or you can use the %apply directive : + + %include + %apply double *INPUT { double *a, double *b }; + double fadd(double *a, double *b); + +In Go you could then use it like this: + answer := modulename.Fadd(10.0, 20.0) + +There are no char *INPUT typemaps, however you can apply the signed +char * typemaps instead: + %include + %apply signed char *INPUT {char *input}; + void f(char *input); +*/ + +%define INPUT_TYPEMAP(TYPE, GOTYPE) +%typemap(go) TYPE *INPUT, TYPE &INPUT "GOTYPE" + +%typemap(in) TYPE *INPUT +%{ $1 = ($1_ltype)&$input; %} + +%typemap(in) TYPE &INPUT +%{ $1 = ($1_ltype)$input; %} + +%typemap(freearg) TYPE *INPUT, TYPE &INPUT "" + +%typemap(directorout) TYPE *INPUT +%{ $result = ($1_ltype)&$input; %} + +%typemap(directorout) TYPE &INPUT +%{ $result = ($1_ltype)$input; %} + +%typemap(directorin) TYPE &INPUT +%{ $1 = ($input_ltype)&$input; %} + +// %typemap(typecheck) TYPE *INPUT = TYPE; +// %typemap(typecheck) TYPE &INPUT = TYPE; +%enddef + +INPUT_TYPEMAP(bool, bool); +INPUT_TYPEMAP(signed char, int8); +INPUT_TYPEMAP(char, byte); +INPUT_TYPEMAP(unsigned char, byte); +INPUT_TYPEMAP(short, int16); +INPUT_TYPEMAP(unsigned short, uint16); +INPUT_TYPEMAP(int, int); +INPUT_TYPEMAP(unsigned int, uint); +INPUT_TYPEMAP(long, int64); +INPUT_TYPEMAP(unsigned long, uint64); +INPUT_TYPEMAP(long long, int64); +INPUT_TYPEMAP(unsigned long long, uint64); +INPUT_TYPEMAP(float, float); +INPUT_TYPEMAP(double, float64); + +#undef INPUT_TYPEMAP + +// OUTPUT typemaps. These typemaps are used for parameters that +// are output only. An array replaces the c pointer or reference parameter. +// The output value is returned in this array passed in. + +/* +OUTPUT typemaps +--------------- + +The following typemaps can be applied to turn a pointer or reference +into an "output" value. When calling a function, no input value would +be given for a parameter, but an output value would be returned. This +works by a Go slice being passed as a parameter where a c pointer or +reference is required. As with any Go function, the array is passed +by reference so that any modifications to the array will be picked up +in the calling function. Note that the array passed in MUST have at +least one element, but as the c function does not require any input, +the value can be set to anything. + + bool *OUTPUT, bool &OUTPUT + signed char *OUTPUT, signed char &OUTPUT + unsigned char *OUTPUT, unsigned char &OUTPUT + short *OUTPUT, short &OUTPUT + unsigned short *OUTPUT, unsigned short &OUTPUT + int *OUTPUT, int &OUTPUT + unsigned int *OUTPUT, unsigned int &OUTPUT + long *OUTPUT, long &OUTPUT + unsigned long *OUTPUT, unsigned long &OUTPUT + long long *OUTPUT, long long &OUTPUT + unsigned long long *OUTPUT, unsigned long long &OUTPUT + float *OUTPUT, float &OUTPUT + double *OUTPUT, double &OUTPUT + +For example, suppose you were trying to wrap the modf() function in the +C math library which splits x into integral and fractional parts (and +returns the integer part in one of its parameters): + + double modf(double x, double *ip); + +You could wrap it with SWIG as follows : + + %include + double modf(double x, double *OUTPUT); + +or you can use the %apply directive : + + %include + %apply double *OUTPUT { double *ip }; + double modf(double x, double *ip); + +The Go output of the function would be the function return value and the +value in the single element array. In Go you would use it like this: + + ptr := []float64{0.0} + fraction := modulename.Modf(5.0,ptr) + +There are no char *OUTPUT typemaps, however you can apply the signed +char * typemaps instead: + %include + %apply signed char *OUTPUT {char *output}; + void f(char *output); +*/ + +%define OUTPUT_TYPEMAP(TYPE, GOTYPE) +%typemap(go) TYPE *OUTPUT, TYPE &OUTPUT %{[]GOTYPE%} + +%typemap(in) TYPE *OUTPUT($*1_ltype temp) +{ + if ($input.len == 0) { + _swig_gopanic("array must contain at least 1 element"); + } + $1 = &temp; +} + +%typemap(in) TYPE &OUTPUT($*1_ltype temp) +{ + if ($input->len == 0) { + _swig_gopanic("array must contain at least 1 element"); + } + $1 = &temp; +} + +%typemap(freearg) TYPE *OUTPUT, TYPE &OUTPUT "" + +%typemap(argout) TYPE *OUTPUT +{ + TYPE* a = (TYPE *) $input.array; + a[0] = temp$argnum; +} + +%typemap(argout) TYPE &OUTPUT +{ + TYPE* a = (TYPE *) $input->array; + a[0] = temp$argnum; +} + +%typemap(directorout,warning="Need to provide TYPE *OUTPUT directorout typemap") TYPE *OUTPUT, TYPE &OUTPUT { +} + +%typemap(directorin) TYPE &OUTPUT +%{ *(($&1_ltype) $input = &$1; %} + +%typemap(directorin,warning="Need to provide TYPE *OUTPUT directorin typemap, TYPE array length is unknown") TYPE *OUTPUT +{ +} + +%enddef + +OUTPUT_TYPEMAP(bool, bool); +OUTPUT_TYPEMAP(signed char, int8); +OUTPUT_TYPEMAP(char, byte); +OUTPUT_TYPEMAP(unsigned char, byte); +OUTPUT_TYPEMAP(short, int16); +OUTPUT_TYPEMAP(unsigned short, uint16); +OUTPUT_TYPEMAP(int, int); +OUTPUT_TYPEMAP(unsigned int, uint); +OUTPUT_TYPEMAP(long, int64); +OUTPUT_TYPEMAP(unsigned long, uint64); +OUTPUT_TYPEMAP(long long, int64); +OUTPUT_TYPEMAP(unsigned long long, uint64); +OUTPUT_TYPEMAP(float, float); +OUTPUT_TYPEMAP(double, float64); + +#undef OUTPUT_TYPEMAP + +/* +INOUT typemaps +-------------- + +Mappings for a parameter that is both an input and an output parameter + +The following typemaps can be applied to make a function parameter both +an input and output value. This combines the behavior of both the +"INPUT" and "OUTPUT" typemaps described earlier. Output values are +returned as an element in a Go slice. + + bool *INOUT, bool &INOUT + signed char *INOUT, signed char &INOUT + unsigned char *INOUT, unsigned char &INOUT + short *INOUT, short &INOUT + unsigned short *INOUT, unsigned short &INOUT + int *INOUT, int &INOUT + unsigned int *INOUT, unsigned int &INOUT + long *INOUT, long &INOUT + unsigned long *INOUT, unsigned long &INOUT + long long *INOUT, long long &INOUT + unsigned long long *INOUT, unsigned long long &INOUT + float *INOUT, float &INOUT + double *INOUT, double &INOUT + +For example, suppose you were trying to wrap the following function : + + void neg(double *x) { + *x = -(*x); + } + +You could wrap it with SWIG as follows : + + %include + void neg(double *INOUT); + +or you can use the %apply directive : + + %include + %apply double *INOUT { double *x }; + void neg(double *x); + +This works similarly to C in that the mapping directly modifies the +input value - the input must be an array with a minimum of one element. +The element in the array is the input and the output is the element in +the array. + + x := []float64{5.0} + Neg(x); + +The implementation of the OUTPUT and INOUT typemaps is different to +other languages in that other languages will return the output value +as part of the function return value. This difference is due to Go +being a typed language. + +There are no char *INOUT typemaps, however you can apply the signed +char * typemaps instead: + %include + %apply signed char *INOUT {char *inout}; + void f(char *inout); +*/ + +%define INOUT_TYPEMAP(TYPE, GOTYPE) +%typemap(go) TYPE *INOUT, TYPE &INOUT %{[]GOTYPE%} + +%typemap(in) TYPE *INOUT { + if ($input.len == 0) { + _swig_gopanic("array must contain at least 1 element"); + } + $1 = ($1_ltype) $input.array; +} + +%typemap(in) TYPE &INOUT { + if ($input->len == 0) { + _swig_gopanic("array must contain at least 1 element"); + } + $1 = ($1_ltype) $input->array; +} + +%typemap(freearg) TYPE *INOUT, TYPE &INOUT "" + +%typemap(directorout,warning="Need to provide TYPE *INOUT directorout typemap") TYPE *INOUT, TYPE &INOUT { +} + +%typemap(directorin) TYPE &INOUT +%{ *(($&1_ltype)&$input) = &$1; %} + +%typemap(directorin,warning="Need to provide TYPE *INOUT directorin typemap, TYPE array length is unknown") TYPE *INOUT, TYPE &INOUT +{ +} + +%enddef + +INOUT_TYPEMAP(bool, bool); +INOUT_TYPEMAP(signed char, int8); +INOUT_TYPEMAP(char, byte); +INOUT_TYPEMAP(unsigned char, byte); +INOUT_TYPEMAP(short, int16); +INOUT_TYPEMAP(unsigned short, uint16); +INOUT_TYPEMAP(int, int); +INOUT_TYPEMAP(unsigned int, uint); +INOUT_TYPEMAP(long, int64); +INOUT_TYPEMAP(unsigned long, uint64); +INOUT_TYPEMAP(long long, int64); +INOUT_TYPEMAP(unsigned long long, uint64); +INOUT_TYPEMAP(float, float); +INOUT_TYPEMAP(double, float64); + +#undef INOUT_TYPEMAP diff --git a/Makefile.in b/Makefile.in index 0beb7cbdd..180ad3451 100644 --- a/Makefile.in +++ b/Makefile.in @@ -75,6 +75,7 @@ skip-clisp = test -n "@SKIP_CLISP@" skip-cffi = test -n "@SKIP_CFFI@" skip-uffi = test -n "@SKIP_UFFI@" skip-r = test -n "@SKIP_R@" +skip-go = test -n "@SKIP_GO@" # Additional dependencies for some tests skip-gcj = test -n "@SKIP_GCJ@" @@ -110,6 +111,7 @@ check-aliveness: @$(skip-modula3) || ./$(TARGET) -modula3 -help @$(skip-lua) || ./$(TARGET) -lua -help @$(skip-r) || ./$(TARGET) -r -help + @$(skip-go) || ./$(TARGET) -go -help check-ccache: test -z "$(ENABLE_CCACHE)" || (cd $(CCACHE) && $(MAKE) check) @@ -135,7 +137,8 @@ check-examples: \ check-clisp-examples \ check-uffi-examples \ check-cffi-examples \ - check-r-examples + check-r-examples \ + check-go-examples tcl_examples :=$(shell sed '/^\#/d' $(srcdir)/Examples/tcl/check.list) perl5_examples :=$(shell sed '/^\#/d' $(srcdir)/Examples/perl5/check.list) @@ -157,6 +160,7 @@ clisp_examples := uffi_examples := cffi_examples := r_examples :=$(shell sed '/^\#/d' $(srcdir)/Examples/r/check.list) +go_examples :=$(shell sed '/^\#/d' $(srcdir)/Examples/go/check.list) # all examples check-%-examples : @@ -206,7 +210,8 @@ check-test-suite: \ check-uffi-test-suite \ check-cffi-test-suite \ check-chicken-test-suite \ - check-r-test-suite + check-r-test-suite \ + check-go-test-suite check-%-test-suite: @if test -z "$(skip-$*)"; then \ @@ -257,7 +262,8 @@ all-test-suite: \ all-uffi-test-suite \ all-cffi-test-suite \ all-chicken-test-suite \ - all-r-test-suite + all-r-test-suite \ + all-go-test-suite all-%-test-suite: @$(MAKE) -k -s check-$*-test-suite ACTION=all @@ -284,7 +290,8 @@ broken-test-suite: \ broken-uffi-test-suite \ broken-cffi-test-suite \ broken-chicken-test-suite \ - broken-r-test-suite + broken-r-test-suite \ + broken-go-test-suite broken-%-test-suite: @$(MAKE) -k -s check-$*-test-suite ACTION=broken @@ -401,7 +408,7 @@ install-main: @$(INSTALL_PROGRAM) $(TARGET) $(DESTDIR)$(BIN_DIR)/`echo $(TARGET_NOEXE) | sed '$(transform)'`@EXEEXT@ lib-languages = gcj typemaps tcl perl5 python guile java mzscheme ruby php ocaml octave \ - pike chicken csharp modula3 allegrocl clisp lua cffi uffi r + pike chicken csharp modula3 allegrocl clisp lua cffi uffi r go lib-modules = std diff --git a/Source/Makefile.am b/Source/Makefile.am index 26f37b2fe..4677002e6 100644 --- a/Source/Makefile.am +++ b/Source/Makefile.am @@ -44,6 +44,7 @@ eswig_SOURCES = CParse/cscanner.c \ Modules/csharp.cxx \ Modules/directors.cxx \ Modules/emit.cxx \ + Modules/go.cxx \ Modules/guile.cxx \ Modules/java.cxx \ Modules/lang.cxx \ diff --git a/Source/Modules/allegrocl.cxx b/Source/Modules/allegrocl.cxx index de4a7bfa9..93ca6d8f3 100644 --- a/Source/Modules/allegrocl.cxx +++ b/Source/Modules/allegrocl.cxx @@ -1709,6 +1709,8 @@ int ALLEGROCL::top(Node *n) { We don't need a dispatch function in the C++ wrapper code; we want it over on the lisp side. */ +#define Swig_overload_rank Allegrocl_swig_overload_rank + #define MAX_OVERLOAD 256 /* Overload "argc" and "argv" */ diff --git a/Source/Modules/go.cxx b/Source/Modules/go.cxx new file mode 100644 index 000000000..91a0f457b --- /dev/null +++ b/Source/Modules/go.cxx @@ -0,0 +1,4824 @@ +/* ----------------------------------------------------------------------------- + * See the LICENSE file for information on copyright, usage and redistribution + * of SWIG, and the README file for authors - http://www.swig.org/release.html. + * + * go.cxx + * + * Go language module for SWIG. + * ----------------------------------------------------------------------------- */ + +char cvsroot_go_cxx[] = "$Id"; + +#include "swigmod.h" +#include "cparse.h" +#include +#include + +class GO:public Language { + static const char * const usage; + + // Go package name. + String *package; + // Flag for generating gccgo output. + bool gccgo_flag; + // Prefix to use with gccgo. + String *go_prefix; + // Name of shared library to import. + String *soname; + // Size in bits of the C type "long". + int long_type_size; + // Rename directives. + String *renames; + + /* Output files */ + File *f_c_begin; + File *f_go_begin; + File *f_gc_begin; + + /* Output fragments */ + File *f_c_runtime; + File *f_c_header; + File *f_c_wrappers; + File *f_c_init; + File *f_c_directors; + File *f_c_directors_h; + File *f_go_runtime; + File *f_go_header; + File *f_go_wrappers; + File *f_go_once; + File *f_gc_runtime; + File *f_gc_header; + File *f_gc_wrappers; + File *f_gc_once; + + // True if we imported a module. + bool saw_import; + // If not NULL, name of import package being processed. + String *imported_package; + // Build interface methods while handling a class. This is only + // non-NULL when we are handling methods. + String *interfaces; + // The class node while handling a class. This is only non-NULL + // when we are handling methods. + Node *class_node; + // The class name while handling a class. This is only non-NULL + // when we are handling methods. This is the name of the class as + // SWIG sees it. + String *class_name; + // The receiver name while handling a class. This is only non-NULL + // when we are handling methods. This is the name of the class + // as run through goCPointerType. + String *class_receiver; + // A hash table of method names that we have seen when processing a + // class. This lets us detect base class methods that we don't want + // to use. + Hash *class_methods; + // True when we are generating the wrapper functions for a variable. + bool making_variable_wrappers; + // True when working with a static member function. + bool is_static_member_function; + // A hash table of types that we have seen but which may not have + // been defined. The index is a SwigType. + Hash *undefined_types; + // A hash table of classes which were defined. The index is a Go + // type name. + Hash *defined_types; + +public: + GO():package(NULL), + gccgo_flag(false), + go_prefix(NULL), + soname(NULL), + long_type_size(32), + renames(NULL), + f_c_begin(NULL), + f_go_begin(NULL), + f_gc_begin(NULL), + f_c_runtime(NULL), + f_c_header(NULL), + f_c_wrappers(NULL), + f_c_init(NULL), + f_c_directors(NULL), + f_c_directors_h(NULL), + f_go_runtime(NULL), + f_go_header(NULL), + f_go_wrappers(NULL), + f_go_once(NULL), + f_gc_runtime(NULL), + f_gc_header(NULL), + f_gc_wrappers(NULL), + f_gc_once(NULL), + saw_import(false), + imported_package(NULL), + interfaces(NULL), + class_receiver(NULL), + class_methods(NULL), + making_variable_wrappers(false), + is_static_member_function(false), + undefined_types(NULL), + defined_types(NULL) + { + director_multiple_inheritance = 1; + director_language = 1; + director_prot_ctor_code = NewString("_swig_gopanic(\"accessing abstract class or protected constructor\");"); + } + +private: + /* ------------------------------------------------------------ + * main() + * ------------------------------------------------------------ */ + virtual void main(int argc, char *argv[]) { + + SWIG_library_directory("go"); + + // Process command line options. + for (int i = 1; i < argc; i++) { + if (argv[i]) { + if (strcmp(argv[i], "-package") == 0) { + if (argv[i + 1] != NULL) { + package = NewString(argv[i + 1]); + Swig_mark_arg(i); + Swig_mark_arg(i + 1); + i++; + } else { + Swig_arg_error(); + } + } else if (strcmp(argv[i], "-gccgo") == 0) { + Swig_mark_arg(i); + gccgo_flag = true; + } else if (strcmp(argv[i], "-go-prefix") == 0) { + if (argv[i + 1] != NULL) { + go_prefix = NewString(argv[i + 1]); + Swig_mark_arg(i); + Swig_mark_arg(i + 1); + i++; + } else { + Swig_arg_error(); + } + } else if (strcmp(argv[i], "-soname") == 0) { + if (argv[i + 1] != NULL) { + soname = NewString(argv[i + 1]); + Swig_mark_arg(i); + Swig_mark_arg(i + 1); + i++; + } else { + Swig_arg_error(); + } + } else if (strcmp(argv[i], "-longsize") == 0) { + if (argv[i + 1] != NULL) { + long_type_size = atoi(argv[i + 1]); + if (long_type_size != 32 && long_type_size != 64) { + Printf(stderr, "-longsize not 32 or 64\n"); + Swig_arg_error(); + } + Swig_mark_arg(i); + Swig_mark_arg(i + 1); + ++i; + } else { + Swig_arg_error(); + } + } else if (strcmp(argv[i], "-rename") == 0) { + if (argv[i + 1] != NULL) { + String *d = NewString(argv[i + 1]); + Replace(d, "=", " ", DOH_REPLACE_FIRST); + Preprocessor_define(d, 0); + if (renames == NULL) { + renames = NewString(""); + } + Printv(renames, "#define ", d, "\n", NULL); + Delete(d); + Swig_mark_arg(i); + Swig_mark_arg(i + 1); + ++i; + // Prevent SWIG from trying to define this for the + // preprocessor, which breaks if there are multiple + // -rename options. + argv[i] = NULL; + } else { + Swig_arg_error(); + } + } else if (strcmp(argv[i], "-help") == 0) { + Printf(stdout, "%s\n", usage); + } + } + } + + if (gccgo_flag && go_prefix == NULL) { + go_prefix = NewString("go"); + } + + // Add preprocessor symbol to parser. + Preprocessor_define("SWIGGO 1", 0); + + if (gccgo_flag) { + Preprocessor_define("SWIGGO_GCCGO 1", 0); + } + + if (long_type_size == 32) { + Preprocessor_define("SWIGGO_LONG_TYPE_SIZE 32", 0); + } else { + Preprocessor_define("SWIGGO_LONG_TYPE_SIZE 64", 0); + } + + // Add typemap definitions. + SWIG_typemap_lang("go"); + SWIG_config_file("go.swg"); + + allow_overloading(); + } + + /* --------------------------------------------------------------------- + * top() + * + * For 6g/8g, we are going to create the following files: + * + * 1) A .c or .cxx file compiled with gcc. This file will contain + * function wrappers. Each wrapper will take a pointer to a + * struct holding the arguments, unpack them, and call the real + * function. + * + * 2) A .go file which defines the Go form of all types, and which + * defines Go function wrappers. Each wrapper will call the C + * function wrapper in the second file. + * + * 3) A .c file compiled with 6c/8c. This file will define + * Go-callable C function wrappers. Each wrapper will use + * cgocall to call the function wrappers in the first file. + * + * When generating code for gccgo, we don't need the third file, and + * the function wrappers in the first file have a different form. + * + * --------------------------------------------------------------------- */ + + virtual int top(Node *n) { + Node *optionsnode = Getattr(Getattr(n, "module"), "options"); + if (optionsnode != NULL) { + if (Getattr(optionsnode, "directors")) { + allow_directors(); + } + if (Getattr(optionsnode, "dirprot")) { + allow_dirprot(); + } + allow_allprotected(GetFlag(optionsnode, "allprotected")); + } + + String *module = Getattr(n, "name"); + if (package == NULL) { + package = Copy(module); + } + if (soname == NULL) { + soname = Copy(package); + Append(soname, ".so"); + } + + // Get filenames. + + String *c_filename = Getattr(n, "outfile"); + String *c_filename_h = Getattr(n, "outfile_h"); + + String *go_filename = NewString(""); + Printf(go_filename, "%s%s.go", SWIG_output_directory(), module); + + String *gc_filename = NULL; + if (!gccgo_flag) { + gc_filename = NewString(""); + Printf(gc_filename, "%s%s_gc.c", SWIG_output_directory(), module); + } + + // Open files. + + f_c_begin = NewFile(c_filename, "w", SWIG_output_files()); + if (!f_c_begin) { + FileErrorDisplay(c_filename); + SWIG_exit(EXIT_FAILURE); + } + + if (directorsEnabled()) { + if (!c_filename_h) { + Printf(stderr, "Unable to determine outfile_h\n"); + SWIG_exit(EXIT_FAILURE); + } + f_c_directors_h = NewFile(c_filename_h, "w", SWIG_output_files()); + if (!f_c_directors_h) { + FileErrorDisplay(c_filename_h); + SWIG_exit(EXIT_FAILURE); + } + } + + f_go_begin = NewFile(go_filename, "w", SWIG_output_files()); + if (!f_go_begin) { + FileErrorDisplay(go_filename); + SWIG_exit(EXIT_FAILURE); + } + + if (!gccgo_flag) { + f_gc_begin = NewFile(gc_filename, "w", SWIG_output_files()); + if (!f_gc_begin) { + FileErrorDisplay(gc_filename); + SWIG_exit(EXIT_FAILURE); + } + } + + f_c_runtime = NewString(""); + f_c_header = NewString(""); + f_c_wrappers = NewString(""); + f_c_init = NewString(""); + f_c_directors = NewString(""); + f_go_runtime = NewString(""); + f_go_header = NewString(""); + f_go_wrappers = NewString(""); + f_go_once = NewString(""); + if (!gccgo_flag) { + f_gc_runtime = NewString(""); + f_gc_header = NewString(""); + f_gc_wrappers = NewString(""); + f_gc_once = NewString(""); + } + + Swig_register_filebyname("begin", f_c_begin); + Swig_register_filebyname("runtime", f_c_runtime); + Swig_register_filebyname("header", f_c_header); + Swig_register_filebyname("wrapper", f_c_wrappers); + Swig_register_filebyname("init", f_c_init); + Swig_register_filebyname("director", f_c_directors); + Swig_register_filebyname("director_h", f_c_directors_h); + Swig_register_filebyname("go_begin", f_go_begin); + Swig_register_filebyname("go_runtime", f_go_runtime); + Swig_register_filebyname("go_header", f_go_header); + Swig_register_filebyname("go_wrapper", f_go_wrappers); + Swig_register_filebyname("go_once", f_go_once); + if (!gccgo_flag) { + Swig_register_filebyname("gc_begin", f_gc_begin); + Swig_register_filebyname("gc_runtime", f_gc_runtime); + Swig_register_filebyname("gc_header", f_gc_header); + Swig_register_filebyname("gc_wrapper", f_gc_wrappers); + Swig_register_filebyname("gc_once", f_gc_once); + } + + Swig_banner(f_c_begin); + if (!gccgo_flag) { + Printf(f_c_begin, "\n/* This file should be compiled with gcc. */\n"); + } + if (renames != NULL) { + Printf(f_c_begin, "%s\n", renames); + } + + if (directorsEnabled()) { + Printf(f_c_runtime, "#define SWIG_DIRECTORS\n"); + + Swig_banner(f_c_directors_h); + Printf(f_c_directors_h, + "\n/* This file should be compiled with gcc. */\n"); + Printf(f_c_directors_h, "#ifndef SWIG_%s_WRAP_H_\n", module); + Printf(f_c_directors_h, "#define SWIG_%s_WRAP_H_\n\n", module); + + Printf(f_c_directors, "\n// C++ director class methods.\n"); + Printf(f_c_directors, "#include \"%s\"\n\n", + Swig_file_filename(c_filename_h)); + } + + Swig_banner(f_go_begin); + + if (!gccgo_flag) { + Swig_banner(f_gc_begin); + Printf(f_gc_begin, "\n/* This file should be compiled with 6c/8c. */\n"); + } + + // Output module initialization code. + + Printf(f_go_begin, "\npackage %s\n\n", package); + + // Set up the hash table for types not defined by SWIG. + + undefined_types = NewHash(); + defined_types = NewHash(); + + // Emit code. + + Language::top(n); + + // Write out definitions for the types not defined by SWIG. + + Printv(f_go_wrappers, "\n", NULL); + for (Iterator p = First(undefined_types); p.key != NULL; p = Next(p)) { + String *ty = goType(NULL, p.key); + if (Getattr(defined_types, ty) == NULL) { + String *cp = goCPointerType(p.key, false); + if (Getattr(defined_types, cp) == NULL) { + Printv(f_go_wrappers, "type ", cp, " uintptr\n", NULL); + Printv(f_go_wrappers, "type ", ty, " interface {\n", NULL); + Printv(f_go_wrappers, "\tSwigcptr() uintptr;\n", NULL); + Printv(f_go_wrappers, "}\n", NULL); + Printv(f_go_wrappers, "func (p ", cp, ") Swigcptr() uintptr {\n", + NULL); + Printv(f_go_wrappers, "\treturn uintptr(p)\n", NULL); + Printv(f_go_wrappers, "}\n\n", NULL); + } + Delete(cp); + } + Delete(ty); + } + Delete(undefined_types); + Delete(defined_types); + + /* Write and cleanup */ + + Dump(f_c_header, f_c_runtime); + + if (directorsEnabled()) { + Printf(f_c_directors_h, "#endif\n"); + Close(f_c_directors_h); + Delete(f_c_directors_h); + f_c_directors_h = NULL; + + Dump(f_c_directors, f_c_runtime); + Close(f_c_directors); + Delete(f_c_directors); + f_c_directors = NULL; + } + + Dump(f_c_runtime, f_c_begin); + Dump(f_c_wrappers, f_c_begin); + Dump(f_c_init, f_c_begin); + Dump(f_go_header, f_go_begin); + if (!saw_import) { + Dump(f_go_once, f_go_begin); + } + Dump(f_go_runtime, f_go_begin); + Dump(f_go_wrappers, f_go_begin); + if (!gccgo_flag) { + Dump(f_gc_header, f_gc_begin); + if (!saw_import) { + Dump(f_gc_once, f_gc_begin); + } + Dump(f_gc_runtime, f_gc_begin); + Dump(f_gc_wrappers, f_gc_begin); + } + + Delete(f_c_runtime); + Delete(f_c_header); + Delete(f_c_wrappers); + Delete(f_c_init); + Delete(f_go_runtime); + Delete(f_go_header); + Delete(f_go_wrappers); + if (!gccgo_flag) { + Delete(f_gc_runtime); + Delete(f_gc_header); + Delete(f_gc_wrappers); + } + + Close(f_c_begin); + Delete(f_c_begin); + Close(f_go_begin); + Delete(f_go_begin); + if (!gccgo_flag) { + Close(f_gc_begin); + Delete(f_gc_begin); + } + + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * importDirective() + * + * Handle a SWIG import statement by generating a Go import + * statement. + * ------------------------------------------------------------ */ + + virtual int importDirective(Node *n) { + String *hold_import = imported_package; + String *modname = Getattr(n, "module"); + if (modname != NULL) { + Printv(f_go_begin, "import \"", modname, "\"\n", NULL); + imported_package = modname; + saw_import = true; + } + int r = Language::importDirective(n); + imported_package = hold_import; + return r; + } + + /* ---------------------------------------------------------------------- + * functionWrapper() + * + * Implement a function. + * ---------------------------------------------------------------------- */ + + virtual int functionWrapper(Node *n) { + if (GetFlag(n, "feature:ignore")) { + return SWIG_OK; + } + + // We don't need explicit calls. + if (GetFlag(n, "explicitcall")) { + return SWIG_OK; + } + + String *name = Getattr(n, "sym:name"); + String *nodetype = Getattr(n, "nodeType"); + bool is_static = is_static_member_function || isStatic(n); + bool is_friend = isFriend(n); + bool is_ctor_dtor = false; + + SwigType *result = Getattr(n, "type"); + + // For some reason SWIG changs the "type" value during the call to + // functionWrapper. We need to remember the type for possible + // overload processing. + Setattr(n, "go:type", Copy(result)); + + String *go_name; + + String *r1 = NULL; + if (making_variable_wrappers) { + // Change the name of the variable setter and getter functions + // to be more Go like. + + bool is_set = Strcmp(Char(name) + Len(name) - 4, "_set") == 0; + assert(is_set || Strcmp(Char(name) + Len(name) - 4, "_get") == 0); + + // Start with Set or Get. + go_name = NewString(is_set ? "Set" : "Get"); + + // If this is a static variable, put in the class name, + // capitalized. + if (is_static && class_name != NULL) { + String *ccn = exportedName(class_name); + Append(go_name, ccn); + Delete(ccn); + } + + // Add the rest of the name, capitalized, dropping the _set or + // _get. + String *c1 = removeClassname(name); + String *c2 = exportedName(c1); + char *p = Char(c2); + int len = Len(p); + for (int i = 0; i < len - 4; ++i) { + Putc(p[i], go_name); + } + Delete(c2); + Delete(c1); + } else if (Cmp(nodetype, "constructor") == 0) { + is_ctor_dtor = true; + + // Change the name of a constructor to be more Go like. Change + // new_ to New, and capitalize the class name. + assert(Strncmp(name, "new_", 4) == 0); + String *c1 = NewString(Char(name) + 4); + String *c2 = exportedName(c1); + go_name = NewString("New"); + Append(go_name, c2); + Delete(c2); + Delete(c1); + + if (Swig_methodclass(n) != NULL + && Swig_directorclass(n) + && Strcmp(Char(Getattr(n, "wrap:action")), + director_prot_ctor_code) != 0) { + // The core SWIG code skips the first parameter when + // generating the $nondirector_new string. Recreate the + // action in this case. But don't it if we are using the + // special code for an abstract class. + String *call = Swig_cppconstructor_call(getClassType(), + Getattr(n, "parms")); + SwigType *type = Copy(getClassType()); + SwigType_add_pointer(type); + String *cres = Swig_cresult(type, "result", call); + Setattr(n, "wrap:action", cres); + } + } else if (Cmp(nodetype, "destructor") == 0) { + // No need to emit protected destructors. + if (!is_public(n)) { + return SWIG_OK; + } + + is_ctor_dtor = true; + + // Change the name of a destructor to be more Go like. Change + // delete_ to Delete and capitalize the class name. + assert(Strncmp(name, "delete_", 7) == 0); + String *c1 = NewString(Char(name) + 7); + String *c2 = exportedName(c1); + go_name = NewString("Delete"); + Append(go_name, c2); + Delete(c2); + Delete(c1); + + result = NewString("void"); + r1 = result; + } else { + if (!is_public(n)) { + return SWIG_OK; + } + + go_name = buildGoName(name, is_static, is_friend); + } + + String *overname = NULL; + if (Getattr(n, "sym:overloaded")) { + overname = Getattr(n, "sym:overname"); + } else if (class_name == NULL || is_static) { + if (!addSymbol(go_name, n)) { + return SWIG_ERROR; + } + } else { + String *c = Copy(class_name); + Putc('+', c); + Append(c, go_name); + if (!addSymbol(c, n)) { + return SWIG_ERROR; + } + Delete(c); + } + + String *wname = Swig_name_wrapper(name); + if (overname != NULL) { + Append(wname, overname); + } + Setattr(n, "wrap:name", wname); + + ParmList *parms = Getattr(n, "parms"); + Setattr(n, "wrap:parms", parms); + + int r = makeWrappers(n, name, go_name, overname, wname, NULL, parms, + result, is_static); + if (r != SWIG_OK) { + return r; + } + + if (Getattr(n, "sym:overloaded") && Getattr(n, "sym:nextSibling") == NULL) { + String *receiver = class_receiver; + if (is_static || is_ctor_dtor) { + receiver = NULL; + } + r = makeDispatchFunction(n, go_name, receiver, is_static, NULL, false); + if (r != SWIG_OK) { + return r; + } + } + + Delete(wname); + Delete(go_name); + if (r1 != NULL) { + Delete(r1); + } + + return SWIG_OK; + } + + /* ---------------------------------------------------------------------- + * staticmemberfunctionHandler + * + * For some reason the language code removes the "storage" attribute + * for a static function before calling functionWrapper, which means + * that we have no way of knowing whether a function is static or + * not. That makes no sense in the Go context. Here we note that a + * function is static. + * ---------------------------------------------------------------------- */ + + int staticmemberfunctionHandler(Node *n) { + assert(!is_static_member_function); + is_static_member_function = true; + int r = Language::staticmemberfunctionHandler(n); + is_static_member_function = false; + return r; + } + + /* ---------------------------------------------------------------------- + * makeWrappers() + * + * Write out the various function wrappers. + * N: The function we are emitting. + * NAME: The function name. + * GO_NAME: The name of the function in Go. + * OVERNAME: The overload string for overloaded function. + * WNAME: The SWIG wrapped name--the name of the C function. + * BASE: A list of the names of base classes, in the case where this + * is is a vritual method not defined in the current class. + * PARMS: The parameters. + * RESULT: The result type. + * IS_STATIC: Whether this is a static method or member. + * ---------------------------------------------------------------------- */ + + int makeWrappers(Node *n, String *name, String *go_name, String *overname, + String *wname, List *base, ParmList *parms, + SwigType *result, bool is_static) { + + assert(result != NULL); + + bool needs_wrapper; + int r = goFunctionWrapper(n, name, go_name, overname, wname, base, parms, + result, is_static, &needs_wrapper); + if (r != SWIG_OK) { + return r; + } + + if (!gccgo_flag) { + r = gcFunctionWrapper(n, name, go_name, overname, wname, parms, result, + is_static, needs_wrapper); + if (r != SWIG_OK) { + return r; + } + r = gccFunctionWrapper(n, base, wname, parms, result); + if (r != SWIG_OK) { + return r; + } + } else { + r = gccgoFunctionWrapper(n, base, wname, parms, result); + if (r != SWIG_OK) { + return r; + } + } + + if (class_methods != NULL) { + Setattr(class_methods, Getattr(n, "name"), NewString("")); + } + + return SWIG_OK; + } + + /* ---------------------------------------------------------------------- + * goFunctionWrapper() + * + * Write out a function wrapper in Go. When not implementing a + * method, the actual code is all in C; here we just declare the C + * function. When implementing a method, we have to call the C + * function, because it will have a different name. If base is not + * NULL, then we are being called to forward a virtual method to a + * base class. + * ---------------------------------------------------------------------- */ + + int goFunctionWrapper(Node *n, String *name, String *go_name, + String *overname, String *wname, List *base, + ParmList *parms, SwigType *result, bool is_static, + bool *p_needs_wrapper) { + Wrapper *dummy = NewWrapper(); + emit_attach_parmmaps(parms, dummy); + Swig_typemap_attach_parms("default", parms, dummy); + Swig_typemap_attach_parms("go", parms, dummy); + int parm_count = emit_num_arguments(parms); + int required_count = emit_num_required(parms); + + String *receiver = class_receiver; + if (receiver != NULL && is_static) { + receiver = NULL; + } + + String *nodetype = Getattr(n, "nodeType"); + bool is_constructor = Cmp(nodetype, "constructor") == 0; + bool is_destructor = Cmp(nodetype, "destructor") == 0; + if (is_constructor || is_destructor) { + assert(class_receiver != NULL); + assert(base == NULL); + receiver = NULL; + } + + bool add_to_interface = (interfaces != NULL + && !is_constructor + && !is_destructor + && !is_static + && overname == NULL + && is_public(n)); + + bool needs_wrapper = (gccgo_flag + || receiver != NULL + || is_constructor + || is_destructor + || parm_count > required_count); + + // See whether any of the function parameters are represented by + // interface values When calling the C++ code, we need to convert + // back to a uintptr. + if (!needs_wrapper) { + Parm *p = parms; + for (int i = 0; i < parm_count; ++i) { + p = getParm(p); + String *ty = Getattr(p, "type"); + if (goTypeIsInterface(p, ty)) { + needs_wrapper = true; + break; + } + p = nextParm(p); + } + } + if (goTypeIsInterface(NULL, result)) { + needs_wrapper = true; + } + + *p_needs_wrapper = needs_wrapper; + + // If this is a method, first declare the C function we will call. + // If we do not need a wrapper, then we will only be writing a + // declaration. + String *wrapper_name = NULL; + if (needs_wrapper) { + wrapper_name = buildGoWrapperName(name, overname); + + Printv(f_go_wrappers, "func ", wrapper_name, "(", NULL); + if (parm_count > required_count) { + Printv(f_go_wrappers, "int", NULL); + } + Parm *p = getParm(parms); + Swig_cparm_name(p, 0); + int i = 0; + if (is_destructor) { + if (parm_count > required_count) { + Printv(f_go_wrappers, ", ", NULL); + } + Printv(f_go_wrappers, "uintptr", NULL); + ++i; + p = nextParm(p); + } else if (receiver != NULL && (base != NULL || !is_constructor)) { + if (parm_count > required_count) { + Printv(f_go_wrappers, ", ", NULL); + } + Printv(f_go_wrappers, receiver, NULL); + if (base == NULL) { + ++i; + p = nextParm(p); + } + } + for (; i < parm_count; ++i) { + p = getParm(p); + // Give the parameter a name we will use below. + Swig_cparm_name(p, i); + if (i > 0 + || (base != NULL && receiver != NULL) + || parm_count > required_count) { + Printv(f_go_wrappers, ", ", NULL); + } + String *tm = goWrapperType(p, Getattr(p, "type"), false); + Printv(f_go_wrappers, tm, NULL); + Delete(tm); + p = nextParm(p); + } + Printv(f_go_wrappers, ")", NULL); + if (is_constructor) { + Printv(f_go_wrappers, " ", class_receiver, NULL); + } else { + if (SwigType_type(result) != T_VOID) { + String *tm = goWrapperType(n, result, true); + Printv(f_go_wrappers, " ", tm, NULL); + Delete(tm); + } + } + + if (gccgo_flag) { + Printv(f_go_wrappers, " __asm__ (\"", go_prefix, "_", wname, "\")", + NULL); + } + + Printv(f_go_wrappers, "\n\n", NULL); + } + + // Start defining the Go function. + + Printv(f_go_wrappers, "func ", NULL); + + Parm *p = parms; + int pi = 0; + + // Add the receiver if this is a method. + if (receiver != NULL) { + Printv(f_go_wrappers, "(", NULL); + if (base != NULL && receiver != NULL) { + Printv(f_go_wrappers, "_swig_base", NULL); + } else { + Printv(f_go_wrappers, Getattr(p, "lname"), NULL); + p = nextParm(p); + ++pi; + } + Printv(f_go_wrappers, " ", receiver, ") ", NULL); + } + + Printv(f_go_wrappers, go_name, NULL); + if (overname != NULL) { + Printv(f_go_wrappers, overname, NULL); + } + Printv(f_go_wrappers, "(", NULL); + + // If we are doing methods, add this function to the interface. + if (add_to_interface) { + Printv(interfaces, "\t", go_name, "(", NULL); + } + + // Write out the parameters to both the function definition and + // the interface. + + String *parm_print = NewString(""); + + for (; pi < parm_count; ++pi) { + p = getParm(p); + if (pi == 0 && is_destructor) { + String *cl = exportedName(class_name); + Printv(parm_print, Getattr(p, "lname"), " ", cl, NULL); + Delete(cl); + } else { + if (pi > (receiver != NULL && base == NULL ? 1 : 0)) { + Printv(parm_print, ", ", NULL); + } + if (pi >= required_count) { + Printv(parm_print, "_swig_args ...interface{}", NULL); + break; + } + if (needs_wrapper) { + Printv(parm_print, Getattr(p, "lname"), " ", NULL); + } + String *tm = goType(p, Getattr(p, "type")); + Printv(parm_print, tm, NULL); + Delete(tm); + } + p = nextParm(p); + } + + Printv(parm_print, ")", NULL); + + // Write out the result type. + if (is_constructor) { + String *cl = exportedName(class_name); + Printv(parm_print, " ", cl, NULL); + Delete(cl); + } else { + if (SwigType_type(result) != T_VOID) { + String *tm = goType(n, result); + Printv(parm_print, " ", tm, NULL); + Delete(tm); + } + } + + Printv(f_go_wrappers, parm_print, NULL); + if (add_to_interface) { + Printv(interfaces, parm_print, "\n", NULL); + } + + // If this is a wrapper, we need to actually call the C function. + if (needs_wrapper) { + Printv(f_go_wrappers, " {\n", NULL); + + if (parm_count > required_count) { + Parm *p = parms; + int i; + for (i = 0; i < required_count; ++i) { + p = getParm(p); + p = nextParm(p); + } + for (; i < parm_count; ++i) { + p = getParm(p); + String *tm = goType(p, Getattr(p, "type")); + Printv(f_go_wrappers, "\tvar ", Getattr(p, "lname"), " ", tm, "\n", + NULL); + Printf(f_go_wrappers, "\tif len(_swig_args) > %d {\n", + i - required_count); + Printf(f_go_wrappers, "\t\t%s = _swig_args[%d].(%s)\n", + Getattr(p, "lname"), i - required_count, tm); + Printv(f_go_wrappers, "\t}\n", NULL); + Delete(tm); + p = nextParm(p); + } + } + + Printv(f_go_wrappers, "\t", NULL); + if (SwigType_type(result) != T_VOID) { + Printv(f_go_wrappers, "return ", NULL); + } + + Printv(f_go_wrappers, wrapper_name, "(", NULL); + + if (parm_count > required_count) { + Printv(f_go_wrappers, "len(_swig_args)", NULL); + } + + if (base != NULL && receiver != NULL) { + if (parm_count > required_count) { + Printv(f_go_wrappers, ", ", NULL); + } + Printv(f_go_wrappers, "_swig_base", NULL); + } + + Parm *p = parms; + for (int i = 0; i < parm_count; ++i) { + p = getParm(p); + if (i > 0 + || (base != NULL && receiver != NULL) + || parm_count > required_count) { + Printv(f_go_wrappers, ", ", NULL); + } + Printv(f_go_wrappers, Getattr(p, "lname"), NULL); + + // If this is a destructor, then the C function expects the + // C++ value, and we have the interface. We need to get the + // C++ value. The same is true for a type represented as an + // interface. + if ((i == 0 && is_destructor) + || ((i > 0 || receiver == NULL || base != NULL || is_constructor) + && goTypeIsInterface(p, Getattr(p, "type")))) { + Printv(f_go_wrappers, ".Swigcptr()", NULL); + } + + p = nextParm(p); + } + Printv(f_go_wrappers, ")\n", NULL); + Printv(f_go_wrappers, "}\n", NULL); + } else { + if (gccgo_flag) { + Printv(f_go_wrappers, " __asm__ (\"", go_prefix, "_", + wname, "\")\n", NULL); + } + } + + Printv(f_go_wrappers, "\n", NULL); + + Delete(wrapper_name); + DelWrapper(dummy); + + return SWIG_OK; + } + + /* ---------------------------------------------------------------------- + * gcFunctionWrapper() + * + * This is used for 6g/8g, not for gccgo. Write out the function + * wrapper which will be compiled with 6c/8c. + * ---------------------------------------------------------------------- */ + + int gcFunctionWrapper(Node *n, String *name, String *go_name, + String *overname, String *wname, ParmList *parms, + SwigType *result, bool is_static, bool needs_wrapper) { + Wrapper *f = NewWrapper(); + + Printv(f->def, "#pragma dynimport ", wname, " ", wname, " \"", + soname, "\"\n", NULL); + Printv(f->def, "void (*", wname, ")(void*);\n", NULL); + Printv(f->def, "\n", NULL); + Printv(f->def, "void\n", NULL); + + Wrapper *dummy = NewWrapper(); + emit_attach_parmmaps(parms, dummy); + Swig_typemap_attach_parms("default", parms, dummy); + Swig_typemap_attach_parms("gosize", parms, dummy); + int parm_count = emit_num_arguments(parms); + int required_count = emit_num_required(parms); + + String *parm_size = NewString(""); + + if (parm_count > required_count) { + Append(parm_size, "SWIG_PARM_SIZE"); + } + + if (class_receiver != NULL && !is_static) { + if (Len(parm_size) > 0) { + Append(parm_size, " + "); + } + Append(parm_size, "SWIG_PARM_SIZE"); + } + + Parm *p = parms; + for (int i = 0; i < parm_count; ++i) { + p = getParm(p); + addGcTypeSize(p, Getattr(p, "type"), parm_size); + p = nextParm(p); + } + + if (SwigType_type(result) != T_VOID) { + addGcTypeSize(n, result, parm_size); + } + + if (Len(parm_size) == 0) { + Append(parm_size, "1"); + } + + String *fn_name; + if (!needs_wrapper) { + fn_name = Copy(go_name); + if (overname != NULL) { + Append(fn_name, overname); + } + } else { + fn_name = buildGoWrapperName(name, overname); + } + + // \xc2\xb7 is UTF-8 for U+00B7 which is Unicode 'Middle Dot' + Printv(f->def, "\xc2\xb7", fn_name, + "(struct { uint8 x[", parm_size, "];} p)", NULL); + + Delete(fn_name); + Delete(parm_size); + + Printv(f->code, "{\n", NULL); + Printv(f->code, "\tcgocall(", wname, ", &p);\n", NULL); + Printv(f->code, "}\n", NULL); + Printv(f->code, "\n", NULL); + + Wrapper_print(f, f_gc_wrappers); + + DelWrapper(f); + DelWrapper(dummy); + + return SWIG_OK; + } + + /* ---------------------------------------------------------------------- + * getGcTypeSize() + * + * Return the size to use when passing a type from 6g/8g to 6c/8c. + * ---------------------------------------------------------------------- */ + + String *addGcTypeSize(Node *n, SwigType *type, String *orig) { + if (Len(orig) > 0) { + Append(orig, " + "); + } + + String *go = goType(n, type); + if (Cmp(go, "string") == 0) { + // A string has a pointer and a length. + Append(orig, "(2 * SWIG_PARM_SIZE)"); + } else if (Strncmp(go, "[]", 2) == 0) { + // A slice has a pointer, a length, and a capacity. The + // length and capacity are always 4 bytes. + Append(orig, "(SWIG_PARM_SIZE + 8)"); + } else if (Strcmp(go, "float") == 0 || Strcmp(go, "float64") == 0) { + Append(orig, "8"); + } else if (Strcmp(go, "complex") == 0 || Strcmp(go, "complex64") == 0) { + Append(orig, "8"); + } else if (Strcmp(go, "complex128") == 0) { + Append(orig, "16"); + } else { + Append(orig, "SWIG_PARM_SIZE"); + } + + return orig; + } + + /* ---------------------------------------------------------------------- + * gccFunctionWrapper() + * + * This is used for 6g/8g, not for gccgo. Write out the function + * wrapper which will be compiled with gcc. If the base parameter + * is not NULL, this is calls the base class method rather than + * executing the SWIG wrapper code. + * ---------------------------------------------------------------------- */ + + int gccFunctionWrapper(Node *n, List *base, String *wname, ParmList *parms, + SwigType *result) { + Wrapper *f = NewWrapper(); + + Swig_save("gccFunctionWrapper", n, "parms", NULL); + + Parm *base_parm = NULL; + if (base != NULL && !isStatic(n)) { + SwigType *base_type = Copy(Getattr(class_node, "classtype")); + SwigType_add_pointer(base_type); + base_parm = NewParm(base_type, NewString("arg1"), n); + set_nextSibling(base_parm, parms); + parms = base_parm; + } + + emit_parameter_variables(parms, f); + emit_attach_parmmaps(parms, f); + int parm_count = emit_num_arguments(parms); + int required_count = emit_num_required(parms); + + emit_return_variable(n, result, f); + + // Start the function definition. + + Printv(f->def, + "#ifdef __cplusplus\n", + "extern \"C\"\n", + "#endif\n", + NULL); + + Printv(f->def, "void\n", wname, "(void *swig_v)\n", "{\n", NULL); + + // The single function parameter is a pointer to the real argument + // values. Define the structure that it points to. + + Printv(f->code, "\tstruct swigargs {\n", NULL); + + if (parm_count > required_count) { + Printv(f->code, "\t\tint _swig_optargc;\n", NULL); + } + + Parm *p = parms; + for (int i = 0; i < parm_count; ++i) { + p = getParm(p); + String *ln = Getattr(p, "lname"); + SwigType *pt = Getattr(p, "type"); + String *ct = gcCTypeForGoValue(p, pt, ln); + Printv(f->code, "\t\t\t", ct, ";\n", NULL); + Delete(ct); + p = nextParm(p); + } + if (SwigType_type(result) != T_VOID) { + Printv(f->code, "\t\tint : 0;\n", NULL); + String *ln = NewString("result"); + String *ct = gcCTypeForGoValue(n, result, ln); + Delete(ln); + Printv(f->code, "\t\t", ct, ";\n", NULL); + Delete(ct); + } + Printv(f->code, "\t} *swig_a = (struct swigargs *) swig_v;\n", NULL); + + Printv(f->code, "\n", NULL); + + // Copy the input arguments out of the structure into the + // parameter variables. + + p = parms; + for (int i = 0; i < parm_count; ++i) { + p = getParm(p); + + String *tm = Getattr(p, "tmap:in"); + if (tm == NULL) { + Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, + "Unable to use type %s as a function argument\n", + SwigType_str(Getattr(p, "type"), 0)); + } else { + String *ln = Getattr(p, "lname"); + String *input = NewString(""); + Printv(input, "swig_a->", ln, NULL); + Replaceall(tm, "$input", input); + Setattr(p, "emit:input", input); + if (i < required_count) { + Printv(f->code, "\t", tm, "\n", NULL); + } else { + Printf(f->code, "\tif (swig_a->_swig_optargc > %d) {\n", + i - required_count); + Printv(f->code, "\t\t", tm, "\n", NULL); + Printv(f->code, "\t}\n", NULL); + } + } + p = nextParm(p); + } + + Printv(f->code, "\n", NULL); + + // Do the real work of the function. + + checkConstraints(parms, f); + + emitGoAction(n, base, parms, result, f); + + argout(parms, f); + + cleanupFunction(n, f, parms); + + Printv(f->code, "}\n", NULL); + + Wrapper_print(f, f_c_wrappers); + + Swig_restore(n); + + DelWrapper(f); + if (base_parm != NULL) { + Delete(base_parm); + } + + return SWIG_OK; + } + + /* ---------------------------------------------------------------------- + * gccgoFunctionWrapper() + * + * This is used for gccgo, not 6g/8g. Write out the function + * wrapper which will be compiled with gcc. If the base parameter + * is not NULL, this is calls the base class method rather than + * executing the SWIG wrapper code. + * ---------------------------------------------------------------------- */ + + int gccgoFunctionWrapper(Node *n, List *base, String *wname, ParmList *parms, + SwigType *result) { + Wrapper *f = NewWrapper(); + + Swig_save("gccgoFunctionWrapper", n, "parms", NULL); + + Parm *base_parm = NULL; + if (base != NULL && !isStatic(n)) { + SwigType *base_type = Copy(Getattr(class_node, "classtype")); + SwigType_add_pointer(base_type); + base_parm = NewParm(base_type, NewString("arg1"), n); + set_nextSibling(base_parm, parms); + parms = base_parm; + } + + emit_parameter_variables(parms, f); + emit_attach_parmmaps(parms, f); + int parm_count = emit_num_arguments(parms); + int required_count = emit_num_required(parms); + + emit_return_variable(n, result, f); + + // Start the function definition. + + Printv(f->def, + "#ifdef __cplusplus\n", + "extern \"C\"\n", + "#endif\n", + NULL); + + String *fnname = NewString(""); + Printv(fnname, go_prefix, "_", wname, "(", NULL); + + if (parm_count > required_count) { + Printv(fnname, "int _swig_optargc", NULL); + } + + Parm *p = parms; + for (int i = 0; i < parm_count; ++i) { + p = getParm(p); + SwigType *pt = Getattr(p, "type"); + String *pn = NewString("g"); + Append(pn, Getattr(p, "lname")); + String *ct = gccgoCTypeForGoValue(p, pt, pn); + if (i > 0 || parm_count > required_count) { + Printv(fnname, ", ", NULL); + } + Printv(fnname, ct, NULL); + Delete(ct); + Delete(pn); + p = nextParm(p); + } + + Printv(fnname, ")", NULL); + + if (SwigType_type(result) == T_VOID) { + Printv(f->def, "void ", fnname, NULL); + } else { + String *ct = gccgoCTypeForGoValue(n, result, fnname); + Printv(f->def, ct, NULL); + Delete(ct); + } + + Printv(f->def, " {\n", NULL); + + Delete(fnname); + + if (SwigType_type(result) != T_VOID) { + String *ln = NewString("go_result"); + String *ct = gccgoCTypeForGoValue(n, result, ln); + Wrapper_add_local(f, "go_result", ct); + Delete(ct); + Delete(ln); + } + + // Copy the parameters into the variables which hold their values, + // applying appropriate transformations. + + p = parms; + for (int i = 0; i < parm_count; ++i) { + p = getParm(p); + + String *tm = Getattr(p, "tmap:in"); + if (tm == NULL) { + Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, + "Unable to use type %s as a function argument\n", + SwigType_str(Getattr(p, "type"), 0)); + } else { + String *ln = Getattr(p, "lname"); + String *pn = NewString("g"); + Append(pn, ln); + Replaceall(tm, "$input", pn); + Setattr(p, "emit:input", pn); + if (i < required_count) { + Printv(f->code, " ", tm, "\n", NULL); + } else { + Printf(f->code, " if (_swig_optargc > %d) {\n", i - required_count); + Printv(f->code, " ", tm, "\n", NULL); + Printv(f->code, " }\n", NULL); + } + } + + p = nextParm(p); + } + + Printv(f->code, "\n", NULL); + + // Do the real work of the function. + + checkConstraints(parms, f); + + emitGoAction(n, base, parms, result, f); + + argout(parms, f); + + cleanupFunction(n, f, parms); + + if (SwigType_type(result) != T_VOID) { + Printv(f->code, " return go_result;\n", NULL); + } + + Printv(f->code, "}\n", NULL); + + Wrapper_print(f, f_c_wrappers); + + Swig_restore(n); + + DelWrapper(f); + if (base_parm != NULL) { + Delete(base_parm); + } + + return SWIG_OK; + } + + /* ----------------------------------------------------------------------- + * checkConstraints() + * + * Check parameter constraints if any. This is used for the C/C++ + * function. This assumes that each parameter has an "emit:input" + * property with the name to use to refer to that parameter. + * ----------------------------------------------------------------------- */ + + void checkConstraints(ParmList *parms, Wrapper *f) { + Parm *p = parms; + while (p != NULL) { + String *tm = Getattr(p, "tmap:check"); + if (tm == NULL) { + p = nextSibling(p); + } else { + Replaceall(tm, "$input", Getattr(p, "emit:input")); + Printv(f->code, tm, "\n\n", NULL); + p = Getattr(p, "tmap:check:next"); + } + } + } + + /* ----------------------------------------------------------------------- + * getGoAction() + * + * Get the action of the function. This is used for C/C++ function. + * ----------------------------------------------------------------------- */ + + void emitGoAction(Node *n, List *base, ParmList *parms, SwigType *result, + Wrapper *f) { + String *actioncode; + if (base == NULL || isStatic(n)) { + Swig_director_emit_dynamic_cast(n, f); + actioncode = emit_action(n); + } else { + // Call the base class method. + actioncode = NewString(""); + + String *current = NewString(""); + if (!gccgo_flag) { + Printv(current, "swig_a->", NULL); + } + Printv(current, Getattr(parms, "lname"), NULL); + + String *last = NULL; + int vc = 0; + for (Iterator bi = First(base); bi.item != NULL; bi = Next(bi)) { + Printf(actioncode, " %s *swig_b%d = (%s *)%s;\n", bi.item, vc, + bi.item, current); + Delete(current); + current = NewString(""); + Printf(current, "swig_b%d", vc); + ++vc; + last = bi.item; + } + + String *code = Copy(Getattr(n, "wrap:action")); + Replaceall(code, Getattr(parms, "lname"), current); + Printv(actioncode, code, "\n", NULL); + } + + Swig_save("emitGoAction", n, "type", "tmap:out", NULL); + + Setattr(n, "type", result); + + String *tm = Swig_typemap_lookup_out("out", n, "result", f, actioncode); + if (tm == NULL) { + Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, + "Unable to use return type %s\n", + SwigType_str(result, 0)); + } else { + if (!gccgo_flag) { + Replaceall(tm, "$result", "swig_a->result"); + } else { + Replaceall(tm, "$result", "go_result"); + } + if (GetFlag(n, "feature:new")) { + Replaceall(tm, "$owner", "1"); + } else { + Replaceall(tm, "$owner", "0"); + } + Printv(f->code, tm, "\n", NULL); + Delete(tm); + } + + Swig_restore(n); + } + + /* ----------------------------------------------------------------------- + * argout() + * + * Handle argument output code if any. This is used for the C/C++ + * function. This assumes that each parameter has an "emit:input" + * property with the name to use to refer to that parameter. + * ----------------------------------------------------------------------- */ + + void argout(ParmList *parms, Wrapper *f) { + Parm *p = parms; + while (p != NULL) { + String *tm = Getattr(p, "tmap:argout"); + if (tm == NULL) { + p = nextSibling(p); + } else { + Replaceall(tm, "$result", "result"); + Replaceall(tm, "$input", Getattr(p, "emit:input")); + Printv(f->code, tm, "\n", NULL); + p = Getattr(p, "tmap:argout:next"); + } + } + } + + /* ----------------------------------------------------------------------- + * freearg() + * + * Handle argument cleanup code if any. This is used for the C/C++ + * function. This assumes that each parameter has an "emit:input" + * property with the name to use to refer to that parameter. + * ----------------------------------------------------------------------- */ + + String *freearg(ParmList *parms) { + String *ret = NewString(""); + Parm *p = parms; + while (p != NULL) { + String *tm = Getattr(p, "tmap:freearg"); + if (tm == NULL) { + p = nextSibling(p); + } else { + Replaceall(tm, "$input", Getattr(p, "emit:input")); + Printv(ret, tm, "\n", NULL); + p = Getattr(p, "tmap:freearg:next"); + } + } + return ret; + } + + /* ----------------------------------------------------------------------- + * cleanupFunction() + * + * Final function cleanup code. + * ----------------------------------------------------------------------- */ + + void cleanupFunction(Node *n, Wrapper *f, ParmList *parms) { + String *cleanup = freearg(parms); + Printv(f->code, cleanup, NULL); + + if (GetFlag(n, "feature:new")) { + String *tm = Swig_typemap_lookup("newfree", n, "result", 0); + if (tm != NULL) { + Replaceall(tm, "$source", "result"); + Printv(f->code, tm, "\n", NULL); + Delete(tm); + } + } + + Replaceall(f->code, "$cleanup", cleanup); + Delete(cleanup); + + Replaceall(f->code, "$symname", Getattr(n, "sym:name")); + } + + /* ----------------------------------------------------------------------- + * variableHandler() + * + * This exists just to set the making_variable_wrappers flag. + * ----------------------------------------------------------------------- */ + + virtual int variableHandler(Node *n) { + assert(!making_variable_wrappers); + making_variable_wrappers = true; + int r = Language::variableHandler(n); + making_variable_wrappers = false; + return r; + } + + /* ----------------------------------------------------------------------- + * constantWrapper() + * + * Product a const declaration. + * ------------------------------------------------------------------------ */ + + virtual int constantWrapper(Node *n) { + SwigType *type = Getattr(n, "type"); + + if (!SwigType_issimple(type) && SwigType_type(type) != T_STRING) { + return goComplexConstant(n, type); + } + + if (Getattr(n, "storage") != NULL + && Strcmp(Getattr(n, "storage"), "static") == 0) { + return goComplexConstant(n, type); + } + + String *go_name = buildGoName(Getattr(n, "sym:name"), false, false); + + if (!addSymbol(go_name, n)) { + Delete(go_name); + return SWIG_ERROR; + } + + String *tm = goType(n, type); + String *value = Getattr(n, "value"); + + String *copy = NULL; + if (SwigType_type(type) == T_BOOL) { + if (Cmp(value, "true") != 0 && Cmp(value, "false") != 0) { + return goComplexConstant(n, type); + } + } else if (SwigType_type(type) == T_STRING + || SwigType_type(type) == T_CHAR) { + // Backslash sequences are somewhat different in Go and C/C++. + if (Strchr(value, '\\') != NULL) { + return goComplexConstant(n, type); + } + } else { + // Accept a 0x prefix, and strip combinations of u and l + // suffixes. Otherwise accept digits, decimal point, and + // exponentiation. Treat anything else as too complicated to + // handle as a Go constant. + char *p = Char(value); + int len = strlen(p); + bool need_copy = false; + while (len > 0) { + char c = p[len - 1]; + if (c != 'l' && c != 'L' && c != 'u' && c != 'U') { + break; + } + --len; + need_copy = true; + } + bool is_hex = false; + int i = 0; + if (p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) { + i = 2; + is_hex = true; + } + for (; i < len; ++i) { + switch (p[i]) { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + break; + case 'a': case 'b': case 'c': case 'd': case 'f': + case 'A': case 'B': case 'C': case 'D': case 'F': + if (!is_hex) { + return goComplexConstant(n, type); + } + break; + case '.': case 'e': case 'E': case '+': case '-': + break; + default: + return goComplexConstant(n, type); + } + } + if (need_copy) { + copy = Copy(value); + Replaceall(copy, p + len, ""); + value = copy; + } + } + + Printv(f_go_wrappers, "const ", go_name, " ", tm, " = ", NULL); + if (SwigType_type(type) == T_STRING) { + Printv(f_go_wrappers, "\"", value, "\"", NULL); + } else if (SwigType_type(type) == T_CHAR) { + Printv(f_go_wrappers, "'", value, "'", NULL); + } else { + Printv(f_go_wrappers, value, NULL); + } + + Printv(f_go_wrappers, "\n", NULL); + + Delete(tm); + Delete(go_name); + if (copy != NULL) { + Delete(copy); + } + + return SWIG_OK; + } + + /* ---------------------------------------------------------------------- + * enumDeclaration() + * + * A C++ enum type turns into a Named go int type. + * ---------------------------------------------------------------------- */ + + virtual int enumDeclaration(Node *n) { + String *name = goEnumName(n); + if (Strcmp(name, "int") != 0) { + if (!ImportMode || imported_package == NULL) { + Printv(f_go_wrappers, "type ", name, " int\n", NULL); + } else { + String *nw = NewString(""); + Printv(nw, imported_package, ".", name, NULL); + Setattr(n, "go:enumname", nw); + } + } + Delete(name); + + return Language::enumDeclaration(n); + } + + /* ----------------------------------------------------------------------- + * enumvalueDeclaration() + * + * Declare a single value of an enum type. We fetch the value by + * calling a C/C++ function. + * ------------------------------------------------------------------------ */ + + virtual int enumvalueDeclaration(Node *n) { + if (!is_public(n)) { + return SWIG_OK; + } + if (Getattr(parentNode(n), "unnamed") != NULL) { + Setattr(n, "type", NewString("int")); + } else { + Setattr(n, "type", Getattr(parentNode(n), "enumtype")); + } + return goComplexConstant(n, Getattr(n, "type")); + } + + /* ----------------------------------------------------------------------- + * goComplexConstant() + * + * Handle a const declaration for something which is not a Go constant. + * ------------------------------------------------------------------------ */ + + int goComplexConstant(Node *n, SwigType *type) { + String *get = NewString(""); + Printv(get, "result = ", NULL); + + char quote; + if (Getattr(n, "wrappedasconstant") != NULL) { + quote = '\0'; + } else if (SwigType_type(type) == T_CHAR) { + quote = '\''; + } else if (SwigType_type(type) == T_STRING) { + quote = '"'; + } else { + quote = '\0'; + } + + if (quote != '\0') { + Printf(get, "%c", quote); + } + + Printv(get, Getattr(n, "value"), NULL); + + if (quote != '\0') { + Printf(get, "%c", quote); + } + + Printv(get, ";\n", NULL); + Setattr(n, "wrap:action", get); + + String* symname = Getattr(n, "sym:name"); + if (symname == NULL) { + symname = Getattr(n, "name"); + } + + String *sname = Copy(symname); + if (class_name != NULL) { + Append(sname, "_"); + Append(sname, class_name); + } + + String *go_name = NewString("_swig_get"); + if (class_name != NULL) { + Append(go_name, class_name); + Append(go_name, "_"); + } + Append(go_name, sname); + + String *wname = Swig_name_wrapper(sname); + Setattr(n, "wrap:name", wname); + + int r = makeWrappers(n, sname, go_name, NULL, wname, NULL, NULL, type, + true); + + if (r != SWIG_OK) { + return r; + } + + String *varname = buildGoName(symname, true, false); + String *t = goType(n, type); + Printv(f_go_wrappers, "var ", varname, " ", t, " = ", go_name, "()\n", + NULL); + + Delete(varname); + Delete(t); + Delete(go_name); + Delete(sname); + + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * classHandler() + * + * For a C++ class, in Go we generate both a struct and an + * interface. The interface will declare all the class public + * methods. We will define all the methods on the struct, so that + * the struct meets the interface. We then expect users of the + * class to use the interface. + * ------------------------------------------------------------ */ + + virtual int classHandler(Node *n) { + class_node = n; + + List *baselist = Getattr(n, "bases"); + bool has_base_classes = baselist != NULL && Len(baselist) > 0; + + String *name = Getattr(n, "sym:name"); + + String *go_name = exportedName(name); + + String *go_type_name = goCPointerType(Getattr(n, "classtypeobj"), true); + + class_name = name; + class_receiver = go_type_name; + class_methods = NewHash(); + + int isdir = GetFlag(n, "feature:director"); + int isnodir = GetFlag(n, "feature:nodirector"); + bool is_director = isdir && !isnodir; + + Printv(f_go_wrappers, "type ", go_type_name, " uintptr\n\n", NULL); + + // A method to return the pointer to the C++ class. This is used + // by generated code to convert between the interface and the C++ + // value. + Printv(f_go_wrappers, "func (p ", go_type_name, ") Swigcptr() uintptr {\n", + NULL); + Printv(f_go_wrappers, "\treturn (uintptr)(p)\n", NULL); + Printv(f_go_wrappers, "}\n\n", NULL); + + // A method used as a marker for the class, to avoid invalid + // interface conversions when using multiple inheritance. + Printv(f_go_wrappers, "func (p ", go_type_name, ") SwigIs", go_name, + "() {\n", NULL); + Printv(f_go_wrappers, "}\n\n", NULL); + + if (is_director) { + // Return the interface passed to the NewDirector function. + Printv(f_go_wrappers, "func (p ", go_type_name, + ") DirectorInterface() interface{} {\n", NULL); + Printv(f_go_wrappers, "\treturn nil\n", NULL); + Printv(f_go_wrappers, "}\n\n", NULL); + } + + // We have seen a definition for this type. + Setattr(defined_types, go_name, go_name); + Setattr(defined_types, go_type_name, go_type_name); + + interfaces = NewString(""); + + int r = Language::classHandler(n); + if (r != SWIG_OK) { + return r; + } + + if (has_base_classes) { + // For each method defined in a base class but not defined in + // this class, we need to define the method in this class. We + // can't use anonymous field inheritance because it works + // differently in Go and in C++. + + Hash *local = NewHash(); + for (Node *ni = Getattr(n, "firstChild"); + ni != NULL; + ni = nextSibling(ni)) { + + if (!is_public(ni)) { + continue; + } + + String *type = Getattr(ni, "nodeType"); + if (Cmp(type, "constructor") == 0 || Cmp(type, "destructor") == 0) { + continue; + } + + String *cname = Getattr(ni, "sym:name"); + if (cname == NULL) { + cname = Getattr(ni, "name"); + } + if (cname != NULL) { + Setattr(local, cname, NewString("")); + } + } + + for (Iterator b = First(baselist); b.item != NULL; b = Next(b)) { + List *bases = NewList(); + Append(bases, Getattr(b.item, "classtype")); + int r = addBase(n, b.item, bases, local); + if (r != SWIG_OK) { + return r; + } + Delete(bases); + } + + Delete(local); + + Hash *parents = NewHash(); + addFirstBaseInterface(n, parents, baselist); + int r = addExtraBaseInterfaces(n, parents, baselist); + Delete(parents); + if (r != SWIG_OK) { + return r; + } + } + + Printv(f_go_wrappers, "type ", go_name, " interface {\n", NULL); + Printv(f_go_wrappers, "\tSwigcptr() uintptr\n", NULL); + Printv(f_go_wrappers, "\tSwigIs", go_name, "()\n", NULL); + + if (is_director) { + Printv(f_go_wrappers, "\tDirectorInterface() interface{}\n", NULL); + } + + Append(f_go_wrappers, interfaces); + Printf(f_go_wrappers, "}\n\n", NULL); + Delete(interfaces); + + interfaces = NULL; + class_name = NULL; + class_receiver = NULL; + class_node = NULL; + Delete(class_methods); + class_methods = NULL; + + Delete(go_type_name); + + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * addBase() + * + * Implement methods and members defined in a parent class for a + * child class. + * ------------------------------------------------------------ */ + + int addBase(Node *n, Node *base, List *bases, Hash *local) { + if (GetFlag(base, "feature:ignore")) { + return SWIG_OK; + } + + for (Node *ni = Getattr(base, "firstChild"); + ni != NULL; + ni = nextSibling(ni)) { + + if (GetFlag(ni, "feature:ignore")) { + continue; + } + + if (!is_public(ni)) { + continue; + } + + String *type = Getattr(ni, "nodeType"); + if (Strcmp(type, "constructor") == 0 + || Strcmp(type, "destructor") == 0 + || Strcmp(type, "enum") == 0 + || Strcmp(type, "using") == 0) { + continue; + } + String *storage = Getattr(ni, "storage"); + if (Strcmp(storage, "typedef") == 0 || Strcmp(storage, "friend") == 0) { + continue; + } + + String *mname = Getattr(ni, "sym:name"); + if (mname == NULL) { + continue; + } + + String *lname = Getattr(ni, "name"); + if (Getattr(class_methods, lname) != NULL) { + continue; + } + if (Getattr(local, lname) != NULL) { + continue; + } + Setattr(local, lname, NewString("")); + + String *ty = NewString(Getattr(ni, "type")); + SwigType_push(ty, Getattr(ni, "decl")); + String *fullty = SwigType_typedef_resolve_all(ty); + bool is_function = SwigType_isfunction(fullty); + Delete(ty); + Delete(fullty); + + if (is_function) { + int r = goBaseMethod(n, bases, ni); + if (r != SWIG_OK) { + return r; + } + + if (Getattr(ni, "sym:overloaded") != NULL) { + for (Node *on = Getattr(ni, "sym:nextSibling"); + on != NULL; + on = Getattr(on, "sym:nextSibling")) { + r = goBaseMethod(n, bases, on); + if (r != SWIG_OK) { + return r; + } + } + + String *receiver = class_receiver; + bool is_static = isStatic(ni); + if (is_static) { + receiver = NULL; + } + String *go_name = buildGoName(Getattr(ni, "sym:name"), is_static, + false); + r = makeDispatchFunction(ni, go_name, receiver, is_static, NULL, + false); + Delete(go_name); + if (r != SWIG_OK) { + return r; + } + } + } else { + int r = goBaseVariable(n, bases, ni); + if (r != SWIG_OK) { + return r; + } + } + } + + List *baselist = Getattr(base, "bases"); + if (baselist != NULL && Len(baselist) > 0) { + for (Iterator b = First(baselist); b.item != NULL; b = Next(b)) { + List *nb = Copy(bases); + Append(nb, Getattr(b.item, "classtype")); + int r = addBase(n, b.item, nb, local); + Delete(nb); + if (r != SWIG_OK) { + return r; + } + } + } + + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * goBaseMethod() + * + * Implement a method defined in a parent class for a child class. + * ------------------------------------------------------------ */ + + int goBaseMethod(Node *method_class, List *bases, Node *method) { + String *symname = Getattr(method, "sym:name"); + if (!validIdentifier(symname)) { + return SWIG_OK; + } + + String *name = NewString(""); + Printv(name, Getattr(method_class, "sym:name"), "_", symname, NULL); + + bool is_static = isStatic(method); + + String *go_name = buildGoName(name, is_static, false); + + String *overname = NULL; + if (Getattr(method, "sym:overloaded")) { + overname = Getattr(method, "sym:overname"); + } + String *wname = Swig_name_wrapper(name); + if (overname != NULL) { + Append(wname, overname); + } + + String *result = NewString(Getattr(method, "type")); + SwigType_push(result, Getattr(method, "decl")); + if (SwigType_isqualifier(result)) { + Delete(SwigType_pop(result)); + } + Delete(SwigType_pop_function(result)); + + // If the base method is imported, wrap:action may not be set. + Swig_save("goBaseMethod", method, "wrap:action", "parms", NULL); + if (Getattr(method, "wrap:action") == NULL) { + if (!is_static) { + Swig_MethodToFunction(method, getNSpace(), getClassType(), + (Getattr(method, "template") != NULL + ? SmartPointer + : Extend | SmartPointer), + NULL, false); + // Remove any self parameter that was just added. + ParmList *parms = Getattr(method, "parms"); + if (parms != NULL && Getattr(parms, "self") != NULL) { + parms = CopyParmList(nextSibling(parms)); + Setattr(method, "parms", parms); + } + } else { + String *call = Swig_cfunction_call(Getattr(method, "name"), + Getattr(method, "parms")); + Setattr(method, "wrap:action", Swig_cresult(Getattr(method, "type"), + "result", call)); + } + } + + int r = makeWrappers(method, name, go_name, overname, wname, bases, + Getattr(method, "parms"), result, is_static); + + Swig_restore(method); + + Delete(result); + Delete(go_name); + Delete(name); + + return r; + } + + /* ------------------------------------------------------------ + * goBaseVariable() + * + * Add accessors for a member variable defined in a parent class for + * a child class. + * ------------------------------------------------------------ */ + + int goBaseVariable(Node *var_class, List *bases, Node *var) { + if (isStatic(var)) { + return SWIG_OK; + } + + String *var_name = buildGoName(Getattr(var, "sym:name"), false, false); + + Swig_save("goBaseVariable", var, "type", "wrap:action", NULL); + + // For a pointer type we apparently have to wrap in the decl. + SwigType *var_type = NewString(Getattr(var, "type")); + SwigType_push(var_type, Getattr(var, "decl")); + Setattr(var, "type", var_type); + + SwigType *vt = Copy(var_type); + if (SwigType_isclass(vt)) { + SwigType_add_pointer(vt); + } + + int flags = Extend | SmartPointer | use_naturalvar_mode(var); + if (is_non_virtual_protected_access(var)) { + flags |= CWRAP_ALL_PROTECTED_ACCESS; + } + + String *mname = Swig_name_member(getNSpace(), + Getattr(var_class, "sym:name"), + var_name); + + if (is_assignable(var)) { + for (Iterator ki = First(var); ki.key != NULL; ki = Next(ki)) { + if (Strncmp(ki.key, "tmap:", 5) == 0) { + Delattr(var, ki.key); + } + } + Swig_save("goBaseVariableSet", var, "name", "sym:name", "type", NULL); + + String *mname_set = NewString("Set"); + Append(mname_set, mname); + + String *go_name = NewString("Set"); + Append(go_name, var_name); + + Swig_MembersetToFunction(var, class_name, flags); + + String *wname = Swig_name_wrapper(mname_set); + ParmList *parms = NewParm(vt, var_name, var); + String *result = NewString("void"); + int r = makeWrappers(var, mname_set, go_name, NULL, wname, bases, parms, + result, false); + if (r != SWIG_OK) { + return r; + } + Delete(wname); + Delete(parms); + Delete(result); + Delete(go_name); + Delete(mname_set); + + Swig_restore(var); + for (Iterator ki = First(var); ki.key != NULL; ki = Next(ki)) { + if (Strncmp(ki.key, "tmap:", 5) == 0) { + Delattr(var, ki.key); + } + } + } + + Swig_MembergetToFunction(var, class_name, flags); + + String *mname_get = NewString("Get"); + Append(mname_get, mname); + + String *go_name = NewString("Get"); + Append(go_name, var_name); + + String *wname = Swig_name_wrapper(mname_get); + + int r = makeWrappers(var, mname_get, go_name, NULL, wname, bases, NULL, + vt, false); + if (r != SWIG_OK) { + return r; + } + + Delete(wname); + Delete(mname_get); + Delete(go_name); + Delete(mname); + Delete(var_name); + Delete(var_type); + Delete(vt); + + Swig_restore(var); + + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * addFirstBaseInterface() + * + * When a C++ class uses multiple inheritance, we can use the C++ + * pointer for the first base class but not for any subsequent base + * classes. However, the Go interface will match the interface for + * all the base classes. To avoid accidentally treating a class as + * a pointer to a base class other than the first one, we use an + * isClassname method. This function adds those methods as + * required. + * + * For convenience when using multiple inheritance, we also add + * functions to retrieve the base class pointers. + * ------------------------------------------------------------ */ + + void addFirstBaseInterface(Node *n, Hash *parents, List *bases) { + if (bases == NULL || Len(bases) == 0) { + return; + } + Iterator b = First(bases); + if (!GetFlag(b.item, "feature:ignore")) { + String *go_name = buildGoName(Getattr(n, "sym:name"), false, false); + String *go_type_name = goCPointerType(Getattr(n, "classtypeobj"), true); + String *go_base_name = exportedName(Getattr(b.item, "sym:name")); + String *go_base_type = goType(n, Getattr(b.item, "classtypeobj")); + String *go_base_type_name = goCPointerType(Getattr(b.item, + "classtypeobj"), + true); + + Printv(f_go_wrappers, "func (p ", go_type_name, ") SwigIs", go_base_name, + "() {\n", NULL); + Printv(f_go_wrappers, "}\n\n", NULL); + + Printv(interfaces, "\tSwigIs", go_base_name, "()\n", NULL); + + Printv(f_go_wrappers, "func (p ", go_type_name, ") SwigGet", go_base_name, + "() ", go_base_type, " {\n", NULL); + Printv(f_go_wrappers, "\treturn ", go_base_type_name, + "(p.Swigcptr())\n", NULL); + Printv(f_go_wrappers, "}\n\n", NULL); + + Printv(interfaces, "\tSwigGet", go_base_name, "() ", go_base_type, "\n", + NULL); + + Setattr(parents, go_base_name, NewString("")); + + Delete(go_name); + Delete(go_type_name); + Delete(go_base_type); + Delete(go_base_type_name); + } + + addFirstBaseInterface(n, parents, Getattr(b.item, "bases")); + } + + /* ------------------------------------------------------------ + * addExtraBaseInterfaces() + * + * Add functions to retrieve the base class pointers for all base + * classes other than the first. + * ------------------------------------------------------------ */ + + int addExtraBaseInterfaces(Node *n, Hash *parents, List *bases) { + Iterator b = First(bases); + + Node *fb = b.item; + + for (b = Next(b); b.item != NULL; b = Next(b)) { + if (GetFlag(b.item, "feature:ignore")) { + continue; + } + + String *go_base_name = exportedName(Getattr(b.item, "sym:name")); + + Swig_save("addExtraBaseInterface", n, "wrap:action", "wrap:name", + "wrap:parms", NULL); + + SwigType *type = Copy(Getattr(n, "classtypeobj")); + SwigType_add_pointer(type); + Parm *parm = NewParm(type, "self", n); + Setattr(n, "wrap:parms", parm); + + String *pn = Swig_cparm_name(parm, 0); + String *action = NewString(""); + Printv(action, "result = (", Getattr(b.item, "classtype"), "*)", pn, + ";", NULL); + Delete(pn); + + Setattr(n, "wrap:action", action); + + String *name = Copy(class_name); + Append(name, "_SwigGet"); + Append(name, go_base_name); + + String *go_name = NewString("SwigGet"); + String *c1 = exportedName(go_base_name); + Append(go_name, c1); + Delete(c1); + + String *wname = Swig_name_wrapper(name); + Setattr(n, "wrap:name", wname); + + SwigType *result = Copy(Getattr(b.item, "classtypeobj")); + SwigType_add_pointer(result); + + int r = makeWrappers(n, name, go_name, NULL, wname, NULL, parm, result, + false); + if (r != SWIG_OK) { + return r; + } + + Swig_restore(n); + + Setattr(parents, go_base_name, NewString("")); + + Delete(go_name); + Delete(type); + Delete(parm); + Delete(action); + Delete(result); + + String *ns = NewString(""); + addParentExtraBaseInterfaces(n, parents, b.item, false, ns); + Delete(ns); + } + + if (!GetFlag(fb, "feature:ignore")) { + String *ns = NewString(""); + addParentExtraBaseInterfaces(n, parents, fb, true, ns); + Delete(ns); + } + + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * addParentExtraBaseInterfaces() + * + * Add functions to retrieve the base class pointers for all base + * classes of parents other than the first base class at each level. + * ------------------------------------------------------------ */ + + void addParentExtraBaseInterfaces(Node *n, Hash *parents, Node *base, + bool is_base_first, String *sofar) { + List *baselist = Getattr(base, "bases"); + if (baselist == NULL || Len(baselist) == 0) { + return; + } + + String *go_this_base_name = exportedName(Getattr(base, "sym:name")); + + String *sf = NewString(""); + Printv(sf, sofar, ".SwigGet", go_this_base_name, "()", NULL); + + Iterator b = First(baselist); + + if (is_base_first) { + if (!GetFlag(b.item, "feature:ignore")) { + addParentExtraBaseInterfaces(n, parents, b.item, true, sf); + } + + b = Next(b); + if (b.item == NULL) { + return; + } + } + + String *go_name = buildGoName(Getattr(n, "sym:name"), false, false); + String *go_type_name = goCPointerType(Getattr(n, "classtypeobj"), true); + + for (; b.item != NULL; b = Next(b)) { + if (GetFlag(b.item, "feature:ignore")) { + continue; + } + + String *go_base_name = exportedName(Getattr(b.item, "sym:name")); + + if (Getattr(parents, go_base_name) == NULL) { + Printv(f_go_wrappers, "func (p ", go_type_name, ") SwigGet", + go_base_name, "() ", go_base_name, " {\n", NULL); + Printv(f_go_wrappers, "\treturn p", sf, ".SwigGet", go_base_name, + "()\n", NULL); + Printv(f_go_wrappers, "}\n\n", NULL); + + Printv(interfaces, "\tSwigGet", go_base_name, "() ", go_base_name, "\n", + NULL); + + addParentExtraBaseInterfaces(n, parents, b.item, false, sf); + + Setattr(parents, go_base_name, NewString("")); + } + } + + Delete(go_name); + Delete(go_type_name); + Delete(go_this_base_name); + Delete(sf); + } + + /* ------------------------------------------------------------ + * classDirectorInit + * + * Add support for a director class. + * + * Virtual inheritance is different in Go and C++. We implement + * director classes by defining a new function in Go, + * NewDirectorClassname, which takes a empty interface value and + * creates an instance of a new child class. The new child class + * refers all methods back to Go. The Go code checks whether the + * value passed to NewDirectorClassname implements that method; if + * it does, it calls it, otherwise it calls back into C++. + * ------------------------------------------------------------ */ + + int classDirectorInit(Node *n) { + // Because we use a different function to handle inheritance in + // Go, ordinary creations of the object should not create a + // director object. + Delete(director_ctor_code); + director_ctor_code = NewString("$nondirector_new"); + + class_node = n; + + String *name = Getattr(n, "sym:name"); + + assert(class_name == NULL); + class_name = name; + + String *go_name = exportedName(name); + + String *go_type_name = goCPointerType(Getattr(n, "classtypeobj"), true); + + assert(class_receiver == NULL); + class_receiver = go_type_name; + + String *director_struct_name = NewString("_swig_Director"); + Append(director_struct_name, go_name); + + String* cxx_director_name = NewString("SwigDirector_"); + Append(cxx_director_name, name); + + // The Go type of the director class. + Printv(f_go_wrappers, "type ", director_struct_name, " struct {\n", NULL); + Printv(f_go_wrappers, "\t", go_type_name, "\n", NULL); + Printv(f_go_wrappers, "\tv interface{}\n", NULL); + Printv(f_go_wrappers, "}\n\n", NULL); + + Printv(f_go_wrappers, "func (p *", director_struct_name, + ") Swigcptr() uintptr {\n", NULL); + Printv(f_go_wrappers, "\treturn p.", go_type_name, ".Swigcptr()\n", NULL); + Printv(f_go_wrappers, "}\n\n", NULL); + + Printv(f_go_wrappers, "func (p *", director_struct_name, ") SwigIs", + go_name, "() {\n", NULL); + Printv(f_go_wrappers, "}\n\n", NULL); + + Printv(f_go_wrappers, "func (p *", director_struct_name, + ") DirectorInterface() interface{} {\n", NULL); + Printv(f_go_wrappers, "\treturn p.v\n", NULL); + Printv(f_go_wrappers, "}\n\n", NULL); + + // Start defining the director class. + Printv(f_c_directors_h, "class ", cxx_director_name, " : public ", + Getattr(n, "classtype"), "\n", NULL); + Printv(f_c_directors_h, "{\n", NULL); + Printv(f_c_directors_h, " public:\n", NULL); + + Delete(director_struct_name); + Delete(cxx_director_name); + + class_methods = NewHash(); + + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * classDirectorConstructor + * + * Emit a constructor for a director class. + * ------------------------------------------------------------ */ + + int classDirectorConstructor(Node *n) { + bool is_ignored = GetFlag(n, "feature:ignore"); + + String *name = Getattr(n, "sym:name"); + if (name == NULL) { + assert(is_ignored); + name = Getattr(n, "name"); + } + + String *overname = NULL; + if (Getattr(n, "sym:overloaded")) { + overname = Getattr(n, "sym:overname"); + } + + String *go_name = exportedName(name); + + ParmList *parms = Getattr(n, "parms"); + Setattr(n, "wrap:parms", parms); + + String *cn = exportedName(Getattr(parentNode(n), "sym:name")); + + String *go_type_name = goCPointerType(Getattr(parentNode(n), + "classtypeobj"), + true); + + String *director_struct_name = NewString("_swig_Director"); + Append(director_struct_name, cn); + + String *fn_name = NewString("_swig_NewDirector"); + Append(fn_name, cn); + Append(fn_name, go_name); + + if (overname == NULL && !is_ignored) { + if (!addSymbol(fn_name, n)) { + return SWIG_ERROR; + } + } + + String *wname = Swig_name_wrapper(fn_name); + + if (overname != NULL) { + Append(wname, overname); + } + Setattr(n, "wrap:name", wname); + + bool is_static = isStatic(n); + + Wrapper *dummy = NewWrapper(); + emit_attach_parmmaps(parms, dummy); + DelWrapper(dummy); + + Swig_typemap_attach_parms("go", parms, NULL); + int parm_count = emit_num_arguments(parms); + + String *func_name = NewString("NewDirector"); + Append(func_name, go_name); + + String *func_with_over_name = Copy(func_name); + if (overname != NULL) { + Append(func_with_over_name, overname); + } + + SwigType *first_type = NewString("void"); + SwigType_add_pointer(first_type); + Parm *first_parm = NewParm(first_type, "swig_p", n); + set_nextSibling(first_parm, parms); + Setattr(first_parm, "lname", "p"); + + Parm *p = parms; + for (int i = 0; i < parm_count; ++i) { + p = getParm(p); + Swig_cparm_name(p, i); + p = nextParm(p); + } + + if (!is_ignored) { + // Declare the C++ wrapper. + Printv(f_go_wrappers, "func ", fn_name, NULL); + if (overname != NULL) { + Printv(f_go_wrappers, overname, NULL); + } + Printv(f_go_wrappers, "(*", director_struct_name, NULL); + + p = parms; + for (int i = 0; i < parm_count; ++i) { + p = getParm(p); + String *tm = goType(p, Getattr(p, "type")); + Printv(f_go_wrappers, ", ", tm, NULL); + Delete(tm); + p = nextParm(p); + } + + Printv(f_go_wrappers, ") ", go_type_name, NULL); + + if (gccgo_flag) { + Printv(f_go_wrappers, " __asm__(\"", go_prefix, "_", wname, "\")", + NULL); + } + + Printv(f_go_wrappers, "\n\n", NULL); + + Printv(f_go_wrappers, "func ", func_with_over_name, "(v interface{}", + NULL); + + p = parms; + for (int i = 0; i < parm_count; ++i) { + p = getParm(p); + // Set the lname parameter. + Printv(f_go_wrappers, ", ", Getattr(p, "lname"), " ", NULL); + String *tm = goType(p, Getattr(p, "type")); + Printv(f_go_wrappers, tm, NULL); + Delete(tm); + p = nextParm(p); + } + + Printv(f_go_wrappers, ") ", cn, " {\n", NULL); + + Printv(f_go_wrappers, "\tp := &", director_struct_name, "{0, v}\n", + NULL); + Printv(f_go_wrappers, "\tp.", class_receiver, " = ", fn_name, NULL); + if (overname != NULL) { + Printv(f_go_wrappers, overname, NULL); + } + Printv(f_go_wrappers, "(p", NULL); + + p = parms; + for (int i = 0; i < parm_count; ++i) { + p = getParm(p); + Printv(f_go_wrappers, ", ", Getattr(p, "lname"), NULL); + p = nextParm(p); + } + + Printv(f_go_wrappers, ")\n", NULL); + Printv(f_go_wrappers, "\treturn p\n", NULL); + Printv(f_go_wrappers, "}\n\n", NULL); + + SwigType *result = Copy(Getattr(parentNode(n), "classtypeobj")); + SwigType_add_pointer(result); + + Swig_save("classDirectorConstructor", n, "wrap:name", "wrap:action", + NULL); + + Setattr(n, "wrap:name", Swig_name_wrapper(name)); + + String *action = NewString(""); + Printv(action, "result = new SwigDirector_", class_name, "(", NULL); + String *pname = Swig_cparm_name(NULL, 0); + Printv(action, pname, NULL); + Delete(pname); + p = parms; + for (int i = 0; i < parm_count; ++i) { + p = getParm(p); + String *pname = Swig_cparm_name(NULL, i + 1); + Printv(action, ", ", NULL); + if (SwigType_isreference(Getattr(p, "type"))) { + Printv(action, "*", NULL); + } + Printv(action, pname, NULL); + Delete(pname); + p = nextParm(p); + } + Printv(action, ");", NULL); + Setattr(n, "wrap:action", action); + + if (!gccgo_flag) { + int r = gcFunctionWrapper(n, fn_name, fn_name, overname, wname, + first_parm, result, is_static, false); + if (r != SWIG_OK) { + return r; + } + r = gccFunctionWrapper(n, NULL, wname, first_parm, result); + if (r != SWIG_OK) { + return r; + } + } else { + int r = gccgoFunctionWrapper(n, NULL, wname, first_parm, result); + if (r != SWIG_OK) { + return r; + } + } + + Swig_restore(n); + + Delete(result); + } + + String *cxx_director_name = NewString("SwigDirector_"); + Append(cxx_director_name, class_name); + + String *decl = Swig_method_decl(NULL, Getattr(n, "decl"), + cxx_director_name, first_parm, 0, 0); + Printv(f_c_directors_h, " ", decl, ";\n", NULL); + Delete(decl); + + decl = Swig_method_decl(NULL, Getattr(n, "decl"), + cxx_director_name, first_parm, 0, 0); + Printv(f_c_directors, cxx_director_name, "::", decl, "\n", NULL); + Delete(decl); + + Printv(f_c_directors, " : ", Getattr(parentNode(n), "classtype"), "(", + NULL); + + p = parms; + for (int i = 0; i < parm_count; ++i) { + p = getParm(p); + if (i > 0) { + Printv(f_c_directors, ", ", NULL); + } + String *pn = Getattr(p, "name"); + assert(pn != NULL); + Printv(f_c_directors, pn, NULL); + p = nextParm(p); + } + Printv(f_c_directors, "),\n", NULL); + Printv(f_c_directors, " go_val(swig_p)\n", NULL); + Printv(f_c_directors, "{ }\n\n", NULL); + + if (Getattr(n, "sym:overloaded") && Getattr(n, "sym:nextSibling") == NULL) { + int r = makeDispatchFunction(n, func_name, cn, is_static, + Getattr(parentNode(n), "classtypeobj"), + false); + if (r != SWIG_OK) { + return r; + } + } + + Delete(cxx_director_name); + Delete(go_name); + Delete(cn); + Delete(go_type_name); + Delete(director_struct_name); + Delete(fn_name); + Delete(func_name); + Delete(func_with_over_name); + Delete(wname); + Delete(first_type); + Delete(first_parm); + + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * classDirectorDestructor + * + * Emit a destructor for a director class. + * ------------------------------------------------------------ */ + + int classDirectorDestructor(Node *n) { + if (!is_public(n)) { + return SWIG_OK; + } + + bool is_ignored = GetFlag(n, "feature:ignore"); + + if (!is_ignored) { + String *fnname = NewString("DeleteDirector"); + String *c1 = exportedName(class_name); + Append(fnname, c1); + Delete(c1); + + String *wname = Swig_name_wrapper(fnname); + + Setattr(n, "wrap:name", fnname); + + Swig_DestructorToFunction(n, getNSpace(), + Getattr(parentNode(n), "classtype"), + CPlusPlus, Extend); + + ParmList *parms = Getattr(n, "parms"); + Setattr(n, "wrap:parms", parms); + + String *result = NewString("void"); + int r = makeWrappers(n, fnname, fnname, NULL, wname, NULL, parms, result, + isStatic(n)); + if (r != SWIG_OK) { + return r; + } + + Delete(result); + Delete(fnname); + Delete(wname); + } + + // Generate the destructor for the C++ director class. Since the + // Go code is keeping a pointer to the C++ object, we need to call + // back to the Go code to let it know that the C++ object is gone. + + String *wname = NewString("_swiggo_wrap_DeleteDirector_"); + Append(wname, class_name); + + String *go_name = NewString("Swiggo_DeleteDirector_"); + Append(go_name, class_name); + + String *cn = exportedName(class_name); + + String *director_struct_name = NewString("_swig_Director"); + Append(director_struct_name, cn); + + Printv(f_c_directors_h, " virtual ~SwigDirector_", class_name, "()", + NULL); + + String *throws = buildThrow(n); + if (throws != NULL) { + Printv(f_c_directors_h, " ", throws, NULL); + } + + Printv(f_c_directors_h, ";\n", NULL); + + if (!is_ignored) { + if (!gccgo_flag) { + Printv(f_c_directors, "extern \"C\" void ", wname, "(void*, int);\n", + NULL); + } else { + Printv(f_c_directors, "extern \"C\" void ", wname, "(void*) __asm__(\"", + go_prefix, ".", package, ".", go_name, "\");\n", NULL); + } + } + + Printv(f_c_directors, "SwigDirector_", class_name, "::~SwigDirector_", + class_name, "()", NULL); + + if (throws != NULL) { + Printv(f_c_directors, " ", throws, NULL); + Delete(throws); + } + + Printv(f_c_directors, "\n", NULL); + Printv(f_c_directors, "{\n", NULL); + + if (!is_ignored) { + if (!gccgo_flag) { + Printv(f_c_directors, " struct { void *p; } a;\n", NULL); + Printv(f_c_directors, " a.p = go_val;\n", NULL); + Printv(f_c_directors, " crosscall2(", wname, + ", &a, (int) sizeof a);\n", NULL); + + Printv(f_gc_wrappers, "#pragma dynexport ", wname, " ", wname, "\n", + NULL); + Printv(f_gc_wrappers, "extern void \xc2\xb7", go_name, "();\n", NULL); + Printv(f_gc_wrappers, "void\n", NULL); + Printv(f_gc_wrappers, wname, "(void *a, int32 n)\n", NULL); + Printv(f_gc_wrappers, "{\n", NULL); + Printv(f_gc_wrappers, "\tcgocallback(\xc2\xb7", go_name, ", a, n);\n", + NULL); + Printv(f_gc_wrappers, "}\n\n", NULL); + } else { + Printv(f_c_directors, " ", wname, "(go_val);\n", NULL); + } + } + + Printv(f_c_directors, "}\n\n", NULL); + + if (!is_ignored) { + Printv(f_go_wrappers, "func ", go_name, "(p *", director_struct_name, + ") {\n", NULL); + Printv(f_go_wrappers, "\tp.", class_receiver, " = 0\n", NULL); + Printv(f_go_wrappers, "}\n\n", NULL); + } + + Delete(wname); + Delete(go_name); + Delete(cn); + Delete(director_struct_name); + + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * classDirectorMethod + * + * Emit a method for a director class, plus its overloads. + * ------------------------------------------------------------ */ + + int classDirectorMethod(Node *n, Node *parent, String *super) { + (void) super; + + bool is_ignored = GetFlag(n, "feature:ignore"); + bool is_pure_virtual = (Cmp(Getattr(n, "storage"), "virtual") == 0 + && Cmp(Getattr(n, "value"), "0") == 0); + + // We don't need explicit calls. + if (GetFlag(n, "explicitcall")) { + return SWIG_OK; + } + + String *name = Getattr(n, "sym:name"); + if (name == NULL) { + assert(is_ignored); + name = Getattr(n, "name"); + } + + if (Getattr(class_methods, name) != NULL) { + // We need to emit a pure virtual function, even if it is + // overloaded. Otherwise we won't be able to create an instance + // of the director class. The function doesn't need to actually + // do anything. + if (!is_pure_virtual || Getattr(n, "sym:overloaded") != NULL) { + return SWIG_OK; + } + } + Setattr(class_methods, name, NewString("")); + + if (Getattr(n, "sym:overloaded") == NULL) { + int r = oneClassDirectorMethod(n, parent); + if (r != SWIG_OK) { + return r; + } + } else { + // Handle overloaded methods here, because otherwise we will + // reject them in the class_methods hash table. We need to use + // class_methods so that we correctly handle cases where a + // function in one class hides a function of the same name in a + // parent class. + for (Node *on = Getattr(n, "sym:overloaded"); + on != NULL; + on = Getattr(on, "sym:nextSibling")) { + int r = oneClassDirectorMethod(on, parent); + if (r != SWIG_OK) { + return r; + } + + // Swig_overload_rank expects wrap:name and wrap:parms to be + // set. + String *wn = Swig_name_wrapper(Getattr(on, "sym:name")); + Append(wn, Getattr(on, "sym:overname")); + Setattr(on, "wrap:name", wn); + Delete(wn); + Setattr(on, "wrap:parms", Getattr(on, "parms")); + } + + bool is_static = isStatic(n); + + String *cn = exportedName(Getattr(parent, "sym:name")); + String *go_name = buildGoName(name, is_static, false); + + String *director_struct_name = NewString("_swig_Director"); + Append(director_struct_name, cn); + + int r = makeDispatchFunction(n, go_name, director_struct_name, is_static, + director_struct_name, false); + if (r != SWIG_OK) { + return r; + } + + String *go_upcall = NewString("Director"); + Append(go_upcall, cn); + Append(go_upcall, go_name); + r = makeDispatchFunction(n, go_upcall, director_struct_name, is_static, + director_struct_name, true); + if (r != SWIG_OK) { + return r; + } + + Delete(cn); + Delete(go_name); + Delete(director_struct_name); + Delete(go_upcall); + } + + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * oneClassDirectorMethod + * + * Emit a method for a director class. + * ------------------------------------------------------------ */ + + int oneClassDirectorMethod(Node *n, Node *parent) { + bool is_ignored = GetFlag(n, "feature:ignore"); + bool is_pure_virtual = (Cmp(Getattr(n, "storage"), "virtual") == 0 + && Cmp(Getattr(n, "value"), "0") == 0); + + String *name = Getattr(n, "sym:name"); + if (name == NULL) { + assert(is_ignored); + name = Getattr(n, "name"); + } + + String *overname = NULL; + if (Getattr(n, "sym:overloaded")) { + overname = Getattr(n, "sym:overname"); + } + + String *cn = exportedName(Getattr(parent, "sym:name")); + + String *go_type_name = goCPointerType(Getattr(parent, "classtypeobj"), + true); + + String *director_struct_name = NewString("_swig_Director"); + Append(director_struct_name, cn); + + bool is_static = isStatic(n); + + String *go_name = buildGoName(name, is_static, false); + + ParmList *parms = Getattr(n, "parms"); + Setattr(n, "wrap:parms", parms); + + Wrapper *dummy = NewWrapper(); + emit_attach_parmmaps(parms, dummy); + DelWrapper(dummy); + + Swig_typemap_attach_parms("go", parms, NULL); + int parm_count = emit_num_arguments(parms); + + SwigType *result = Getattr(n, "returntype"); + if (result == NULL) { + // This can happen when following overloads. + result = NewString(Getattr(n, "type")); + SwigType_push(result, Getattr(n, "decl")); + if (SwigType_isqualifier(result)) { + Delete(SwigType_pop(result)); + } + Delete(SwigType_pop_function(result)); + Setattr(n, "returntype", result); + } + + // Save the type for overload processing. + Setattr(n, "go:type", result); + + String *interface_name = NewString("_swig_DirectorInterface"); + Append(interface_name, cn); + Append(interface_name, go_name); + if (overname != NULL) { + Append(interface_name, overname); + } + + String *callback_name = Copy(director_struct_name); + Append(callback_name, "_callback_"); + Append(callback_name, name); + Replace(callback_name, "_swig", "Swig", DOH_REPLACE_FIRST); + if (overname != NULL) { + Append(callback_name, overname); + } + + String *callback_wname = Swig_name_wrapper(callback_name); + + String *upcall_name = Copy(director_struct_name); + Append(upcall_name, "_upcall_"); + Append(upcall_name, go_name); + + String *upcall_wname = Swig_name_wrapper(upcall_name); + + String *go_with_over_name = Copy(go_name); + if (overname != NULL) { + Append(go_with_over_name, overname); + } + + Wrapper *f = NewWrapper(); + + Parm *p = parms; + for (int i = 0; i < parm_count; ++i) { + p = getParm(p); + Swig_cparm_name(p, i); + if (Getattr(p, "name") == NULL) { + String *pn = NewString(""); + Printf(pn, "arg%d", i); + Setattr(p, "name", pn); + } + p = nextParm(p); + } + + Swig_typemap_attach_parms("directorin", parms, f); + + if (!is_ignored) { + // We use an interface to see if this method is defined in Go. + Printv(f_go_wrappers, "type ", interface_name, " interface {\n", NULL); + Printv(f_go_wrappers, "\t", go_with_over_name, "(", NULL); + + p = parms; + for (int i = 0; i < parm_count; ++i) { + p = getParm(p); + if (i > 0) { + Printv(f_go_wrappers, ", ", NULL); + } + String *tm = goType(p, Getattr(p, "type")); + Printv(f_go_wrappers, tm, NULL); + Delete(tm); + p = nextParm(p); + } + + Printv(f_go_wrappers, ")", NULL); + + if (SwigType_type(result) != T_VOID) { + String *tm = goType(n, result); + Printv(f_go_wrappers, " ", tm, NULL); + Delete(tm); + } + + Printv(f_go_wrappers, "\n", NULL); + Printv(f_go_wrappers, "}\n\n", NULL); + + // Declare the upcall function, which calls the method on the + // parent class. + + if (overname != NULL) { + Append(upcall_wname, overname); + } + + String *upcall_gc_name = buildGoWrapperName(upcall_name, overname); + + Printv(f_go_wrappers, "func ", upcall_gc_name, "(", + go_type_name, NULL); + + p = parms; + for (int i = 0; i < parm_count; ++i) { + p = getParm(p); + String *tm = goWrapperType(p, Getattr(p, "type"), false); + Printv(f_go_wrappers, ", ", tm, NULL); + Delete(tm); + p = nextParm(p); + } + + Printv(f_go_wrappers, ")", NULL); + + if (SwigType_type(result) != T_VOID) { + String *tm = goWrapperType(n, result, true); + Printv(f_go_wrappers, " ", tm, NULL); + Delete(tm); + } + + if (gccgo_flag) { + Printv(f_go_wrappers, " __asm__(\"", go_prefix, "_", upcall_wname, + "\")", NULL); + } + + Printv(f_go_wrappers, "\n", NULL); + + // Define the method on the director class in Go. + + Printv(f_go_wrappers, "func (swig_p *", director_struct_name, ") ", + go_with_over_name, "(", NULL); + + p = parms; + for (int i = 0; i < parm_count; ++i) { + p = getParm(p); + if (i > 0) { + Printv(f_go_wrappers, ", ", NULL); + } + Printv(f_go_wrappers, Getattr(p, "lname"), " ", NULL); + String *tm = goType(p, Getattr(p, "type")); + Printv(f_go_wrappers, tm, NULL); + Delete(tm); + p = nextParm(p); + } + + Printv(f_go_wrappers, ")", NULL); + + if (SwigType_type(result) != T_VOID) { + String *tm = goType(n, result); + Printv(f_go_wrappers, " ", tm, NULL); + Delete(tm); + } + + Printv(f_go_wrappers, " {\n", NULL); + + Printv(f_go_wrappers, "\tif swig_g, swig_ok := swig_p.v.(", + interface_name, "); swig_ok {\n", NULL); + Printv(f_go_wrappers, "\t\t", NULL); + if (SwigType_type(result) != T_VOID) { + Printv(f_go_wrappers, "return ", NULL); + } + Printv(f_go_wrappers, "swig_g.", go_with_over_name, "(", NULL); + + p = parms; + for (int i = 0; i < parm_count; ++i) { + p = getParm(p); + if (i > 0) { + Printv(f_go_wrappers, ", ", NULL); + } + Printv(f_go_wrappers, Getattr(p, "lname"), NULL); + p = nextParm(p); + } + + Printv(f_go_wrappers, ")\n", NULL); + if (SwigType_type(result) == T_VOID) { + Printv(f_go_wrappers, "\t\treturn\n", NULL); + } + Printv(f_go_wrappers, "\t}\n", NULL); + Printv(f_go_wrappers, "\t", NULL); + if (SwigType_type(result) != T_VOID) { + Printv(f_go_wrappers, "return ", NULL); + } + Printv(f_go_wrappers, upcall_gc_name, "(swig_p.", go_type_name, NULL); + + p = parms; + for (int i = 0; i < parm_count; ++i) { + p = getParm(p); + SwigType *pt = Getattr(p, "type"); + Printv(f_go_wrappers, ", ", Getattr(p, "lname"), NULL); + if (goTypeIsInterface(p, pt)) { + Printv(f_go_wrappers, ".Swigcptr()", NULL); + } + p = nextParm(p); + } + + Printv(f_go_wrappers, ")\n", NULL); + Printv(f_go_wrappers, "}\n\n", NULL); + + // Define a method in the C++ director class that the C++ upcall + // function can call. This permits an upcall to a protected + // method. + + String *upcall_method_name = NewString("_swig_upcall_"); + Append(upcall_method_name, name); + if (overname != NULL) { + Append(upcall_method_name, overname); + } + String *upcall_decl = Swig_method_decl(Getattr(n, "type"), + Getattr(n, "decl"), + upcall_method_name, parms, 0, 0); + Printv(f_c_directors_h, " ", upcall_decl, " {\n", NULL); + Delete(upcall_decl); + + Printv(f_c_directors_h, " ", NULL); + if (SwigType_type(result) != T_VOID) { + Printv(f_c_directors_h, "return ", NULL); + } + Printv(f_c_directors_h, Getattr(parent, "classtype"), "::", + Getattr(n, "name"), "(", NULL); + + p = parms; + for (int i = 0; i < parm_count; ++i) { + p = getParm(p); + if (i > 0) { + Printv(f_c_directors_h, ", ", NULL); + } + String *pn = Getattr(p, "name"); + assert(pn != NULL); + Printv(f_c_directors_h, pn, NULL); + p = nextParm(p); + } + + Printv(f_c_directors_h, ");\n", NULL); + Printv(f_c_directors_h, " }\n", NULL); + + + // Define the C++ function that the Go function calls. + + SwigType *first_type = NULL; + Parm *first_parm = parms; + if (!is_static) { + first_type = NewString("SwigDirector_"); + Append(first_type, class_name); + SwigType_add_pointer(first_type); + first_parm = NewParm(first_type, "p", n); + set_nextSibling(first_parm, parms); + } + + Swig_save("classDirectorMethod", n, "wrap:name", "wrap:action", NULL); + + Setattr(n, "wrap:name", upcall_wname); + + String *action = NewString(""); + if (SwigType_type(result) != T_VOID) { + Printv(action, "result = (", SwigType_lstr(result, 0), ")", NULL); + if (SwigType_isreference(result)) { + Printv(action, "&", NULL); + } + } + Printv(action, Swig_cparm_name(NULL, 0), "->", upcall_method_name, "(", + NULL); + + p = parms; + for (int i = 0; i < parm_count; ++i) { + p = getParm(p); + String *pname = Swig_cparm_name(NULL, i + 1); + if (i > 0) { + Printv(action, ", ", NULL); + } + // A parameter whose type is a reference is converted into a + // pointer type by gcCTypeForGoValue. We are calling a + // function which expects a reference so we need to convert + // back. + if (SwigType_isreference(Getattr(p, "type"))) { + Printv(action, "*", NULL); + } + Printv(action, pname, NULL); + Delete(pname); + p = nextParm(p); + } + Printv(action, ");", NULL); + Setattr(n, "wrap:action", action); + + if (!gccgo_flag) { + // Write the upcall wrapper function. This is compiled by gc + // and calls the C++ function. + int r = gcFunctionWrapper(n, upcall_name, upcall_name, + overname, upcall_wname, first_parm, result, + is_static, true); + if (r != SWIG_OK) { + return r; + } + r = gccFunctionWrapper(n, NULL, upcall_wname, first_parm, result); + if (r != SWIG_OK) { + return r; + } + } else { + int r = gccgoFunctionWrapper(n, NULL, upcall_wname, first_parm, result); + if (r != SWIG_OK) { + return r; + } + } + + if (first_type != NULL) { + Delete(first_type); + } + if (first_parm != parms) { + Delete(first_parm); + } + + Swig_restore(n); + + // Define a function which uses the Go director type that other + // methods in the Go type can call to get parent methods. + + Printv(f_go_wrappers, "func Director", cn, go_with_over_name, "(p ", cn, + NULL); + + p = parms; + for (int i = 0; i < parm_count; ++i) { + p = getParm(p); + Printv(f_go_wrappers, ", ", Getattr(p, "lname"), " ", NULL); + String *tm = goType(p, Getattr(p, "type")); + Printv(f_go_wrappers, tm, NULL); + Delete(tm); + p = nextParm(p); + } + + Printv(f_go_wrappers, ")", NULL); + + if (SwigType_type(result) != T_VOID) { + String *tm = goType(n, result); + Printv(f_go_wrappers, " ", tm, NULL); + Delete(tm); + } + + Printv(f_go_wrappers, " {\n", NULL); + + Printv(f_go_wrappers, "\t", NULL); + if (SwigType_type(result) != T_VOID) { + Printv(f_go_wrappers, "return ", NULL); + } + Printv(f_go_wrappers, upcall_gc_name, "(p.(*", + director_struct_name, ").", go_type_name, NULL); + + p = parms; + for (int i = 0; i < parm_count; ++i) { + p = getParm(p); + SwigType *pt = Getattr(p, "type"); + Printv(f_go_wrappers, ", ", Getattr(p, "lname"), NULL); + if (goTypeIsInterface(p, pt)) { + Printv(f_go_wrappers, ".Swigcptr()", NULL); + } + p = nextParm(p); + } + + Printv(f_go_wrappers, ")\n", NULL); + Printv(f_go_wrappers, "}\n\n", NULL); + + // The Go function which invokes the method. This is called + // from by the C++ method on the director class. + + Printv(f_go_wrappers, "func ", callback_name, "(p *", + director_struct_name, NULL); + + p = parms; + for (int i = 0; i < parm_count; ++i) { + p = getParm(p); + String *tm = goWrapperType(p, Getattr(p, "type"), false); + Printv(f_go_wrappers, ", ", Getattr(p, "lname"), " ", tm, NULL); + Delete(tm); + p = nextParm(p); + } + + Printv(f_go_wrappers, ") ", NULL); + String *result_wrapper = NULL; + if (SwigType_type(result) != T_VOID) { + result_wrapper = goWrapperType(n, result, true); + Printv(f_go_wrappers, "(swig_result ", result_wrapper, ") ", NULL); + } + Printv(f_go_wrappers, "{\n", NULL); + Printv(f_go_wrappers, "\t", NULL); + + if (is_ignored) { + Printv(f_go_wrappers, "return\n", NULL); + } else { + bool result_is_interface = false; + if (SwigType_type(result) != T_VOID) { + Printv(f_go_wrappers, "return ", NULL); + result_is_interface = goTypeIsInterface(NULL, result); + if (result_is_interface) { + Printv(f_go_wrappers, result_wrapper, "(", NULL); + } + } + Printv(f_go_wrappers, "p.", go_with_over_name, "(", NULL); + + p = parms; + for (int i = 0; i < parm_count; ++i) { + p = getParm(p); + if (i > 0) { + Printv(f_go_wrappers, ", ", NULL); + } + SwigType *pt = Getattr(p, "type"); + + // If the Go representation is an interface type class, then + // we are receiving a uintptr, and must convert to the + // interface. + bool is_interface = goTypeIsInterface(p, pt); + if (is_interface) { + // Passing is_result as true to goWrapperType gives us the + // name of the Go type we need to convert to an interface. + String *wt = goWrapperType(p, pt, true); + Printv(f_go_wrappers, wt, "(", NULL); + Delete(wt); + } + + Printv(f_go_wrappers, Getattr(p, "lname"), NULL); + + if (is_interface) { + Printv(f_go_wrappers, ")", NULL); + } + + p = nextParm(p); + } + + Printv(f_go_wrappers, ")", NULL); + + if (result_is_interface) { + Printv(f_go_wrappers, ".Swigcptr())", NULL); + } + + Printv(f_go_wrappers, "\n", NULL); + + Delete(upcall_gc_name); + } + + Printv(f_go_wrappers, "}\n\n", NULL); + + if (result_wrapper != NULL) { + Delete(result_wrapper); + } + + // Build the C++ functions. + + Delete(upcall_wname); + + if (!gccgo_flag) { + Printv(f_c_directors, "extern \"C\" void ", callback_wname, + "(void*, int);\n", NULL); + } else { + Printv(f_c_directors, "extern \"C\" ", NULL); + + String *fnname = NewString(""); + Printv(fnname, callback_wname, "(void*", NULL); + + p = parms; + while (p != NULL) { + while (checkAttribute(p, "tmap:directorin:numinputs", "0")) { + p = Getattr(p, "tmap:directorin:next"); + } + String *cg = gccgoCTypeForGoValue(p, Getattr(p, "type"), + Getattr(p, "lname")); + Printv(fnname, ", ", cg, NULL); + Delete(cg); + p = Getattr(p, "tmap:directorin:next"); + } + + Printv(fnname, ")", NULL); + + if (SwigType_type(result) == T_VOID) { + Printv(f_c_directors, "void ", fnname, NULL); + } else { + String *tm = gccgoCTypeForGoValue(n, result, fnname); + Printv(f_c_directors, tm, NULL); + Delete(tm); + } + + Delete(fnname); + + Printv(f_c_directors, " __asm__(\"", go_prefix, ".", package, ".", + callback_name, "\");\n", NULL); + } + + Delete(upcall_method_name); + Delete(go_with_over_name); + } + + if (!is_ignored || is_pure_virtual) { + // Declare the method for the director class. + + SwigType *rtype = (Getattr(n, "conversion_operator") + ? NULL + : Getattr(n, "type")); + String *decl = Swig_method_decl(rtype, Getattr(n, "decl"), + Getattr(n, "name"), parms, + 0, 0); + Printv(f_c_directors_h, " virtual ", decl, NULL); + Delete(decl); + + String *qname = NewString(""); + Printv(qname, "SwigDirector_", class_name, "::", Getattr(n, "name"), + NULL); + decl = Swig_method_decl(rtype, Getattr(n, "decl"), qname, parms, 0, 0); + Printv(f->def, decl, NULL); + Delete(decl); + Delete(qname); + + String *throws = buildThrow(n); + if (throws != NULL) { + Printv(f_c_directors_h, " ", throws, NULL); + Printv(f->def, " ", throws, NULL); + Delete(throws); + } + + Printv(f_c_directors_h, ";\n", NULL); + + Printv(f->def, " {\n", NULL); + + if (SwigType_type(result) != T_VOID) { + Wrapper_add_local(f, "c_result", + SwigType_lstr(Getattr(n, "returntype"), "c_result")); + } + + if (!is_ignored) { + if (!gccgo_flag) { + Printv(f->code, " struct {\n", NULL); + Printv(f->code, " void *go_val;\n", NULL); + + p = parms; + while (p != NULL) { + while (checkAttribute(p, "tmap:directorin:numinputs", "0")) { + p = Getattr(p, "tmap:directorin:next"); + } + String *ln = Getattr(p, "lname"); + String *cg = gcCTypeForGoValue(p, Getattr(p, "type"), ln); + Printv(f->code, " ", cg, ";\n", NULL); + Delete(cg); + p = Getattr(p, "tmap:directorin:next"); + } + if (SwigType_type(result) != T_VOID) { + Printv(f->code, " int : 0;\n", NULL); + String *rname = NewString("result"); + String *cg = gcCTypeForGoValue(n, result, rname); + Printv(f->code, " ", cg, ";\n", NULL); + Delete(cg); + Delete(rname); + } + + Printv(f->code, " } swig_a;\n", NULL); + Printv(f->code, " swig_a.go_val = go_val;\n", NULL); + + p = parms; + while (p != NULL) { + while (checkAttribute(p, "tmap:directorin:numinputs", "0")) { + p = Getattr(p, "tmap:directorin:next"); + } + String *tm = Getattr(p, "tmap:directorin"); + if (tm == NULL) { + Swig_warning(WARN_TYPEMAP_DIRECTORIN_UNDEF, input_file, + line_number, + "Unable to use type %s as director method argument\n", + SwigType_str(Getattr(p, "type"), 0)); + } else { + String *ln = Getattr(p, "lname"); + String *input = NewString(""); + Printv(input, "swig_a.", ln, NULL); + Replaceall(tm, "$input", input); + Replaceall(tm, "$owner", "0"); + Delete(input); + Printv(f->code, "\t", tm, "\n", NULL); + } + p = Getattr(p, "tmap:directorin:next"); + } + + Printv(f->code, " crosscall2(", callback_wname, + ", &swig_a, (int) sizeof swig_a);\n", NULL); + + if (SwigType_type(result) != T_VOID) { + String *rname = NewString("c_result"); + Parm *rp = NewParm(Getattr(n, "returntype"), rname, n); + String *tm = Swig_typemap_lookup("directorout", rp, rname, NULL); + if (tm == NULL) { + Swig_warning(WARN_TYPEMAP_DIRECTOROUT_UNDEF, input_file, line_number, + "Unable to use type %s as director method result\n", + SwigType_str(result, 0)); + } else { + Replaceall(tm, "$input", "swig_a.result"); + Replaceall(tm, "$result", "c_result"); + Printv(f->code, " ", tm, "\n", NULL); + String *retstr = SwigType_rcaststr(Getattr(n, "returntype"), + "c_result"); + Printv(f->code, " return ", retstr, ";\n", NULL); + Delete(retstr); + Delete(tm); + } + Delete(rp); + Delete(rname); + } + + // The C wrapper code which calls the Go function. + Printv(f_gc_wrappers, "#pragma dynexport ", callback_wname, " ", + callback_wname, "\n", NULL); + Printv(f_gc_wrappers, "extern void \xc2\xb7", callback_name, "();\n", + NULL); + Printv(f_gc_wrappers, "void\n", NULL); + Printv(f_gc_wrappers, callback_wname, "(void *a, int32 n)\n", NULL); + Printv(f_gc_wrappers, "{\n", NULL); + Printv(f_gc_wrappers, "\tcgocallback(\xc2\xb7", callback_name, + ", a, n);\n", NULL); + Printv(f_gc_wrappers, "}\n\n", NULL); + } else { + if (SwigType_type(result) != T_VOID) { + String *r = NewString("result"); + String *tm = gccgoCTypeForGoValue(n, result, r); + Wrapper_add_local(f, r, tm); + Delete(tm); + Delete(r); + } + + String *args = NewString(""); + + p = parms; + while (p != NULL) { + while (checkAttribute(p, "tmap:directorin:numinputs", "0")) { + p = Getattr(p, "tmap:directorin:next"); + } + + String *pn = NewString("g"); + Append(pn, Getattr(p, "lname")); + Setattr(p, "emit:input", pn); + + String *tm = gccgoCTypeForGoValue(n, Getattr(p, "type"), pn); + Wrapper_add_local(f, pn, tm); + Delete(tm); + + tm = Getattr(p, "tmap:directorin"); + if (tm == NULL) { + Swig_warning(WARN_TYPEMAP_DIRECTORIN_UNDEF, input_file, + line_number, + "Unable to use type %s as director method argument\n", + SwigType_str(Getattr(p, "type"), 0)); + } else { + Replaceall(tm, "$input", pn); + Replaceall(tm, "$owner", 0); + Printv(f->code, " ", tm, "\n", NULL); + + Printv(args, ", ", pn, NULL); + } + + p = Getattr(p, "tmap:directorin:next"); + } + + Printv(f->code, " ", NULL); + if (SwigType_type(result) != T_VOID) { + Printv(f->code, "result = ", NULL); + } + Printv(f->code, callback_wname, "(go_val", args, ");\n", NULL); + + if (SwigType_type(result) != T_VOID) { + String *rname = NewString("c_result"); + Parm *rp = NewParm(Getattr(n, "returntype"), rname, n); + String *tm = Swig_typemap_lookup("directorout", rp, rname, NULL); + if (tm == NULL) { + Swig_warning(WARN_TYPEMAP_DIRECTOROUT_UNDEF, input_file, line_number, + "Unable to use type %s as director method result\n", + SwigType_str(result, 0)); + } else { + Replaceall(tm, "$input", "result"); + Replaceall(tm, "$result", "c_result"); + Printv(f->code, " ", tm, "\n", NULL); + String *retstr = SwigType_rcaststr(Getattr(n, "returntype"), + "c_result"); + Printv(f->code, " return ", retstr, ";\n", NULL); + Delete(retstr); + Delete(tm); + } + Delete(rp); + Delete(rname); + } + } + } else { + assert(is_pure_virtual); + Printv(f->code, " _swig_gopanic(\"call to pure virtual function ", + Getattr(parent, "sym:name"), name, "\");\n"); + if (SwigType_type(result) != T_VOID) { + String *retstr = SwigType_rcaststr(Getattr(n, "returntype"), + "c_result"); + Printv(f->code, " return ", retstr, ";\n", NULL); + Delete(retstr); + } + } + + Printv(f->code, "}", NULL); + + Wrapper_print(f, f_c_directors); + + DelWrapper(f); + } + + Delete(cn); + Delete(go_type_name); + Delete(director_struct_name); + Delete(interface_name); + Delete(upcall_name); + Delete(callback_wname); + Delete(go_name); + + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * classDirectorEnd + * + * Complete support for a director class. + * ------------------------------------------------------------ */ + + int classDirectorEnd(Node *n) { + (void) n; + + Printv(f_c_directors_h, " private:\n", NULL); + Printv(f_c_directors_h, " void *go_val;\n", NULL); + Printv(f_c_directors_h, "};\n\n", NULL); + + class_name = NULL; + class_node = NULL; + + Delete(class_receiver); + class_receiver = NULL; + + Delete(class_methods); + class_methods = NULL; + + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * classDirectorDisown + * + * I think Go does not require a disown method. + * ------------------------------------------------------------ */ + + int classDirectorDisown(Node *n) { + (void) n; + return SWIG_OK; + } + + /*---------------------------------------------------------------------- + * buildThrow() + * + * Build and return a throw clause if needed. + *--------------------------------------------------------------------*/ + + String *buildThrow(Node *n) { + ParmList *throw_parm_list = Getattr(n, "throws"); + if (throw_parm_list == NULL && Getattr(n, "throw") == NULL) + return NULL; + String *ret = NewString("throw("); + if (throw_parm_list != NULL) { + Swig_typemap_attach_parms("throws", throw_parm_list, NULL); + } + bool first = true; + for (Parm *p = throw_parm_list; p != NULL; p = nextSibling(p)) { + if (Getattr(p, "tmap:throws") != NULL) { + if (first) { + first = false; + } else { + Printv(ret, ", ", NULL); + } + String *s = SwigType_str(Getattr(p, "type"), 0); + Printv(ret, s, NULL); + Delete(s); + } + } + Printv(ret, ")", NULL); + return ret; + } + + /*---------------------------------------------------------------------- + * extraDirectorProtectedCPPMethodsRequired() + * + * We don't need to check upcall when calling methods. + *--------------------------------------------------------------------*/ + + bool extraDirectorProtectedCPPMethodsRequired() const { + return false; + } + + /*---------------------------------------------------------------------- + * makeDispatchFunction + * + * Make a dispatch function for an overloaded C++ function. The + * receiver parameter is the receiver for a method, unless is_upcall + * is true. If is_upcall is true, then the receiver parameter is + * the type of the first argument to the function. + *--------------------------------------------------------------------*/ + + int makeDispatchFunction(Node *n, String *go_name, String *receiver, + bool is_static, SwigType *director_struct, + bool is_upcall) { + bool is_director = director_struct != NULL; + + String *nodetype = Getattr(n, "nodeType"); + bool is_constructor = Cmp(nodetype, "constructor") == 0; + bool is_destructor = Cmp(nodetype, "destructor") == 0; + + bool can_use_receiver = (!is_constructor + && !is_destructor + && !is_upcall); + + bool use_receiver = (!is_static + && can_use_receiver); + + bool add_to_interface = (interfaces != NULL + && !is_constructor + && !is_destructor + && !is_static + && !is_upcall); + + List *dispatch = Swig_overload_rank(n, false); + int nfunc = Len(dispatch); + + SwigType *all_result; + bool mismatch; + if (is_constructor) { + assert(!is_upcall); + if (!is_director) { + all_result = Getattr(class_node, "classtypeobj"); + } else { + all_result = director_struct; + } + mismatch = false; + } else { + all_result = NULL; + mismatch = false; + bool any_void = false; + for (int i = 0; i < nfunc; ++i) { + Node *ni = Getitem(dispatch, i); + SwigType *result = Getattr(ni, "go:type"); + assert(result != NULL); + + if (SwigType_type(result) == T_VOID) { + if (all_result != NULL) { + mismatch = true; + } + any_void = true; + } else { + if (any_void) { + mismatch = true; + } else if (all_result == NULL) { + all_result = Copy(result); + } else if (Cmp(result, all_result) != 0) { + mismatch = true; + } + } + } + if (mismatch) { + if (all_result != NULL) { + Delete(all_result); + } + all_result = NULL; + } else if (all_result != NULL) { + ; + } else { + all_result = NewString("void"); + } + } + + Printv(f_go_wrappers, "func ", NULL); + + if (receiver != NULL && use_receiver) { + Printv(f_go_wrappers, "(p ", receiver, ") ", NULL); + } + + Printv(f_go_wrappers, go_name, "(", NULL); + if (is_director && is_constructor) { + Printv(f_go_wrappers, "abi interface{}, ", NULL); + assert(!add_to_interface); + } + if (is_upcall) { + Printv(f_go_wrappers, "p *", receiver, ", ", NULL); + assert(!add_to_interface); + } + Printv(f_go_wrappers, "a ...interface{})", NULL); + + if (add_to_interface) { + Printv(interfaces, "\t", go_name, "(a ...interface{})", NULL); + } + + if (mismatch) { + Printv(f_go_wrappers, " interface{}", NULL); + if (add_to_interface) { + Printv(interfaces, " interface{}", NULL); + } + } else if (all_result != NULL && SwigType_type(all_result) != T_VOID) { + if (is_director && is_constructor) { + Printv(f_go_wrappers, " ", receiver, NULL); + if (add_to_interface) { + Printv(interfaces, " ", receiver, NULL); + } + } else { + String *tm = goType(n, all_result); + Printv(f_go_wrappers, " ", tm, NULL); + if (add_to_interface) { + Printv(interfaces, " ", tm, NULL); + } + Delete(tm); + } + } + Printv(f_go_wrappers, " {\n", NULL); + if (add_to_interface) { + Printv(interfaces, "\n", NULL); + } + + Printv(f_go_wrappers, "\targc := len(a)\n", NULL); + + for (int i = 0; i < nfunc; ++i) { + int fn = 0; + Node *ni = Getitem(dispatch, i); + Parm *pi = Getattr(ni, "wrap:parms"); + + // If we are using a receiver, we want to ignore a leading self + // parameter. Because of the way this is called, there may or + // may not be a self parameter at this point. + if (use_receiver && pi != NULL && Getattr(pi, "self") != NULL) { + pi = getParm(pi); + if (pi != NULL) { + pi = nextParm(pi); + } + } + + int num_required = emit_num_required(pi); + int num_arguments = emit_num_arguments(pi); + bool varargs = emit_isvarargs(pi); + + if (varargs) { + Printf(f_go_wrappers, "\tif argc >= %d {\n", num_required); + } else { + if (num_required == num_arguments) { + Printf(f_go_wrappers, "\tif argc == %d {\n", num_required); + } else { + Printf(f_go_wrappers, "\tif argc >= %d && argc <= %d {\n", + num_required, num_arguments); + } + } + + // Build list of collisions with the same number of arguments. + List *coll = NewList(); + for (int k = i + 1; k < nfunc; ++k) { + Node *nk = Getitem(dispatch, k); + Parm *pk = Getattr(nk, "wrap:parms"); + if (use_receiver && pk != NULL && Getattr(pk, "self") != NULL) { + pk = getParm(pk); + if (pk != NULL) { + pk = nextParm(pk); + } + } + int nrk = emit_num_required(pk); + int nak = emit_num_arguments(pk); + if ((nrk >= num_required && nrk <= num_arguments) + || (nak >= num_required && nak <= num_arguments) + || (nrk <= num_required && nak >= num_arguments)) { + Append(coll, nk); + } + } + + int num_braces = 0; + if (Len(coll) > 0 && num_arguments > 0) { + int j = 0; + Parm *pj = pi; + while (pj != NULL) { + pj = getParm(pj); + if (pj == NULL) { + break; + } + + // If all the wrappers have the same type in this position, + // we can omit the check. + SwigType *tm = goWrapperType(pj, Getattr(pj, "type"), true); + bool emitcheck = false; + for (int k = 0; k < Len(coll) && !emitcheck; ++k) { + Node *nk = Getitem(coll, k); + Parm *pk = Getattr(nk, "wrap:parms"); + if (use_receiver && pk != NULL && Getattr(pk, "self") != NULL) { + pk = getParm(pk); + if (pk != NULL) { + pk = nextParm(pk); + } + } + int nak = emit_num_arguments(pk); + if (nak <= j) + continue; + int l = 0; + Parm *pl = pk; + while (pl != NULL && l <= j) { + pl = getParm(pl); + if (pl == NULL) { + break; + } + if (l == j) { + SwigType *tml = goWrapperType(pl, Getattr(pl, "type"), true); + if (Cmp(tm, tml) != 0) { + emitcheck = true; + } + Delete(tml); + } + pl = nextParm(pl); + ++l; + } + } + + if (emitcheck) { + if (j >= num_required) { + Printf(f_go_wrappers, "\t\tif argc > %d {\n", j); + ++num_braces; + } + + fn = i + 1; + Printf(f_go_wrappers, "\t\tif _, ok := a[%d].(%s); !ok {\n", j, tm); + Printf(f_go_wrappers, "\t\t\tgoto check_%d\n", fn); + Printv(f_go_wrappers, "\t\t}\n", NULL); + } + + Delete(tm); + + pj = nextParm(pj); + + ++j; + } + } + + for (; num_braces > 0; --num_braces) { + Printv(f_go_wrappers, "\t\t}\n", NULL); + } + + // We may need to generate multiple calls if there are variable + // argument lists involved. Build the start of the call. + + String *start = NewString(""); + + SwigType *result = Getattr(ni, "go:type"); + + if (is_constructor) { + result = all_result; + } else if (is_destructor) { + result = NULL; + } + + if (result != NULL + && SwigType_type(result) != T_VOID + && (all_result == NULL + || SwigType_type(all_result) != T_VOID)) { + Printv(start, "return ", NULL); + } + + bool advance_parm = false; + + if (receiver != NULL && use_receiver) { + Printv(start, "p.", go_name, NULL); + } else if (can_use_receiver + && !isStatic(ni) + && pi != NULL + && Getattr(pi, "self") != NULL) { + // This is an overload of a static function and a non-static + // function. + assert(num_required > 0); + SwigType *tm = goWrapperType(pi, Getattr(pi, "type"), true); + String *nm = buildGoName(Getattr(ni, "sym:name"), false, + isFriend(ni)); + Printv(start, "a[0].(", tm, ").", nm, NULL); + Delete(nm); + Delete(tm); + advance_parm = true; + } else { + Printv(start, go_name, NULL); + } + + Printv(start, Getattr(ni, "sym:overname"), "(", NULL); + + bool need_comma = false; + + if (is_director && is_constructor) { + Printv(start, "abi", NULL); + need_comma = true; + } + if (is_upcall) { + Printv(start, "p", NULL); + need_comma = true; + } + Parm *p = pi; + int pn = 0; + if (advance_parm) { + p = getParm(p); + if (p != NULL) { + p = nextParm(p); + } + ++pn; + } + while (pn < num_required) { + p = getParm(p); + + if (need_comma) { + Printv(start, ", ", NULL); + } + + SwigType *tm = goType(p, Getattr(p, "type")); + Printf(start, "a[%d].(%s)", pn, tm); + Delete(tm); + + need_comma = true; + ++pn; + p = nextParm(p); + } + + String *end = NULL; + if (result == NULL + || SwigType_type(result) == T_VOID + || (all_result != NULL && SwigType_type(all_result) == T_VOID)) { + end = NewString(""); + Printv(end, "return", NULL); + if (all_result == NULL || SwigType_type(all_result) != T_VOID) { + Printv(end, " 0", NULL); + } + } + + if (num_required == num_arguments) { + Printv(f_go_wrappers, "\t\t", start, ")\n", NULL); + if (end != NULL) { + Printv(f_go_wrappers, "\t\t", end, "\n", NULL); + } + } else { + Printv(f_go_wrappers, "\t\tswitch argc {\n", NULL); + for (int j = num_required; j <= num_arguments; ++j) { + Printf(f_go_wrappers, "\t\tcase %d:\n", j); + Printv(f_go_wrappers, "\t\t\t", start, NULL); + bool nc = need_comma; + for (int k = num_required; k < j; ++k) { + if (nc) { + Printv(f_go_wrappers, ", ", NULL); + } + Printf(f_go_wrappers, "a[%d]", k); + nc = true; + } + Printv(f_go_wrappers, ")\n", NULL); + if (end != NULL) { + Printv(f_go_wrappers, "\t\t\t", end, "\n", NULL); + } + } + Printv(f_go_wrappers, "\t\t}\n", NULL); + } + + Printv(f_go_wrappers, "\t}\n", NULL); + + if (fn != 0) { + Printf(f_go_wrappers, "check_%d:\n", fn); + } + + Delete(coll); + } + + Printv(f_go_wrappers, "fail:\n", NULL); + Printv(f_go_wrappers, + "\tpanic(\"No match for overloaded function call\")\n", NULL); + Printv(f_go_wrappers, "}\n\n", NULL); + + if (all_result != NULL) { + Delete(all_result); + } + Delete(dispatch); + + return SWIG_OK; + } + + /* ---------------------------------------------------------------------- + * exportedName() + * + * Given a C/C++ name, return a name in Go which will be exported. + * If the first character is an upper case letter, this returns a + * copy of its argment. If the first character is a lower case + * letter, this forces it to upper case. Otherwise, this prepends + * 'X'. + * ---------------------------------------------------------------------- */ + + String *exportedName(String *name) { + String *copy = Copy(name); + char c = *Char(copy); + if (islower(c)) { + char l[2]; + char u[2]; + l[0] = c; + l[1] = '\0'; + u[0] = toupper(c); + u[1] = '\0'; + Replace(copy, l, u, DOH_REPLACE_FIRST); + } else if (!isalpha(c)) { + char l[2]; + char u[3]; + l[0] = c; + l[1] = '\0'; + u[0] = 'X'; + u[1] = c; + u[2] = '\0'; + Replace(copy, l, u, DOH_REPLACE_FIRST); + } + String *ret = Swig_name_mangle(copy); + Delete(copy); + return ret; + } + + /* ---------------------------------------------------------------------- + * removeClassname() + * + * If the name starts with the current class name, followed by an + * underscore, remove it. If there is no current class name, this + * simply returns a copy of the name. This undoes Swig's way of + * recording the class name in a member name. + * ---------------------------------------------------------------------- */ + + String *removeClassname(String *name) { + String *copy = Copy(name); + if (class_name != NULL) { + char *p = Char(name); + if (Strncmp(name, class_name, Len(class_name)) == 0 + && p[Len(class_name)] == '_') { + Replace(copy, class_name, "", DOH_REPLACE_FIRST); + Replace(copy, "_", "", DOH_REPLACE_FIRST); + } + } + return copy; + } + + /* ---------------------------------------------------------------------- + * buildGoName() + * + * Build the name to use for an ordinary function, variable, or + * whatever in Go. The name argument is something like the sym:name + * attribute of the node. If is_static is false, this could be a + * method, and the returned name will be the name of the + * method--i.e., it will not include the class name. + * ---------------------------------------------------------------------- */ + + String *buildGoName(String *name, bool is_static, bool is_friend) { + String *nw = NewString(""); + if (is_static && !is_friend && class_name != NULL) { + String *c1 = exportedName(class_name); + Append(nw, c1); + Delete(c1); + } + String *c2 = removeClassname(name); + String *c3 = exportedName(c2); + Append(nw, c3); + Delete(c2); + Delete(c3); + String *ret = Swig_name_mangle(nw); + Delete(nw); + return ret; + } + + /* ---------------------------------------------------------------------- + * buildGoWrapperName() + * + * Build the name to use for a Go wrapper function. This is a + * function called by the real Go function in order to convert C++ + * classes from interfaces to pointers, and other such conversions + * between the Go type and the C++ type. + * ---------------------------------------------------------------------- */ + + String *buildGoWrapperName(String *name, String *overname) { + String *s1 = NewString("_swig_wrap_"); + Append(s1, name); + String *s2 = Swig_name_mangle(s1); + Delete(s1); + if (overname != NULL) { + Append(s2, overname); + } + return s2; + } + + /* ---------------------------------------------------------------------- + * goType() + * + * Given a SWIG type, return a string for the type in Go. + * ---------------------------------------------------------------------- */ + + String *goType(Node *n, SwigType *type) { + return goTypeWithInfo(n, type, NULL); + } + + /* ---------------------------------------------------------------------- + * goTypeWithInfo() + * + * Like goType, but return some more information. + * + * If the p_is_interface parameter is not NULL, this sets + * *p_is_interface to indicate whether this type is going to be + * represented by a Go interface type. These are cases where the Go + * code needs to make some adjustments when passing values back and + * forth with C/C++. + * ---------------------------------------------------------------------- */ + + String *goTypeWithInfo(Node *n, SwigType *type, bool *p_is_interface) { + if (p_is_interface != NULL) { + *p_is_interface = false; + } + + String *ret; + if (n != NULL && Cmp(type, Getattr(n, "type")) == 0) { + ret = NULL; + if (Strcmp(Getattr(n, "nodeType"), "parm") == 0) { + ret = Getattr(n, "tmap:go"); + } + if (ret == NULL) { + ret = Swig_typemap_lookup("go", n, "", NULL); + } + } else { + Parm *p = NewParmWithoutFileLineInfo(type, "goType"); + ret = Swig_typemap_lookup("go", p, "", NULL); + Delete(p); + } + + if (Strstr(ret, "$gotypename") != NULL) { + ret = NULL; + } + + if (ret != NULL) { + return Copy(ret); + } + + SwigType *t = SwigType_typedef_resolve_all(type); + + Node *e = Language::enumLookup(t); + if (e != NULL) { + ret = goEnumName(e); + } else if (Strcmp(t, "enum ") == 0) { + ret = NewString("int"); + } else if (SwigType_isfunctionpointer(type) || SwigType_isfunction(type)) { + ret = NewString("_swig_fnptr"); + } else if (SwigType_ismemberpointer(type)) { + ret = NewString("_swig_memberptr"); + } else if (SwigType_issimple(t)) { + Node *cn = classLookup(t); + if (cn != NULL) { + ret = Getattr(cn, "sym:name"); + if (ret == NULL) { + ret = Getattr(cn, "name"); + } + ret = exportedName(ret); + + Node *cnmod = Getattr(cn, "module"); + if (cnmod == NULL || Strcmp(Getattr(cnmod, "name"), package) == 0) { + Setattr(undefined_types, t, t); + } else { + String *nw = NewString(""); + Printv(nw, Getattr(cnmod, "name"), ".", ret, NULL); + Delete(ret); + ret = nw; + } + } else { + // SWIG does not know about this type. + ret = exportedName(t); + Setattr(undefined_types, t, t); + } + if (p_is_interface != NULL) { + *p_is_interface = true; + } + } else if (SwigType_ispointer(t) || SwigType_isarray(t)) { + SwigType *r = Copy(t); + if (SwigType_ispointer(r)) { + SwigType_del_pointer(r); + } else { + SwigType_del_array(r); + } + + if (SwigType_type(r) == T_VOID) { + ret = NewString("uintptr"); + } else { + bool is_interface; + String *base = goTypeWithInfo(n, r, &is_interface); + + // At the Go level, an unknown or class type is handled as an + // interface wrapping a pointer. This means that if a + // function returns the C type X, we will be wrapping the C + // type X*. In Go we will call that type X. That means that + // if a C function expects X*, we can pass the Go type X. And + // that means that when we see the C type X*, we should use + // the Go type X. + + // The is_interface variable tells us this. However, it will + // be true both for the case of X and for the case of X*. If + // r is a pointer here, then we are looking at X**. There is + // really no good way for us to handle that. + bool is_pointer_to_pointer = false; + if (is_interface) { + SwigType *c = Copy(r); + if (SwigType_isqualifier(c)) { + SwigType_del_qualifier(c); + if (SwigType_ispointer(c) || SwigType_isarray(c)) { + is_pointer_to_pointer = true; + } + } + Delete(c); + } + + if (is_interface) { + if (!is_pointer_to_pointer) { + ret = base; + if (p_is_interface != NULL) { + *p_is_interface = true; + } + } else { + ret = NewString("uintptr"); + } + } else { + ret = NewString("*"); + Append(ret, base); + Delete(base); + } + } + + Delete(r); + } else if (SwigType_isreference(t)) { + SwigType *r = Copy(t); + SwigType_del_reference(r); + + // If this is a const reference, and we are looking at a pointer + // to it, then we just use the pointer we already have. + bool add_pointer = true; + if (SwigType_isqualifier(r)) { + String *q = SwigType_parm(r); + if (Strcmp(q, "const") == 0) { + SwigType *c = Copy(r); + SwigType_del_qualifier(c); + if (SwigType_ispointer(c)) { + add_pointer = false; + } + Delete(c); + } + } + if (add_pointer) { + SwigType_add_pointer(r); + } + ret = goTypeWithInfo(n, r, p_is_interface); + Delete(r); + } else if (SwigType_isqualifier(t)) { + SwigType *r = Copy(t); + SwigType_del_qualifier(r); + ret = goTypeWithInfo(n, r, p_is_interface); + Delete(r); + } + + Delete(t); + + if (ret == NULL) { + Swig_warning(WARN_LANG_NATIVE_UNIMPL, input_file, line_number, + "No Go typemap defined for %s\n", + SwigType_str(type, 0)); + ret = NewString("uintptr"); + } + + return ret; + } + + /* ---------------------------------------------------------------------- + * goWrapperType() + * + * Given a type, return a string for the type to use for the wrapped + * Go function. This function exists because for a C++ class we + * need to convert interface and reference types. + * ---------------------------------------------------------------------- */ + + String *goWrapperType(Node *n, SwigType *type, bool is_result) { + bool is_interface; + String *ret = goTypeWithInfo(n, type, &is_interface); + + // If this is an interface, we want to pass the real type. + if (is_interface) { + Delete(ret); + if (!is_result) { + ret = NewString("uintptr"); + } else { + SwigType *ty = SwigType_typedef_resolve_all(type); + while (true) { + if (SwigType_ispointer(ty)) { + SwigType_del_pointer(ty); + } else if (SwigType_isarray(ty)) { + SwigType_del_array(ty); + } else if (SwigType_isreference(ty)) { + SwigType_del_reference(ty); + } else if (SwigType_isqualifier(ty)) { + SwigType_del_qualifier(ty); + } else { + break; + } + } + assert(SwigType_issimple(ty)); + String *p = goCPointerType(ty, true); + Delete(ty); + ret = p; + } + } + + return ret; + } + + /* ---------------------------------------------------------------------- + * goCPointerType() + * + * Return the name of the Go type to use for the C pointer value. + * The regular C type is the name of an interface type which wraps a + * pointer whose name is returned by this function. + * ---------------------------------------------------------------------- */ + + String *goCPointerType(SwigType *type, bool add_to_hash) { + SwigType *ty = SwigType_typedef_resolve_all(type); + Node *cn = classLookup(ty); + String *ex; + String *ret; + if (cn == NULL) { + if (add_to_hash) { + Setattr(undefined_types, ty, ty); + } + ret = NewString("Swigcptr"); + ex = exportedName(ty); + Append(ret, ex); + } else { + String *cname = Getattr(cn, "sym:name"); + if (cname == NULL) { + cname = Getattr(cn, "name"); + } + ex = exportedName(cname); + Node *cnmod = Getattr(cn, "module"); + if (cnmod == NULL || Strcmp(Getattr(cnmod, "name"), package) == 0) { + if (add_to_hash) { + Setattr(undefined_types, ty, ty); + } + ret = NewString("Swigcptr"); + Append(ret, ex); + } else { + ret = NewString(""); + Printv(ret, Getattr(cnmod, "name"), ".Swigcptr", ex, NULL); + } + } + Delete(ty); + Delete(ex); + return ret; + } + + /* ---------------------------------------------------------------------- + * gcCTypeForGoValue() + * + * Given a type, return the C/C++ type which will be used to catch + * the value in Go. This is the 6g/8g version. + * ---------------------------------------------------------------------- */ + + String *gcCTypeForGoValue(Node *n, SwigType *type, String *name) { + bool is_interface; + String *gt = goTypeWithInfo(n, type, &is_interface); + bool is_string = Strcmp(gt, "string") == 0; + bool is_slice = Strncmp(gt, "[]", 2) == 0; + bool is_function = Strcmp(gt, "_swig_fnptr") == 0; + bool is_member = Strcmp(gt, "_swig_memberptr") == 0; + bool is_complex = Strcmp(gt, "complex") == 0; + bool is_complex64 = Strcmp(gt, "complex64") == 0; + bool is_complex128 = Strcmp(gt, "complex128") == 0; + Delete(gt); + + String *ret; + if (is_string) { + // Note that we don't turn a reference to a string into a + // pointer to a string. Strings are immutable anyhow. + ret = NewString("_gostring_ "); + Append(ret, name); + return ret; + } else if (is_slice) { + ret = NewString("_goslice_ "); + } else if (is_function || is_member) { + ret = NewString("void *"); + Append(ret, name); + return ret; + } else if (is_complex || is_complex64) { + ret = NewString("_Complex float "); + } else if (is_complex128) { + ret = NewString("_Complex double "); + } else if (is_interface) { + SwigType *t = SwigType_typedef_resolve_all(type); + SwigType_strip_qualifiers(t); + if (SwigType_ispointer(t)) { + SwigType_del_pointer(t); + SwigType_strip_qualifiers(t); + } + if (SwigType_isreference(t)) { + SwigType_del_reference(t); + SwigType_strip_qualifiers(t); + } + SwigType_add_pointer(t); + ret = SwigType_lstr(t, name); + Delete(t); + return ret; + } else { + SwigType *t = SwigType_typedef_resolve_all(type); + if (SwigType_isreference(t)) { + // A const reference to a known type, or to a pointer, is not + // mapped to a pointer. + SwigType_del_reference(t); + if (SwigType_isqualifier(t)) { + String *q = SwigType_parm(t); + if (Strcmp(q, "const") == 0) { + SwigType_del_qualifier(t); + if (hasGoTypemap(t) || SwigType_ispointer(t)) { + ret = SwigType_lstr(t, name); + Delete(q); + Delete(t); + return ret; + } + } + Delete(q); + } + } + Delete(t); + return SwigType_lstr(type, name); + } + + if (SwigType_isreference(type)) { + Append(ret, "* "); + } + Append(ret, name); + return ret; + } + + /* ---------------------------------------------------------------------- + * gcCTypeForGoValue() + * + * Given a type, return the C/C++ type which will be used to catch + * the value in Go. This is the gccgo version. + * ---------------------------------------------------------------------- */ + + String *gccgoCTypeForGoValue(Node *n, SwigType *type, String *name) { + return gcCTypeForGoValue(n, type, name); + } + + /* ------------------------------------------------------------ + * goTypeIsInterface + * + * Return whether this C++ type is represented as an interface type + * in Go. These types require adjustments in the Go code when + * passing them back and forth between Go and C++. + * ------------------------------------------------------------ */ + + bool goTypeIsInterface(Node *n, SwigType *type) { + bool is_interface; + Delete(goTypeWithInfo(n, type, &is_interface)); + return is_interface; + } + + /* ------------------------------------------------------------ + * hasGoTypemap + * + * Return whether a type has a "go" typemap entry. + * ------------------------------------------------------------ */ + + bool hasGoTypemap(SwigType *type) { + Parm *p = NewParmWithoutFileLineInfo(type, "test"); + SwigType *tm = Swig_typemap_lookup("go", p, "", NULL); + Delete(p); + if (tm != NULL && Strstr(tm, "$gotypename") == NULL) { + Delete(tm); + return true; + } + if (tm != NULL) { + Delete(tm); + } + return false; + } + + /* ---------------------------------------------------------------------- + * goEnumName() + * + * Given an enum node, return a string to use for the enum type in + * Go. + * ---------------------------------------------------------------------- */ + + String *goEnumName(Node *n) { + String *ret = Getattr(n, "go:enumname"); + if (ret != NULL) { + return Copy(ret); + } + + if (Strcmp(Getattr(n, "type"), "enum ") == 0) { + return NewString("int"); + } + + String *type = Getattr(n, "enumtype"); + assert(type != NULL); + char *p = Char(type); + int len = Len(type); + String *s = NewString(""); + bool capitalize = true; + for (int i = 0; i < len; ++i, ++p) { + if (*p == ':') { + ++i; + ++p; + assert(*p == ':'); + capitalize = true; + } else if (capitalize) { + Putc(toupper(*p), s); + capitalize = false; + } else { + Putc(*p, s); + } + } + + ret = Swig_name_mangle(s); + Delete(s); + return ret; + } + + + /* ------------------------------------------------------------ + * getParm() + * + * Get the real parameter to use. + * ------------------------------------------------------------ */ + + Parm *getParm(Parm *p) { + while (p != NULL && checkAttribute(p, "tmap:in:numinputs", "0")) { + p = Getattr(p, "tmap:in:next"); + } + return p; + } + + /* ------------------------------------------------------------ + * nextParm() + * + * Return the next parameter. + * ------------------------------------------------------------ */ + + Parm *nextParm(Parm *p) { + if (p == NULL) { + return NULL; + } else if (Getattr(p, "tmap:in") != NULL) { + return Getattr(p, "tmap:in:next"); + } else { + return nextSibling(p); + } + } + + /* ------------------------------------------------------------ + * isStatic + * + * Return whether a node should be considered as static rather than + * as a member. + * ------------------------------------------------------------ */ + + bool isStatic(Node *n) { + String *storage = Getattr(n, "storage"); + return (storage != NULL + && (Strcmp(storage, "static") == 0 + || Strcmp(storage, "friend") == 0) + && (!SmartPointer + || Getattr(n, "allocate:smartpointeraccess") == NULL)); + } + + /* ------------------------------------------------------------ + * isFriend + * + * Return whether a node is a friend. + * ------------------------------------------------------------ */ + + bool isFriend(Node *n) { + String *storage = Getattr(n, "storage"); + return storage != NULL && Strcmp(storage, "friend") == 0; + } + +}; /* class GO */ + +/* ----------------------------------------------------------------------------- + * swig_go() - Instantiate module + * ----------------------------------------------------------------------------- */ + +static Language *new_swig_go() { + return new GO(); +} +extern "C" Language *swig_go(void) { + return new_swig_go(); +} + +/* ----------------------------------------------------------------------------- + * Static member variables + * ----------------------------------------------------------------------------- */ + +// Usage message. +const char * const GO::usage = (char *) "\ +Go Options (available with -go)\n\ + -package - set name of the Go package to \n\ + -gccgo - generate code for gccgo rather than 6g/8g\n\ + -go-prefix

    - like gccgo -fgo-prefix option\n\ + -soname - name for shared library holding C/C++ code\n\ + -longsize - set size of C/C++ long type--32 or 64 bits\n\ + -rename = - rename symbols\n\ +\n"; diff --git a/Source/Modules/overload.cxx b/Source/Modules/overload.cxx index 65deee2de..a62bdc1bf 100644 --- a/Source/Modules/overload.cxx +++ b/Source/Modules/overload.cxx @@ -59,7 +59,7 @@ void Wrapper_cast_dispatch_mode_set(int flag) { * languages ignore the first method parsed. * ----------------------------------------------------------------------------- */ -static List *Swig_overload_rank(Node *n, bool script_lang_wrapping) { +List *Swig_overload_rank(Node *n, bool script_lang_wrapping) { Overloaded nodes[MAX_OVERLOAD]; int nnodes = 0; Node *o = Getattr(n, "sym:overloaded"); diff --git a/Source/Modules/r.cxx b/Source/Modules/r.cxx index e4b246c4e..8f5503743 100644 --- a/Source/Modules/r.cxx +++ b/Source/Modules/r.cxx @@ -1299,6 +1299,8 @@ void R::addAccessor(String *memberName, Wrapper *wrapper, String *name, Printf(stderr, "Adding accessor: %s (%s) => %s\n", memberName, name, tmp); } +#define Swig_overload_rank R_swig_overload_rank + #define MAX_OVERLOAD 256 struct Overloaded { diff --git a/Source/Modules/swigmain.cxx b/Source/Modules/swigmain.cxx index 1ed85e82e..86cccdf88 100644 --- a/Source/Modules/swigmain.cxx +++ b/Source/Modules/swigmain.cxx @@ -51,6 +51,7 @@ extern "C" { Language *swig_cffi(void); Language *swig_uffi(void); Language *swig_r(void); + Language *swig_go(void); } struct swig_module { @@ -69,6 +70,7 @@ static swig_module modules[] = { {"-clisp", swig_clisp, "CLISP"}, {"-cffi", swig_cffi, "CFFI"}, {"-csharp", swig_csharp, "C#"}, + {"-go", swig_go, "Go"}, {"-guile", swig_guile, "Guile"}, {"-java", swig_java, "Java"}, {"-lua", swig_lua, "Lua"}, diff --git a/Source/Modules/swigmod.h b/Source/Modules/swigmod.h index 016ccc8d4..b0b488d6f 100644 --- a/Source/Modules/swigmod.h +++ b/Source/Modules/swigmod.h @@ -344,6 +344,7 @@ void Swig_overload_check(Node *n); String *Swig_overload_dispatch(Node *n, const_String_or_char_ptr fmt, int *); String *Swig_overload_dispatch_cast(Node *n, const_String_or_char_ptr fmt, int *); String *Swig_overload_dispatch_fast(Node *n, const_String_or_char_ptr fmt, int *); +List *Swig_overload_rank(Node *n, bool script_lang_wrapping); SwigType *cplus_value_type(SwigType *t); /* directors.cxx start */ diff --git a/configure.in b/configure.in index fe95fa7c0..f08ad4615 100644 --- a/configure.in +++ b/configure.in @@ -1950,6 +1950,35 @@ fi AC_SUBST(RBIN) +#---------------------------------------------------------------- +# Look for Go compilers +#---------------------------------------------------------------- + +AC_ARG_WITH(go, AS_HELP_STRING([--without-go], [Disable Go]) +AS_HELP_STRING([--with-go=path], [Set location of Go compiler]),[GOBIN="$withval"], [GOBIN=yes]) + +if test x"${GOBIN}" = xno -o x"${with_alllang}" = xno ; then +AC_MSG_NOTICE([Disabling Go]) +GO= +GOGCC=false +else + + if test "x$GOBIN" = xyes; then + AC_CHECK_PROGS(GO, 6g 8g gccgo) + else + GO="$GOBIN" + fi + + GOGCC=false + if $GO --help 2>/dev/null | grep gccgo >/dev/null 2>&1 ; then + GOGCC=true + fi + +fi + +AC_SUBST(GOGCC) +AC_SUBST(GO) + #---------------------------------------------------------------- # Determine which languages to use for examples/test-suite #---------------------------------------------------------------- @@ -2100,6 +2129,12 @@ SKIP_UFFI= #fi AC_SUBST(SKIP_UFFI) +SKIP_GO= +if test -z "$GO" ; then + SKIP_GO="1" +fi +AC_SUBST(SKIP_GO) + #---------------------------------------------------------------- # Additional language dependencies #---------------------------------------------------------------- @@ -2178,6 +2213,7 @@ AC_CONFIG_FILES([ \ Examples/test-suite/cffi/Makefile \ Examples/test-suite/uffi/Makefile \ Examples/test-suite/r/Makefile \ + Examples/test-suite/go/Makefile \ Lib/ocaml/swigp4.ml ]) AC_CONFIG_FILES([preinst-swig], [chmod +x preinst-swig])