mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	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. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_9_3@38506 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
		
							parent
							
								
									3912b7f29d
								
							
						
					
					
						commit
						74bca55da9
					
				
					 5 changed files with 171 additions and 26 deletions
				
			
		
							
								
								
									
										26
									
								
								ChangeLog
									
										
									
									
									
								
							
							
						
						
									
										26
									
								
								ChangeLog
									
										
									
									
									
								
							|  | @ -1,3 +1,29 @@ | |||
| Thu Dec 20 18:46:17 2012  Naohisa Goto  <ngotogenome@gmail.com> | ||||
| 
 | ||||
| 	* 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@gmail.com> | ||||
| 
 | ||||
| 	* 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@gmail.com> | ||||
| 
 | ||||
| 	* 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@gmail.com> | ||||
| 
 | ||||
| 	* ext/fiddle/extconf.rb, ext/fiddle/function.c | ||||
|  |  | |||
|  | @ -11,13 +11,50 @@ module DL | |||
|     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 | |||
| 
 | ||||
|     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 | |||
|     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 | ||||
|  |  | |||
|  | @ -231,11 +231,13 @@ module DL | |||
| 
 | ||||
|     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) | ||||
|  |  | |||
|  | @ -9,12 +9,69 @@ module DL | |||
|       assert_equal 'strcpy', f.name | ||||
|     end | ||||
| 
 | ||||
|     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]) | ||||
|       begin | ||||
|         f.bind { |x, y| x + y } | ||||
|         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,6 +153,7 @@ module DL | |||
|     end | ||||
| 
 | ||||
|     def test_qsort1() | ||||
|       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'), | ||||
|  | @ -108,6 +166,9 @@ module DL | |||
|         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() | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| #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 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 usa
						usa