ruby-changes:26455
From: usa <ko1@a...>
Date: Thu, 20 Dec 2012 18:53:00 +0900 (JST)
Subject: [ruby-changes:26455] usa:r38506 (ruby_1_9_3): merge revision(s) 38202,38238,38324,38326: [Backport #7527]
usa 2012-12-20 18:52:46 +0900 (Thu, 20 Dec 2012) New Revision: 38506 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=38506 Log: merge revision(s) 38202,38238,38324,38326: [Backport #7527] * test/dl/test_func.rb (test_name_with_block, test_bind, test_qsort1): call unbind to release the callback closure because maximum number of callbacks is limited to DL::MAX_CALLBACK (== 5) with pure DL without Fiddle. * ext/dl/lib/dl/func.rb (DL::Function#unbind, #bound?): suppress NoMethodError when Fiddle is available. [ruby-core:50756] [Bug #7543] * test/dl/test_func.rb (test_bound*, test_unbind*): tests for the above. * ext/dl/lib/dl/func.rb (DL::Function#initialize, DL::Function#bind): ABI should be set by using CFunc#calltype even when Fiddle is used. When Fiddle is used and a block is given, name shoud not be ignored. [ruby-core:50562] [Bug #7514] * ext/dl/lib/dl/import.rb (DL::Importer#bind_function): should respect abi and name when Fiddle is used. * test/dl/test_func.rb (test_name_with_block): test for "name" method with giving a block. Modified directories: branches/ruby_1_9_3/ branches/ruby_1_9_3/test/dl/ Modified files: branches/ruby_1_9_3/ChangeLog branches/ruby_1_9_3/ext/dl/lib/dl/func.rb branches/ruby_1_9_3/ext/dl/lib/dl/import.rb branches/ruby_1_9_3/test/dl/test_func.rb branches/ruby_1_9_3/version.h Index: ruby_1_9_3/ChangeLog =================================================================== --- ruby_1_9_3/ChangeLog (revision 38505) +++ ruby_1_9_3/ChangeLog (revision 38506) @@ -1,3 +1,29 @@ https://github.com/ruby/ruby/blob/trunk/ruby_1_9_3/ChangeLog#L1 +Thu Dec 20 18:46:17 2012 Naohisa Goto <ngotogenome@g...> + + * test/dl/test_func.rb (test_name_with_block, test_bind, test_qsort1): + call unbind to release the callback closure because maximum number + of callbacks is limited to DL::MAX_CALLBACK (== 5) with pure DL + without Fiddle. + +Thu Dec 20 18:46:17 2012 Naohisa Goto <ngotogenome@g...> + + * ext/dl/lib/dl/func.rb (DL::Function#unbind, #bound?): suppress + NoMethodError when Fiddle is available. [ruby-core:50756] [Bug #7543] + * test/dl/test_func.rb (test_bound*, test_unbind*): tests for the above. + +Thu Dec 20 18:46:17 2012 Naohisa Goto <ngotogenome@g...> + + * ext/dl/lib/dl/func.rb (DL::Function#initialize, DL::Function#bind): + ABI should be set by using CFunc#calltype even when Fiddle is used. + When Fiddle is used and a block is given, name shoud not be ignored. + [ruby-core:50562] [Bug #7514] + + * ext/dl/lib/dl/import.rb (DL::Importer#bind_function): should respect + abi and name when Fiddle is used. + + * test/dl/test_func.rb (test_name_with_block): test for "name" method + with giving a block. + Thu Dec 20 18:43:00 2012 Naohisa Goto <ngotogenome@g...> * ext/fiddle/extconf.rb, ext/fiddle/function.c Index: ruby_1_9_3/ext/dl/lib/dl/import.rb =================================================================== --- ruby_1_9_3/ext/dl/lib/dl/import.rb (revision 38505) +++ ruby_1_9_3/ext/dl/lib/dl/import.rb (revision 38506) @@ -231,11 +231,13 @@ module DL https://github.com/ruby/ruby/blob/trunk/ruby_1_9_3/ext/dl/lib/dl/import.rb#L231 def bind_function(name, ctype, argtype, call_type = nil, &block) if DL.fiddle? - closure = Class.new(Fiddle::Closure) { + klass = Function.instance_eval { class_fiddle_closure_cfunc } + abi = Function.instance_eval { call_type_to_abi(call_type) } + closure = Class.new(klass) { define_method(:call, block) - }.new(ctype, argtype) + }.new(ctype, argtype, abi, name) - Function.new(closure, argtype) + Function.new(closure, argtype, abi) else f = Function.new(CFunc.new(0, ctype, name, call_type || :cdecl), argtype) f.bind(&block) Index: ruby_1_9_3/ext/dl/lib/dl/func.rb =================================================================== --- ruby_1_9_3/ext/dl/lib/dl/func.rb (revision 38505) +++ ruby_1_9_3/ext/dl/lib/dl/func.rb (revision 38506) @@ -11,13 +11,50 @@ module DL https://github.com/ruby/ruby/blob/trunk/ruby_1_9_3/ext/dl/lib/dl/func.rb#L11 include DL include ValueUtil + if DL.fiddle? + # :stopdoc: + CALL_TYPE_TO_ABI = Hash.new { |h, k| + raise RuntimeError, "unsupported call type: #{k}" + }.merge({ :stdcall => + (Fiddle::Function::STDCALL rescue Fiddle::Function::DEFAULT), + :cdecl => Fiddle::Function::DEFAULT, + nil => Fiddle::Function::DEFAULT + }).freeze + private_constant :CALL_TYPE_TO_ABI + # :startdoc: + + def self.call_type_to_abi(call_type) # :nodoc: + CALL_TYPE_TO_ABI[call_type] + end + private_class_method :call_type_to_abi + + class FiddleClosureCFunc < Fiddle::Closure # :nodoc: all + def initialize ctype, arg, abi, name + @name = name + super(ctype, arg, abi) + end + def name + @name + end + def ptr + to_i + end + end + private_constant :FiddleClosureCFunc + + def self.class_fiddle_closure_cfunc # :nodoc: + FiddleClosureCFunc + end + private_class_method :class_fiddle_closure_cfunc + end + def initialize cfunc, argtypes, abi = nil, &block if DL.fiddle? - abi ||= Fiddle::Function::DEFAULT + abi ||= CALL_TYPE_TO_ABI[(cfunc.calltype rescue nil)] if block_given? - @cfunc = Class.new(Fiddle::Closure) { + @cfunc = Class.new(FiddleClosureCFunc) { define_method(:call, block) - }.new(cfunc.ctype, argtypes) + }.new(cfunc.ctype, argtypes, abi, cfunc.name) else @cfunc = cfunc end @@ -76,16 +113,16 @@ module DL https://github.com/ruby/ruby/blob/trunk/ruby_1_9_3/ext/dl/lib/dl/func.rb#L113 def bind(&block) if DL.fiddle? - @cfunc = Class.new(Fiddle::Closure) { - def initialize ctype, args, block - super(ctype, args) + @cfunc = Class.new(FiddleClosureCFunc) { + def initialize ctype, args, abi, name, block + super(ctype, args, abi, name) @block = block end def call *args @block.call(*args) end - }.new(@cfunc.ctype, @args, block) + }.new(@cfunc.ctype, @args, abi, name, block) @ptr = @cfunc return nil else @@ -120,6 +157,25 @@ module DL https://github.com/ruby/ruby/blob/trunk/ruby_1_9_3/ext/dl/lib/dl/func.rb#L157 end def unbind() + if DL.fiddle? then + if @cfunc.kind_of?(Fiddle::Closure) and @cfunc.ptr != 0 then + call_type = case abi + when CALL_TYPE_TO_ABI[nil] + nil + when CALL_TYPE_TO_ABI[:stdcall] + :stdcall + else + raise(RuntimeError, "unsupported abi: #{abi}") + end + @cfunc = CFunc.new(0, @cfunc.ctype, name, call_type) + return 0 + elsif @cfunc.ptr != 0 then + @cfunc.ptr = 0 + return 0 + else + return nil + end + end if( @cfunc.ptr != 0 ) case @cfunc.calltype when :cdecl Index: ruby_1_9_3/version.h =================================================================== --- ruby_1_9_3/version.h (revision 38505) +++ ruby_1_9_3/version.h (revision 38506) @@ -1,5 +1,5 @@ https://github.com/ruby/ruby/blob/trunk/ruby_1_9_3/version.h#L1 #define RUBY_VERSION "1.9.3" -#define RUBY_PATCHLEVEL 352 +#define RUBY_PATCHLEVEL 353 #define RUBY_RELEASE_DATE "2012-12-20" #define RUBY_RELEASE_YEAR 2012 Index: ruby_1_9_3/test/dl/test_func.rb =================================================================== --- ruby_1_9_3/test/dl/test_func.rb (revision 38505) +++ ruby_1_9_3/test/dl/test_func.rb (revision 38506) @@ -9,12 +9,69 @@ module DL https://github.com/ruby/ruby/blob/trunk/ruby_1_9_3/test/dl/test_func.rb#L9 assert_equal 'strcpy', f.name end - def test_bind + def test_name_with_block + begin + cb = Function.new(CFunc.new(0, TYPE_INT, '<callback>qsort'), + [TYPE_VOIDP, TYPE_VOIDP]){|x,y| CPtr.new(x)[0] <=> CPtr.new(y)[0]} + assert_equal('<callback>qsort', cb.name) + ensure + cb.unbind if cb # max number of callbacks is limited to MAX_CALLBACK + end + end + + def test_bound + f = Function.new(CFunc.new(0, TYPE_INT, 'test'), [TYPE_INT, TYPE_INT]) + assert_equal false, f.bound? + begin + f.bind { |x,y| x + y } + assert_equal true, f.bound? + ensure + f.unbind # max number of callbacks is limited to MAX_CALLBACK + end + end + + def test_bound_for_callback_closure + begin + f = Function.new(CFunc.new(0, TYPE_INT, 'test'), + [TYPE_INT, TYPE_INT]) { |x,y| x + y } + assert_equal true, f.bound? + ensure + f.unbind if f # max number of callbacks is limited to MAX_CALLBACK + end + end + + def test_unbind f = Function.new(CFunc.new(0, TYPE_INT, 'test'), [TYPE_INT, TYPE_INT]) - assert_nothing_raised { + begin f.bind { |x, y| x + y } - } - assert_equal 579, f.call(123, 456) + assert_nothing_raised { f.unbind } + assert_equal false, f.bound? + # unbind() after unbind() should not raise error + assert_nothing_raised { f.unbind } + ensure + f.unbind # max number of callbacks is limited to MAX_CALLBACK + end + end + + def test_unbind_normal_function + f = Function.new(CFunc.new(@libc['strcpy'], TYPE_VOIDP, 'strcpy'), + [TYPE_VOIDP, TYPE_VOIDP]) + assert_nothing_raised { f.unbind } + assert_equal false, f.bound? + # unbind() after unbind() should not raise error + assert_nothing_raised { f.unbind } + end + + def test_bind + f = Function.new(CFunc.new(0, TYPE_INT, 'test'), [TYPE_INT, TYPE_INT]) + begin + assert_nothing_raised { + f.bind { |x, y| x + y } + } + assert_equal 579, f.call(123, 456) + ensure + f.unbind # max number of callbacks is limited to MAX_CALLBACK + end end def test_to_i @@ -96,18 +153,22 @@ module DL https://github.com/ruby/ruby/blob/trunk/ruby_1_9_3/test/dl/test_func.rb#L153 end def test_qsort1() - cb = Function.new(CFunc.new(0, TYPE_INT, '<callback>qsort'), - [TYPE_VOIDP, TYPE_VOIDP]){|x,y| CPtr.new(x)[0] <=> CPtr.new(y)[0]} - qsort = Function.new(CFunc.new(@libc['qsort'], TYPE_VOID, 'qsort'), - [TYPE_VOIDP, TYPE_INT, TYPE_INT, TYPE_VOIDP]) - buff = "9341" - qsort.call(buff, buff.size, 1, cb) - assert_equal("1349", buff) - - bug4929 = '[ruby-core:37395]' - buff = "9341" - EnvUtil.under_gc_stress {qsort.call(buff, buff.size, 1, cb)} - assert_equal("1349", buff, bug4929) + begin + cb = Function.new(CFunc.new(0, TYPE_INT, '<callback>qsort'), + [TYPE_VOIDP, TYPE_VOIDP]){|x,y| CPtr.new(x)[0] <=> CPtr.new(y)[0]} + qsort = Function.new(CFunc.new(@libc['qsort'], TYPE_VOID, 'qsort'), + [TYPE_VOIDP, TYPE_INT, TYPE_INT, TYPE_VOIDP]) + buff = "9341" + qsort.call(buff, buff.size, 1, cb) + assert_equal("1349", buff) + + bug4929 = '[ruby-core:37395]' + buff = "9341" + EnvUtil.under_gc_stress {qsort.call(buff, buff.size, 1, cb)} + assert_equal("1349", buff, bug4929) + ensure + cb.unbind if cb # max number of callbacks is limited to MAX_CALLBACK + end end def test_qsort2() Property changes on: ruby_1_9_3/test/dl ___________________________________________________________________ Modified: svn:mergeinfo Merged /trunk/test/dl:r38324 Property changes on: ruby_1_9_3 ___________________________________________________________________ Modified: svn:mergeinfo Merged /trunk:r38202,38238,38324,38326 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/