From f1841f43eb9d7ec45bcbee7f70abae77d999f76d Mon Sep 17 00:00:00 2001 From: ngoto Date: Wed, 5 Dec 2012 03:20:05 +0000 Subject: * 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/trunk@38202 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 13 +++++++++++++ ext/dl/lib/dl/func.rb | 46 +++++++++++++++++++++++++++++++++++++++------- ext/dl/lib/dl/import.rb | 8 +++++--- test/dl/test_func.rb | 6 ++++++ 4 files changed, 63 insertions(+), 10 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7d4656f197..53d58ddda1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +Wed Dec 5 12:17:11 2012 Naohisa Goto + + * 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. + Wed Dec 5 11:55:00 2012 Zachary Scott * doc/shell.rd, doc/shell.rd.ja: Removed stale doc files diff --git a/ext/dl/lib/dl/func.rb b/ext/dl/lib/dl/func.rb index c5d569575c..fd92c119ac 100644 --- a/ext/dl/lib/dl/func.rb +++ b/ext/dl/lib/dl/func.rb @@ -11,13 +11,45 @@ module DL include DL include ValueUtil + if DL.fiddle? + 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 + + def self.call_type_to_abi(call_type) + CALL_TYPE_TO_ABI[call_type] + end + private_class_method :call_type_to_abi + + class FiddleClosureCFunc < Fiddle::Closure + def initialize ctype, arg, abi, name + @name = name + super(ctype, arg, abi) + end + def name + @name + end + end + private_constant :FiddleClosureCFunc + + def self.class_fiddle_closure_cfunc + 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 +108,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) else if( !block ) raise(RuntimeError, "block must be given.") diff --git a/ext/dl/lib/dl/import.rb b/ext/dl/lib/dl/import.rb index 9005153624..6f157ccf28 100644 --- a/ext/dl/lib/dl/import.rb +++ b/ext/dl/lib/dl/import.rb @@ -243,11 +243,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) diff --git a/test/dl/test_func.rb b/test/dl/test_func.rb index 021ea36d25..514ed6c6c2 100644 --- a/test/dl/test_func.rb +++ b/test/dl/test_func.rb @@ -9,6 +9,12 @@ module DL assert_equal 'strcpy', f.name end + def test_name_with_block + cb = Function.new(CFunc.new(0, TYPE_INT, 'qsort'), + [TYPE_VOIDP, TYPE_VOIDP]){|x,y| CPtr.new(x)[0] <=> CPtr.new(y)[0]} + assert_equal('qsort', cb.name) + end + def test_to_i cfunc = CFunc.new(@libc['strcpy'], TYPE_VOIDP, 'strcpy') f = Function.new(cfunc, [TYPE_VOIDP, TYPE_VOIDP]) -- cgit v1.2.3