From 59e4e93ef7b6b7f1536e3c56374cc6b8d74b5d28 Mon Sep 17 00:00:00 2001 From: naruse Date: Thu, 25 Feb 2010 22:49:20 +0000 Subject: * ext/dl: revert dl with libffi because it can't run on mswin now. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@26764 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ext/dl/lib/dl/callback.rb | 51 ++++++++++++++++++++++++++----------- ext/dl/lib/dl/closure.rb | 19 -------------- ext/dl/lib/dl/func.rb | 64 ++++++++++++++++++++++++++++++----------------- ext/dl/lib/dl/import.rb | 9 +++---- ext/dl/lib/dl/value.rb | 11 +++++++- 5 files changed, 91 insertions(+), 63 deletions(-) delete mode 100644 ext/dl/lib/dl/closure.rb (limited to 'ext/dl/lib') diff --git a/ext/dl/lib/dl/callback.rb b/ext/dl/lib/dl/callback.rb index 53da888d9d..c8daaf6322 100644 --- a/ext/dl/lib/dl/callback.rb +++ b/ext/dl/lib/dl/callback.rb @@ -1,21 +1,26 @@ require 'dl' -require 'dl/closure' require 'thread' module DL SEM = Mutex.new - CdeclCallbackProcs = {} - CdeclCallbackAddrs = {} - - def set_callback_internal(proc_entry, addr_entry, argc, ty, abi = DL::Function::DEFAULT, &cbp) + def set_callback_internal(proc_entry, addr_entry, argc, ty, &cbp) if( argc < 0 ) raise(ArgumentError, "arity should not be less than 0.") end - - closure = DL::Closure::BlockCaller.new(ty, [TYPE_VOIDP] * argc, abi, &cbp) - proc_entry[closure.to_i] = closure - closure.to_i + addr = nil + SEM.synchronize{ + ary = proc_entry[ty] + (0...MAX_CALLBACK).each{|n| + idx = (n * DLSTACK_SIZE) + argc + if( ary[idx].nil? ) + ary[idx] = cbp + addr = addr_entry[ty][idx] + break + end + } + } + addr end def set_cdecl_callback(ty, argc, &cbp) @@ -23,14 +28,32 @@ module DL end def set_stdcall_callback(ty, argc, &cbp) - set_callback_internal(StdcallCallbackProcs, StdcallCallbackAddrs, argc, ty, DL::Function::STDCALL, &cbp) + set_callback_internal(StdcallCallbackProcs, StdcallCallbackAddrs, argc, ty, &cbp) end def remove_callback_internal(proc_entry, addr_entry, addr, ctype = nil) - addr = addr.to_i - return false unless proc_entry.key?(addr) - proc_entry.delete(addr) - true + index = nil + if( ctype ) + addr_entry[ctype].each_with_index{|xaddr, idx| + if( xaddr == addr ) + index = idx + end + } + else + addr_entry.each{|ty,entry| + entry.each_with_index{|xaddr, idx| + if( xaddr == addr ) + index = idx + end + } + } + end + if( index and proc_entry[ctype][index] ) + proc_entry[ctype][index] = nil + return true + else + return false + end end def remove_cdecl_callback(addr, ctype = nil) diff --git a/ext/dl/lib/dl/closure.rb b/ext/dl/lib/dl/closure.rb deleted file mode 100644 index eca941dfbc..0000000000 --- a/ext/dl/lib/dl/closure.rb +++ /dev/null @@ -1,19 +0,0 @@ -require 'dl' - -module DL - class Closure - attr_reader :ctype - attr_reader :args - - class BlockCaller < DL::Closure - def initialize ctype, args, abi = DL::Function::DEFAULT, &block - super(ctype, args, abi) - @block = block - end - - def call *args - @block.call(*args) - end - end - end -end diff --git a/ext/dl/lib/dl/func.rb b/ext/dl/lib/dl/func.rb index c5a2dda355..7a8b62e325 100644 --- a/ext/dl/lib/dl/func.rb +++ b/ext/dl/lib/dl/func.rb @@ -1,26 +1,26 @@ require 'dl' -require 'dl/closure' require 'dl/callback' require 'dl/stack' require 'dl/value' require 'thread' module DL - class Function < DL::Method + class Function include DL include ValueUtil - def initialize cfunc, argtypes, abi = DEFAULT, &block - if block_given? - @cfunc = Class.new(DL::Closure) { - define_method(:call, block) - }.new(cfunc.ctype, argtypes) + def initialize(cfunc, argtypes, &proc) + @cfunc = cfunc + @stack = Stack.new(argtypes.collect{|ty| ty.abs}) + if( @cfunc.ctype < 0 ) + @cfunc.ctype = @cfunc.ctype.abs + @unsigned = true else - @cfunc = cfunc + @unsigned = false + end + if( proc ) + bind(&proc) end - - @args = argtypes - super(@cfunc, @args.reject { |x| x == TYPE_VOID }, cfunc.ctype, abi) end def to_i() @@ -32,10 +32,11 @@ module DL end def call(*args, &block) - if block_given? - args.find { |a| DL::Function === a }.bind_at_call(&block) - end - super + funcs = [] + args = wrap_args(args, @stack.types, funcs, &block) + r = @cfunc.call(@stack.pack(args)) + funcs.each{|f| f.unbind_at_call()} + return wrap_result(r) end def wrap_result(r) @@ -51,16 +52,33 @@ module DL end def bind(&block) - @cfunc = Class.new(DL::Closure) { - def initialize ctype, args, block - super(ctype, args) - @block = block + if( !block ) + raise(RuntimeError, "block must be given.") + end + if( @cfunc.ptr == 0 ) + cb = Proc.new{|*args| + ary = @stack.unpack(args) + @stack.types.each_with_index{|ty, idx| + case ty + when TYPE_VOIDP + ary[idx] = CPtr.new(ary[idx]) + end + } + r = block.call(*ary) + wrap_arg(r, @cfunc.ctype, []) + } + case @cfunc.calltype + when :cdecl + @cfunc.ptr = set_cdecl_callback(@cfunc.ctype, @stack.size, &cb) + when :stdcall + @cfunc.ptr = set_stdcall_callback(@cfunc.ctype, @stack.size, &cb) + else + raise(RuntimeError, "unsupported calltype: #{@cfunc.calltype}") end - - def call *args - @block.call(*args) + if( @cfunc.ptr == 0 ) + raise(RuntimeException, "can't bind C function.") end - }.new(@cfunc.ctype, @args, block) + end end def unbind() diff --git a/ext/dl/lib/dl/import.rb b/ext/dl/lib/dl/import.rb index 4c101d0f5c..199354c18e 100644 --- a/ext/dl/lib/dl/import.rb +++ b/ext/dl/lib/dl/import.rb @@ -1,5 +1,4 @@ require 'dl' -require 'dl/closure' require 'dl/func.rb' require 'dl/struct.rb' require 'dl/cparser.rb' @@ -212,11 +211,9 @@ module DL end def bind_function(name, ctype, argtype, call_type = nil, &block) - closure = Class.new(DL::Closure) { - define_method(:call, block) - }.new(ctype, argtype) - - Function.new(closure, argtype) + f = Function.new(CFunc.new(0, ctype, name, call_type || :cdecl), argtype) + f.bind(&block) + f end def create_temp_function(name, ctype, argtype, call_type = nil) diff --git a/ext/dl/lib/dl/value.rb b/ext/dl/lib/dl/value.rb index cc6da6a7fb..56dfcefa32 100644 --- a/ext/dl/lib/dl/value.rb +++ b/ext/dl/lib/dl/value.rb @@ -36,7 +36,16 @@ module DL end end - def wrap_arg(arg, ty, funcs = [], &block) + def wrap_args(args, tys, funcs, &block) + result = [] + tys ||= [] + args.each_with_index{|arg, idx| + result.push(wrap_arg(arg, tys[idx], funcs, &block)) + } + result + end + + def wrap_arg(arg, ty, funcs, &block) funcs ||= [] case arg when nil -- cgit v1.2.3