summaryrefslogtreecommitdiff
path: root/ext/dl/lib/dl/callback.rb
blob: 53da888d9d95e0dcb76e526bc1018f41bf5253db (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
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)
    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
  end

  def set_cdecl_callback(ty, argc, &cbp)
    set_callback_internal(CdeclCallbackProcs, CdeclCallbackAddrs, argc, ty, &cbp)
  end

  def set_stdcall_callback(ty, argc, &cbp)
    set_callback_internal(StdcallCallbackProcs, StdcallCallbackAddrs, argc, ty, DL::Function::STDCALL, &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
  end

  def remove_cdecl_callback(addr, ctype = nil)
    remove_callback_internal(CdeclCallbackProcs, CdeclCallbackAddrs, addr, ctype)
  end

  def remove_stdcall_callback(addr, ctype = nil)
    remove_callback_internal(StdcallCallbackProcs, StdcallCallbackAddrs, addr, ctype)
  end

  alias set_callback set_cdecl_callback
  alias remove_callback remove_cdecl_callback
end