lib/win/library.rb in win-0.0.3 vs lib/win/library.rb in win-0.0.4

- old
+ new

@@ -1,35 +1,46 @@ require 'ffi' require 'win/extensions' +# Related Windows API functions are grouped by topic and defined in separate namespaces (modules), +# that also contain related constants and convenience methods. For example, Win::DDE module +# contains only functions related to DDE protocol such as DdeInitialize() as well as constants +# such as DMLERR_NO_ERROR, APPCLASS_STANDARD, etc. So if you need only DDE-related functions, +# there is no need to load all the other modules, clogging your namespaces - just require 'win/dde' +# and be done with it. Win is just a top level namespace (container) that holds all the other modules. module Win module Errors # :nodoc: class NotFoundError < NameError # :nodoc: def initialize(name=nil, libs=nil) super %Q[Function #{name ? "'#{name}' ": ""}not found#{libs ? " in #{libs}" : ""}"] end end end + # WIN::Library is a module that extends FFI::Library and is used to connect to Windows API functions + # and wrap them into Ruby methods using 'function' declaration. If you do not see your favorite Windows + # API functions among those already defined, you can easily 'include Win::Library’ into your module + # and declare them using ‘function’ class method (macro) - it does a lot of heavy lifting for you and + # can be customized with options and code blocks to give you reusable API wrapper methods with the exact + # behavior you need. module Library - # API wrapper for Class Win::Library::API mimics Win32::API + # Win::Library::API is a wrapper for callable function API object that mimics Win32::API class API - # The name of the DLL that exports the API function + # The name of the DLL(s) that export this API function attr_reader :dll_name # Ruby namespace (module) where this API function is attached attr_reader :namespace # The name of the function passed to the constructor attr_reader :function_name - # The name of the actual function that is returned by the constructor. - # For example, if you passed 'GetUserName' to the constructor, then the - # effective function name would be either 'GetUserNameA' or 'GetUserNameW'. + # The name of the actual Windows API function. For example, if you passed 'GetUserName' to the + # constructor, then the effective function name would be either 'GetUserNameA' or 'GetUserNameW'. attr_accessor :effective_function_name # The prototype, returned as an array of FFI types attr_reader :prototype @@ -43,10 +54,11 @@ @prototype = prototype @return_type = return_type @dll_name = dll_name end + # Calls underlying CamelCase Windows API function with supplied args def call( *args ) @namespace.send(@function_name.to_sym, *args) end alias_method :[], :call @@ -271,26 +283,29 @@ ## # Defines new method wrappers for Windows API function call: # - Defines method with original (CamelCase) API function name and original signature (matches MSDN description) # - Defines method with snake_case name (converted from CamelCase function name) with enhanced API signature - # When the defined wrapper method is called, it checks the argument count, executes underlying API - # function call and (optionally) transforms the result before returning it. If block is attached to - # method invocation, raw result is yielded to this block before final transformations + # When defined snake_case method is called, it converts the arguments you provided into ones required by + # original API (adding defaults, mute and transitory args as necessary), executes API function call + # and (optionally) transforms the result before returning it. If a block is attached to + # method invocation, raw result is yielded to this block before final transformation take place # - Defines aliases for enhanced method with more Rubyesque names for getters, setters and tests: # GetWindowText -> window_test, SetWindowText -> window_text=, IsZoomed -> zoomed? # - # You may modify default behavior of defined method by providing optional &define_block to def_api. - # If you do so, instead of directly calling API function, defined method just yields callable api - # object, arguments and (optional) runtime block to your &define_block and returns result coming out of it. - # So, &define_block should define all the behavior of defined method. You can use define_block to: + # You may modify default behavior of defined method by providing optional &def_block to function. + # If you do so, snake_case method is defined based on your def_block. It receives callable API + # object for function being defined, arguments and (optional) runtime block with which the method + # will be called. Results coming from &def_block are then transformed and returned. + # So, your &def_block should define all the behavior of defined method. You can use define_block to: # - Change original signature of API function, provide argument defaults, check argument types - # - Pack arguments into strings for [in] or [in/out] parameters that expect a pointer - # - Allocate string buffers for pointers required by API functions [out] parameters + # - Pack arguments into strings/structs for [in] or [in/out] parameters that expect a pointer + # - Allocate buffers/structs for pointers required by API functions [out] parameters # - Unpack [out] and [in/out] parameters returned as pointers # - Explicitly return results of API call that are returned in [out] and [in/out] parameters # - Convert attached runtime blocks into callback functions and stuff them into [in] callback parameters + # - do other stuff that you think is appropriate to make Windows API function behavior more Ruby-like # # Accepts following options: # :dll:: Use this dll instead of default 'user32' # :rename:: Use this name instead of standard (conventional) function name # :alias(es):: Provides additional alias(es) for defined method @@ -393,9 +408,13 @@ # def nonzero_array(*args) args.any?{|arg| arg == 0 } ? args.map{||nil} : args end + ## + # :singleton-method: namespace + # This method is meta-generated when Win::Library module is included into other module/class + # it holds reference to including module for use by Win::Library::API and class methods. end def self.included(klass) klass.extend ClassMethods klass.extend FFI::Library \ No newline at end of file