1 /** 2 * @file rubystdfunctors.swg 3 * @date Sun May 6 00:44:33 2007 4 * 5 * @brief This file provides unary and binary functors for STL 6 * containers, that will invoke a Ruby proc or method to do 7 * their operation. 8 * 9 * You can use them in a swig file like: 10 * 11 * %include <std_set.i> 12 * %include <std_functors.i> 13 * 14 * %template< IntSet > std::set< int, swig::BinaryPredicate<> >; 15 * 16 * 17 * which will then allow calling them from Ruby either like: 18 * 19 * # order of set is defined by C++ default 20 * a = IntSet.new 21 * 22 * # sort order defined by Ruby proc 23 * b = IntSet.new( proc { |a,b| a > b } ) 24 * 25 */ 26 27 %include rubyclasses.swg 28 29 30 namespace swig { 31 32 %apply GC_VALUE { UnaryPredicate, BinaryPredicate, UnaryFunction, 33 BinaryFunction }; 34 35 %typecheck(SWIG_TYPECHECK_POINTER,noblock=1) 36 UnaryPredicate, UnaryPredicate&, UnaryFunction, UnaryFunction& 37 { 38 $1 = SWIG_Ruby_isCallable($input) && SWIG_Ruby_arity($input, 1); 39 } 40 41 %typecheck(SWIG_TYPECHECK_POINTER,noblock=1) 42 BinaryPredicate, BinaryPredicate&, BinaryFunction, BinaryFunction& { 43 $1 = SWIG_Ruby_isCallable($input) && SWIG_Ruby_arity($input, 2); 44 } 45 46 %typemap(in,noblock=1) BinaryFunction&, BinaryFunction { 47 $1 = new swig::BinaryFunction< >($input); 48 } 49 %typemap(in,noblock=1) UnaryFunction&, UnaryFunction { 50 $1 = new swig::UnaryFunction< >($input); 51 } 52 53 %typemap(in,noblock=1) BinaryPredicate&, BinaryPredicate { 54 $1 = new swig::BinaryPredicate<>($input); 55 } 56 57 %typemap(in,noblock=1) UnaryPredicate&, UnaryPredicate { 58 $1 = new swig::UnaryPredicate< >($input); 59 } 60 61 62 %ignore BinaryFunction; 63 template< class _T = GC_VALUE > 64 struct BinaryFunction { 65 }; 66 67 %ignore UnaryFunction; 68 template< class _T = GC_VALUE > 69 struct UnaryFunction { 70 }; 71 72 %ignore BinaryPredicate; 73 template< class _T = GC_VALUE > 74 struct BinaryPredicate { 75 }; 76 77 %ignore UnaryPredicate; 78 template< class _T = GC_VALUE > 79 struct UnaryPredicate { 80 81 }; 82 83 } 84 85 86 %fragment("StdFunctors","header",fragment="StdTraits",fragment="GC_VALUE_definition") 87 { 88 namespace swig { 89 90 static ID call_id = rb_intern("call"); 91 92 template <class _T = GC_VALUE, class _DefaultFunc = std::less<GC_VALUE> > 93 struct BinaryPredicate : GC_VALUE, std::binary_function< _T, _T, bool > 94 { 95 BinaryPredicate(VALUE obj = Qnil) : GC_VALUE(obj) { } 96 bool operator()(_T a, _T b) const 97 { 98 if (_obj != Qnil) { 99 SWIG_RUBY_THREAD_BEGIN_BLOCK; 100 VALUE arg1 = swig::from(a); 101 VALUE arg2 = swig::from(b); 102 VALUE res = rb_funcall( _obj, swig::call_id, 2, arg1, arg2); 103 SWIG_RUBY_THREAD_END_BLOCK; 104 return RTEST(res); 105 } else { 106 return _DefaultFunc()(a, b); 107 } 108 } 109 }; 110 111 template <class _T = GC_VALUE, class _DefaultFunc = std::less< _T > > 112 struct BinaryFunction : GC_VALUE, std::binary_function< _T, _T, _T > 113 { 114 BinaryFunction(VALUE obj = Qnil) : GC_VALUE(obj) { } 115 _T operator()(_T a, _T b) const 116 { 117 if (_obj != Qnil) { 118 SWIG_RUBY_THREAD_BEGIN_BLOCK; 119 VALUE arg1 = swig::from(a); 120 VALUE arg2 = swig::from(b); 121 VALUE res = rb_funcall( _obj, swig::call_id, 2, arg1, arg2); 122 SWIG_RUBY_THREAD_END_BLOCK; 123 return swig::as<_T >(res); 124 } else { 125 return _DefaultFunc()(a, b); 126 } 127 } 128 }; 129 130 template< class _T = GC_VALUE > 131 struct UnaryPredicate : GC_VALUE, std::unary_function< _T, bool > 132 { 133 UnaryPredicate(VALUE obj = Qnil) : GC_VALUE(obj) { } 134 bool operator()(_T a) const 135 { 136 SWIG_RUBY_THREAD_BEGIN_BLOCK; 137 VALUE arg1 = swig::from<_T >(a); 138 VALUE res = rb_funcall( _obj, swig::call_id, 1, arg1); 139 SWIG_RUBY_THREAD_END_BLOCK; 140 return RTEST(res); 141 } 142 }; 143 144 template< class _T = GC_VALUE > 145 struct UnaryFunction : GC_VALUE, std::unary_function< _T, _T > 146 { 147 UnaryFunction(VALUE obj = Qnil) : GC_VALUE(obj) { } 148 _T operator()(_T a) const 149 { 150 SWIG_RUBY_THREAD_BEGIN_BLOCK; 151 VALUE arg1 = swig::from(a); 152 VALUE res = rb_funcall( _obj, swig::call_id, 1, VALUE(arg1)); 153 SWIG_RUBY_THREAD_END_BLOCK; 154 return swig::as< _T >(res); 155 } 156 }; 157 158 } // namespace swig 159 160 } 161 162 163