Permalink
Browse files

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
  • Loading branch information...
1 parent 3912b7f commit 74bca55da9e509592bd04bc785b6eb86082f8cfe @unak unak committed Dec 20, 2012
Showing with 171 additions and 26 deletions.
  1. +26 −0 ChangeLog
  2. +63 −7 ext/dl/lib/dl/func.rb
  3. +5 −3 ext/dl/lib/dl/import.rb
  4. +76 −15 test/dl/test_func.rb
  5. +1 −1 version.h
View
@@ -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
View
@@ -11,13 +11,50 @@ class Function < parent
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 @@ def wrap_result(r)
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 @@ def call *args
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
View
@@ -231,11 +231,13 @@ def import_function(name, ctype, argtype, call_type = nil)
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)
View
@@ -9,12 +9,69 @@ def test_name
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_nothing_raised {
+ 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_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 @@ def test_strtod()
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)
+ 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)
+ 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()
View
@@ -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

0 comments on commit 74bca55

Please sign in to comment.