From a1cea4f483144952989580f54e73f38f94b90562 Mon Sep 17 00:00:00 2001 From: Joel Anderson Date: Wed, 21 Mar 2018 19:12:54 -0400 Subject: [PATCH] Fix ruby %alias directive for native c functions Using the %alias directive on native C functions causes swig to segfault due to a dereference of klass (which is NULL for native C functions) in the defineAliases function of the Ruby module. This commit adds support for an alias of native C functions for both separate module as well as global functions, as well as three test cases for the %alias directive of the Ruby module. Fixes: mod.i %module ruby_alias %alias get_my_name "nickname,fullname"; %inline %{ const char *get_my_name(){ return "Chester Tester"; } %} $ swig -ruby mod.i Segmentation fault Signed-off-by: Joel Anderson --- Examples/test-suite/ruby/Makefile.in | 4 +++ .../ruby/ruby_alias_global_function_runme.rb | 20 ++++++++++++++ .../ruby/ruby_alias_method_runme.rb | 24 +++++++++++++++++ .../ruby/ruby_alias_module_function_runme.rb | 26 +++++++++++++++++++ .../test-suite/ruby_alias_global_function.i | 11 ++++++++ Examples/test-suite/ruby_alias_method.i | 26 +++++++++++++++++++ .../test-suite/ruby_alias_module_function.i | 11 ++++++++ Source/Modules/ruby.cxx | 8 +++++- 8 files changed, 129 insertions(+), 1 deletion(-) create mode 100644 Examples/test-suite/ruby/ruby_alias_global_function_runme.rb create mode 100644 Examples/test-suite/ruby/ruby_alias_method_runme.rb create mode 100644 Examples/test-suite/ruby/ruby_alias_module_function_runme.rb create mode 100644 Examples/test-suite/ruby_alias_global_function.i create mode 100644 Examples/test-suite/ruby_alias_method.i create mode 100644 Examples/test-suite/ruby_alias_module_function.i diff --git a/Examples/test-suite/ruby/Makefile.in b/Examples/test-suite/ruby/Makefile.in index 292244a9e..add65fe9f 100644 --- a/Examples/test-suite/ruby/Makefile.in +++ b/Examples/test-suite/ruby/Makefile.in @@ -22,6 +22,7 @@ CPP_TEST_CASES = \ li_std_stack \ li_std_wstring \ primitive_types \ + ruby_alias_method \ ruby_keywords \ ruby_minherit_shared_ptr \ ruby_naming \ @@ -44,6 +45,8 @@ CPP11_TEST_CASES = \ C_TEST_CASES += \ li_cstring \ + ruby_alias_global_function \ + ruby_alias_module_function \ ruby_manual_proxy \ include $(srcdir)/../common.mk @@ -52,6 +55,7 @@ include $(srcdir)/../common.mk SWIGOPT += -w801 -noautorename -features autodoc=4 # Custom tests - tests with additional commandline options +ruby_alias_global_function.ctest: SWIGOPT += -globalmodule ruby_naming.cpptest: SWIGOPT += -autorename # Rules for the different types of tests diff --git a/Examples/test-suite/ruby/ruby_alias_global_function_runme.rb b/Examples/test-suite/ruby/ruby_alias_global_function_runme.rb new file mode 100644 index 000000000..14e38e4cf --- /dev/null +++ b/Examples/test-suite/ruby/ruby_alias_global_function_runme.rb @@ -0,0 +1,20 @@ +#!/usr/bin/env ruby +# +# Runtime tests for ruby_alias_global_function.i +# + +require 'swig_assert' +require 'ruby_alias_global_function' + +expected_name = get_my_name + +swig_assert(fullname == expected_name, msg: "nickname not working as expected") +swig_assert(nickname == expected_name, msg: "fullname not working as expected") + +if method(:nickname).respond_to?(:original_name) + swig_assert_equal_simple(method(:nickname).original_name, :get_my_name) + swig_assert_equal_simple(method(:fullname).original_name, :get_my_name) +else + swig_assert(method(:nickname) == method(:get_my_name), msg: "nickname is not an alias of get_my_name") + swig_assert(method(:fullname) == method(:get_my_name), msg: "fullname is not an alias of get_my_name") +end diff --git a/Examples/test-suite/ruby/ruby_alias_method_runme.rb b/Examples/test-suite/ruby/ruby_alias_method_runme.rb new file mode 100644 index 000000000..c19101e63 --- /dev/null +++ b/Examples/test-suite/ruby/ruby_alias_method_runme.rb @@ -0,0 +1,24 @@ +#!/usr/bin/env ruby +# +# Runtime tests for ruby_alias_method.i +# + +require 'swig_assert' +require 'ruby_alias_method' + +include Ruby_alias_method + +expected_name = "Chester Tester" +syn = Synonym.new(expected_name) + +swig_assert(syn.getMyName() == expected_name, msg: "getMyName not working as expected") +swig_assert(syn.nickname() == expected_name, msg: "nickname not working as expected") +swig_assert(syn.fullname() == expected_name, msg: "fullname not working as expected") + +if syn.method(:nickname).respond_to?(:original_name) + swig_assert_equal_simple(syn.method(:nickname).original_name, :getMyName) + swig_assert_equal_simple(syn.method(:fullname).original_name, :getMyName) +else + swig_assert(syn.method(:nickname) == syn.method(:getMyName)) + swig_assert(syn.method(:fullname) == syn.method(:getMyName)) +end diff --git a/Examples/test-suite/ruby/ruby_alias_module_function_runme.rb b/Examples/test-suite/ruby/ruby_alias_module_function_runme.rb new file mode 100644 index 000000000..1f4205f1f --- /dev/null +++ b/Examples/test-suite/ruby/ruby_alias_module_function_runme.rb @@ -0,0 +1,26 @@ +#!/usr/bin/env ruby +# +# Runtime tests for ruby_alias_module_function.i +# + +require 'swig_assert' +require 'ruby_alias_module_function' + +include Ruby_alias_module_function + +expected_name = Ruby_alias_module_function.get_my_name + +swig_assert(Ruby_alias_module_function.nickname == expected_name, msg: "nickname returned a different result than get_my_name") +swig_assert(Ruby_alias_module_function.fullname == expected_name, msg: "fullname returned a different result than get_my_name") + +nickname_method = Ruby_alias_module_function.method(:nickname) +fullname_method = Ruby_alias_module_function.method(:fullname) + +if nickname_method.respond_to?(:original_name) + swig_assert_equal_simple(nickname_method.original_name, :get_my_name) + swig_assert_equal_simple(fullname_method.original_name, :get_my_name) +else + original_method = Ruby_alias_module_function.method(:get_my_name) + swig_assert(nickname_method == original_method, msg: "nickname is not an alias of get_my_name") + swig_assert(fullname_method == original_method, msg: "fullname is not an alias of get_my_name") +end diff --git a/Examples/test-suite/ruby_alias_global_function.i b/Examples/test-suite/ruby_alias_global_function.i new file mode 100644 index 000000000..bddb24959 --- /dev/null +++ b/Examples/test-suite/ruby_alias_global_function.i @@ -0,0 +1,11 @@ +%module ruby_alias_global_function + +%alias get_my_name "nickname,fullname"; + +%inline %{ + +const char *get_my_name(){ + return "Chester Tester"; +} + +%} diff --git a/Examples/test-suite/ruby_alias_method.i b/Examples/test-suite/ruby_alias_method.i new file mode 100644 index 000000000..9ddcfce5e --- /dev/null +++ b/Examples/test-suite/ruby_alias_method.i @@ -0,0 +1,26 @@ +%module ruby_alias_method +%include + +%alias Synonym::getMyName "nickname,fullname" + +%inline %{ + +class Synonym { +private: + std::string myName; + +public: + Synonym(std::string myName); + + std::string getMyName(); +}; + +Synonym::Synonym(std::string myName){ + this->myName = myName; +}; + +std::string Synonym::getMyName(){ + return this->myName; +}; + +%} diff --git a/Examples/test-suite/ruby_alias_module_function.i b/Examples/test-suite/ruby_alias_module_function.i new file mode 100644 index 000000000..900de5f1d --- /dev/null +++ b/Examples/test-suite/ruby_alias_module_function.i @@ -0,0 +1,11 @@ +%module ruby_alias_module_function + +%alias get_my_name "nickname,fullname"; + +%inline %{ + +const char *get_my_name(){ + return "Chester Tester"; +} + +%} diff --git a/Source/Modules/ruby.cxx b/Source/Modules/ruby.cxx index 69a849d16..78bd23a6e 100644 --- a/Source/Modules/ruby.cxx +++ b/Source/Modules/ruby.cxx @@ -1316,7 +1316,13 @@ public: Iterator alias = First(aliases); while (alias.item) { if (Len(alias.item) > 0) { - if (multipleInheritance) { + if (current == NO_CPP) { + if (useGlobalModule) { + Printv(f_init, tab4, "rb_define_alias(rb_cObject, \"", alias.item, "\", \"", iname, "\");\n", NIL); + } else { + Printv(f_init, tab4, "rb_define_alias(rb_singleton_class(", modvar, "), \"", alias.item, "\", \"", iname, "\");\n", NIL); + } + } else if (multipleInheritance) { Printv(klass->init, tab4, "rb_define_alias(", klass->mImpl, ", \"", alias.item, "\", \"", iname, "\");\n", NIL); } else { Printv(klass->init, tab4, "rb_define_alias(", klass->vname, ", \"", alias.item, "\", \"", iname, "\");\n", NIL);