Added constructor that can take functors to all
containers that can use one. Created file rubystdfunctors.swg to allow passing in Ruby procs as functors to STL functions (swig-user list suggestion for Python). Fixed a bug in type_info() always failing for std::set. Fixed a bug in type_info() always accepting any failed conversion which could lead to overloaded functions to fail when input wrong parameters. git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@9775 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
parent
f92ebdbe07
commit
1cf8fd332b
9 changed files with 186 additions and 14 deletions
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<Type>(), 0) == SWIG_OK) ? SWIG_OLDOBJ : 0;
|
||||
int res = SWIG_ConvertPtr(obj, (void**)&p, type_info<Type>(), 0);
|
||||
if (SWIG_IsOK(res)) {
|
||||
if (val) *val = p;
|
||||
}
|
||||
|
|
|
|||
174
Lib/ruby/rubystdfunctors.swg
Normal file
174
Lib/ruby/rubystdfunctors.swg
Normal file
|
|
@ -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 <class _DefaultFunc = std::less<GC_VALUE> >
|
||||
struct RubyBinaryPredicate : GC_VALUE, std::binary_function<GC_VALUE, GC_VALUE, bool>
|
||||
{
|
||||
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 <class _DefaultFunc = std::less<GC_VALUE> >
|
||||
struct RubyBinaryFunction : GC_VALUE, std::binary_function<GC_VALUE, GC_VALUE, GC_VALUE>
|
||||
{
|
||||
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<GC_VALUE, bool>
|
||||
{
|
||||
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<GC_VALUE, GC_VALUE>
|
||||
{
|
||||
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);
|
||||
}
|
||||
};
|
||||
}
|
||||
%}
|
||||
|
||||
|
||||
|
|
@ -398,4 +398,5 @@
|
|||
|
||||
%mixin std::map "Enumerable";
|
||||
|
||||
%include <rubystdfunctors.swg>
|
||||
%include <std/std_map.i>
|
||||
|
|
|
|||
|
|
@ -59,4 +59,5 @@
|
|||
|
||||
%mixin std::set "Enumerable";
|
||||
|
||||
%include <rubystdfunctors.swg>
|
||||
%include <std/std_set.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 >);
|
||||
|
|
|
|||
|
|
@ -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 >);
|
||||
|
|
|
|||
|
|
@ -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 >);
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ namespace std {
|
|||
template <> struct traits<std::set<_Key, _Compare, _Alloc > > {
|
||||
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 >);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue