Module: WinWindow::AttachLib
Overview
this module exists because I’ve implemented this library for DL, for FFI, and for Win32::API. Getting tired of changing everything everywhere, now it just takes changes to Types, and a few methods (use_lib, attach, callback) to switch to another library.
Constant Summary collapse
- IsWin64 =
:nodoc: all
nil
- Types =
types that FFI recognizes
[:char, :uchar, :int, :uint, :short, :ushort, :long, :ulong, :void, :pointer, :string].inject({}) do |type_hash, type| type_hash[type]=type type_hash end
Class Method Summary collapse
Instance Method Summary collapse
-
#attach(return_type, function_name, *arg_types) ⇒ Object
this takes arguments in the order that they’re given in c/c++ so that signatures look kind of like the source.
-
#callback(callback_type_name, return_type, callback_method_name, *arg_types) ⇒ Object
this takes arguments like #attach, but with a name for the callback’s type on the front.
- #use_lib(lib) ⇒ Object
Class Method Details
.add_type(hash) ⇒ Object
132 133 134 135 136 137 138 139 |
# File 'lib/winwindow.rb', line 132 def self.add_type(hash) hash.each_pair do |key, value| unless Types.key?(value) raise "unrecognized type #{value.inspect}" end Types[key]=Types[value] end end |
.extended(extender) ⇒ Object
69 70 71 72 73 |
# File 'lib/winwindow.rb', line 69 def self.extended(extender) ffi_module=Module.new ffi_module.send(:extend, FFI::Library) extender.send(:instance_variable_set, '@ffi_module', ffi_module) end |
Instance Method Details
#attach(return_type, function_name, *arg_types) ⇒ Object
this takes arguments in the order that they’re given in c/c++ so that signatures look kind of like the source
79 80 81 82 83 84 85 86 87 |
# File 'lib/winwindow.rb', line 79 def attach(return_type, function_name, *arg_types) @ffi_module.attach_function(function_name, arg_types.map{|arg_type| Types[arg_type] }, Types[return_type]) =class << self;self;end ffi_module=@ffi_module .send(:define_method, function_name) do |*args| ffi_module.send(function_name, *args) end nil end |
#callback(callback_type_name, return_type, callback_method_name, *arg_types) ⇒ Object
this takes arguments like #attach, but with a name for the callback’s type on the front.
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
# File 'lib/winwindow.rb', line 89 def callback(callback_type_name, return_type, callback_method_name, *arg_types) Types[callback_type_name]=callback_type_name #@ffi_module.callback(callback_type_name, arg_types.map{|type| Types[type]}, Types[return_type]) # we do not call @ffi_module.callback here, because it is broken. we need to pass the convention ourselves in the options hash. # this is adapted from: http://gist.github.com/256660 ={} types=Types @ffi_module.instance_eval do [:convention] = defined?(@ffi_convention) ? @ffi_convention : :default [:enums] = @ffi_enums if defined?(@ffi_enums) cb = FFI::CallbackInfo.new(find_type(types[return_type]), arg_types.map{|e| find_type(types[e]) }, ) # the below is for ffi < 1.0; @ffi_callbacks goes away in the future. it's ignored by # newer versions of ffi. so no harm in continuing to set it here. @ffi_callbacks = Hash.new unless defined?(@ffi_callbacks) @ffi_callbacks[callback_type_name] = cb # and the below is for newer versions of ffi (1.0.*). of course, @ffi_module.callback # works in newer. at some point I'll drop support for older broken versions and just # use ffi's #callback. typedef cb, callback_type_name end # perform some hideous class_eval'ing to dynamically define the callback method such that it will take a block =class << self;self;end # FFI just takes the block itself. don't need anything fancy here. .class_eval("def #{callback_method_name}(&block) block end def remove_#{callback_method_name}(callback_method) # FFI has no support for removing callbacks? nil end") # don't use define_method as this will be called from an ensure block which segfaults ruby 1.9.1. see http://redmine.ruby-lang.org/issues/show/2728 #metaclass.send(:define_method, "remove_"+callback_method_name.to_s) do |callback_method| # nil #end nil end |
#use_lib(lib) ⇒ Object
74 75 76 77 |
# File 'lib/winwindow.rb', line 74 def use_lib(lib) @ffi_module.ffi_lib lib @ffi_module.ffi_convention :stdcall end |