diff --git a/Lib/ruby/rubyrun.swg b/Lib/ruby/rubyrun.swg index 1af45b3d2..1205d590a 100644 --- a/Lib/ruby/rubyrun.swg +++ b/Lib/ruby/rubyrun.swg @@ -394,18 +394,6 @@ SWIG_Ruby_SetModule(swig_module_info *pointer) rb_define_readonly_variable("$swig_runtime_data_type_pointer" SWIG_RUNTIME_VERSION SWIG_TYPE_TABLE_NAME, &swig_runtime_data_type_pointer); } -/* This function can be used to check whether a proc or method or similarly - callable function has been passed. Usually used in a %typecheck. */ -SWIGINTERN -int SWIG_Ruby_isCallable( VALUE proc ) -{ - static VALUE call_id = Qnil; - if ( call_id == Qnil ) call_id = rb_intern("call"); - if ( rb_respond_to( proc, call_id ) ) - return 1; - return 0; -} - #ifdef __cplusplus } diff --git a/Lib/ruby/rubystdcommon.swg b/Lib/ruby/rubystdcommon.swg index c953ea86f..98292957f 100644 --- a/Lib/ruby/rubystdcommon.swg +++ b/Lib/ruby/rubystdcommon.swg @@ -53,7 +53,7 @@ namespace swig { struct traits_asptr { static int asptr(VALUE obj, Type **val) { Type *p; - int res = (SWIG_ConvertPtr(obj, (void**)&p, type_info(), 0) == SWIG_OK) ? SWIG_OLDOBJ : 0; + int res = SWIG_ConvertPtr(obj, (void**)&p, type_info(), 0); if (SWIG_IsOK(res)) { if (val) *val = p; } diff --git a/Lib/ruby/rubystdfunctors.swg b/Lib/ruby/rubystdfunctors.swg new file mode 100644 index 000000000..a63f3365b --- /dev/null +++ b/Lib/ruby/rubystdfunctors.swg @@ -0,0 +1,174 @@ +/** + * @file rubystdfunctors.swg + * @date Sun May 6 00:44:33 2007 + * + * @brief This file provides unary and binary functors for STL + * containers, that will invoke a Ruby proc or method to do + * their operation. + * + * You can use them in a swig file like: + * + * %template< IntSet > std::set< int, RubyBinaryPredicate<> >; + * + * + * which will then allow calling them from Ruby either like: + * + * # order of set is defined by C++ default + * a = IntSet.new + * + * # sort order defined by Ruby proc + * b = IntSet.new( proc { |a,b| a > b } ) + * + */ + + +%{ +/* This function can be used to check whether a proc or method or similarly + callable function has been passed. Usually used in a %typecheck. */ +SWIGINTERN +int SWIG_Ruby_isCallable( VALUE proc ) +{ + static VALUE call_id = rb_intern("call"); + if ( rb_respond_to( proc, call_id ) ) + return 1; + return 0; +} + +/* This function can be used to check the arity (number of arguments) + a proc or method can take. Usually used in a %typecheck. + Valid arities will be that equal to minimal or those < 0 + which indicate a variable number of parameters at the end. + */ +SWIGINTERN +int SWIG_Ruby_arity( VALUE proc, int minimal ) +{ + static VALUE arity_id = rb_intern("arity"); + if ( rb_respond_to( proc, arity_id ) ) + { + VALUE num = rb_funcall( proc, arity_id, 0 ); + int arity = NUM2INT(num); + if ( arity < 0 && (arity+1) < -minimal ) return 1; + if ( arity == minimal ) return 1; + return 1; + } + return 0; +} + +%} + + +namespace swig { + + %apply GC_VALUE { RubyUnaryPredicate, RubyBinaryPredicate, RubyUnaryFunction, + RubyBinaryFunction }; + + %typecheck(SWIG_TYPECHECK_POINTER,noblock=1) + RubyUnaryPredicate, RubyUnaryPredicate&, RubyUnaryFunction, RubyUnaryFunction& + { + $1 = SWIG_Ruby_isCallable($input) && SWIG_Ruby_arity($input, 1); + } + + %typecheck(SWIG_TYPECHECK_POINTER,noblock=1) + RubyBinaryPredicate, RubyBinaryPredicate&, RubyBinaryFunction, RubyBinaryFunction& { + $1 = SWIG_Ruby_isCallable($input) && SWIG_Ruby_arity($input, 2); + } + + %typemap(in,noblock=1) RubyUnaryFunction&, RubyUnaryFunction { + $1 = new swig::RubyUnaryFunction<>($input); + } + %typemap(in,noblock=1) RubyUnaryPredicate&, RubyUnaryPredicate { + $1 = new swig::RubyUnaryPredicate<>($input); + } + + %typemap(in,noblock=1) RubyBinaryFunction&, RubyBinaryFunction { + $1 = new swig::RubyBinaryFunction<>($input); + } + %typemap(in,noblock=1) RubyBinaryPredicate&, RubyBinaryPredicate { + $1 = new swig::RubyBinaryPredicate<>($input); + } + + + %ignore RubyBinaryFunction; + struct RubyBinaryFunction {}; + + %ignore RubyUnaryFunction; + struct RubyUnaryFunction {}; + + %ignore RubyBinaryPredicate; + struct RubyBinaryPredicate {}; + + %ignore RubyUnaryPredicate; + struct RubyUnaryPredicate {}; + +} + + +%{ +namespace swig { + + static ID call_id = rb_intern("call"); + + template > + struct RubyBinaryPredicate : GC_VALUE, std::binary_function + { + RubyBinaryPredicate(VALUE obj = Qnil) : GC_VALUE(obj) { } + bool operator()(GC_VALUE arg1, GC_VALUE arg2) const + { + if (_obj != Qnil) { + SWIG_RUBY_THREAD_BEGIN_BLOCK; + VALUE res = rb_funcall( _obj, swig::call_id, 2, + VALUE(arg1), VALUE(arg2)); + SWIG_RUBY_THREAD_END_BLOCK; + return RTEST(res); + } else { + return _DefaultFunc()(arg1, arg2); + } + } + }; + + template > + struct RubyBinaryFunction : GC_VALUE, std::binary_function + { + RubyBinaryFunction(VALUE obj = Qnil) : GC_VALUE(obj) { } + GC_VALUE operator()(GC_VALUE arg1, GC_VALUE arg2) const + { + if (_obj != Qnil) { + SWIG_RUBY_THREAD_BEGIN_BLOCK; + VALUE res = rb_funcall( _obj, swig::call_id, 2, + VALUE(arg1), VALUE(arg2)); + SWIG_RUBY_THREAD_END_BLOCK; + return GC_VALUE(res); + } else { + return _DefaultFunc()(arg1, arg2); + } + } + }; + + + struct RubyUnaryPredicate : GC_VALUE, std::unary_function + { + RubyUnaryPredicate(VALUE obj = Qnil) : GC_VALUE(obj) { } + bool operator()(GC_VALUE arg1) const + { + SWIG_RUBY_THREAD_BEGIN_BLOCK; + VALUE res = rb_funcall( _obj, swig::call_id, 1, VALUE(arg1)); + SWIG_RUBY_THREAD_END_BLOCK; + return RTEST(res); + } + }; + + struct RubyUnaryFunction : GC_VALUE, std::unary_function + { + RubyUnaryFunction(VALUE obj = Qnil) : GC_VALUE(obj) { } + GC_VALUE operator()(GC_VALUE arg1) const + { + SWIG_RUBY_THREAD_BEGIN_BLOCK; + VALUE res = rb_funcall( _obj, swig::call_id, 1, VALUE(arg1)); + SWIG_RUBY_THREAD_END_BLOCK; + return GC_VALUE(res); + } + }; +} +%} + + diff --git a/Lib/ruby/std_map.i b/Lib/ruby/std_map.i index 69d71e453..cf06f0797 100644 --- a/Lib/ruby/std_map.i +++ b/Lib/ruby/std_map.i @@ -398,4 +398,5 @@ %mixin std::map "Enumerable"; +%include %include diff --git a/Lib/ruby/std_set.i b/Lib/ruby/std_set.i index c0f529b9c..ab61a34e3 100644 --- a/Lib/ruby/std_set.i +++ b/Lib/ruby/std_set.i @@ -59,4 +59,5 @@ %mixin std::set "Enumerable"; +%include %include diff --git a/Lib/std/std_map.i b/Lib/std/std_map.i index 487223604..24f3f4a39 100644 --- a/Lib/std/std_map.i +++ b/Lib/std/std_map.i @@ -114,6 +114,8 @@ namespace std { %typemap_traits_ptr(SWIG_TYPECHECK_MAP, std::map<_Key, _Tp, _Compare, _Alloc >); + map( const _Compare&, const _Alloc& a = allocator_type() ); + #ifdef %swig_map_methods // Add swig/language extra methods %swig_map_methods(std::map<_Key, _Tp, _Compare, _Alloc >); diff --git a/Lib/std/std_multimap.i b/Lib/std/std_multimap.i index 0cf46a962..8da49af99 100644 --- a/Lib/std/std_multimap.i +++ b/Lib/std/std_multimap.i @@ -75,6 +75,8 @@ namespace std { %typemap_traits_ptr(SWIG_TYPECHECK_MULTIMAP, std::multimap<_Key, _Tp, _Compare, _Alloc >); + multimap( const _Compare&, const _Alloc& a = allocator_type() ); + #ifdef %swig_multimap_methods // Add swig/language extra methods %swig_multimap_methods(std::multimap<_Key, _Tp, _Compare, _Alloc >); diff --git a/Lib/std/std_multiset.i b/Lib/std/std_multiset.i index bec72e82a..9552edcc8 100644 --- a/Lib/std/std_multiset.i +++ b/Lib/std/std_multiset.i @@ -71,6 +71,8 @@ namespace std { %typemap_traits_ptr(SWIG_TYPECHECK_MULTISET, std::multiset<_Key, _Compare, _Alloc >); + multiset( const _Compare&, const _Alloc& a = allocator_type() ); + #ifdef %swig_multiset_methods // Add swig/language extra methods %swig_multiset_methods(std::multiset<_Key, _Compare, _Alloc >); diff --git a/Lib/std/std_set.i b/Lib/std/std_set.i index 685084174..15cf59008 100644 --- a/Lib/std/std_set.i +++ b/Lib/std/std_set.i @@ -83,7 +83,7 @@ namespace std { template <> struct traits > { typedef pointer_category category; static const char* type_name() { - return "std::set<" #_Key "," #_Alloc " >"; + return "std::set<" #_Key "," #_Compare "," #_Alloc " >"; } }; } @@ -91,6 +91,8 @@ namespace std { %typemap_traits_ptr(SWIG_TYPECHECK_SET, std::set<_Key, _Compare, _Alloc >); + set( const _Compare&, const _Alloc& a = allocator_type() ); + #ifdef %swig_set_methods // Add swig/language extra methods %swig_set_methods(std::set<_Key, _Compare, _Alloc >);