-
Notifications
You must be signed in to change notification settings - Fork 0
Functions with multiple signatures
This technique may be useful if a native function that you are trying to attach has multiple signatures. For example, last argument in Win32 API function SendMessage (lParam) can be either :long or :pointer. You cannot directly tell FFI that this native function can be called with different types of arguments, so you need to attach this function twice with different names and signatures, and then write convenience method to check argument type and route call to attached function with appropriate signature:
require 'ffi' module Win extend FFI::Library ffi_lib 'user32' ffi_convention :stdcall attach_function :SendMessageLong, :SendMessage, [:ulong, :uint, :uint, :long], :int attach_function :SendMessagePointer, :SendMessage, [:ulong, :uint, :uint, :pointer], :int def SendMessage(handle, msg, w_param, l_param) case l_param when Fixnum SendMessageLong(handle, msg, w_param, l_param) else SendMessagePointer(handle, msg, w_param, l_param) end end end
Type checking can be as elaborate as you want to. In the example above I only do light checking, routing calls with FixNum lParam to SendMessageLong and throwing everything else to pointer-typed SendMessagePointer. You can, for example, try to make sure that lParam quacks like :pointer, before routing call to SendMessagePointer. One of the ways to do it is to check if lParam responds to :address (key interface of any FFI::Pointer subclass or any custom pointer class)