summaryrefslogtreecommitdiff
path: root/ext/fiddle
diff options
context:
space:
mode:
Diffstat (limited to 'ext/fiddle')
-rw-r--r--ext/fiddle/closure.c44
-rw-r--r--ext/fiddle/fiddle.c56
-rw-r--r--ext/fiddle/function.c63
-rw-r--r--ext/fiddle/lib/fiddle.rb7
-rw-r--r--ext/fiddle/lib/fiddle/closure.rb31
-rw-r--r--ext/fiddle/lib/fiddle/function.rb1
6 files changed, 202 insertions, 0 deletions
diff --git a/ext/fiddle/closure.c b/ext/fiddle/closure.c
index 48520997bc..542d978395 100644
--- a/ext/fiddle/closure.c
+++ b/ext/fiddle/closure.c
@@ -224,11 +224,55 @@ to_i(VALUE self)
void
Init_fiddle_closure()
{
+#if 0
+ mFiddle = rb_define_module("Fiddle"); /* let rdoc know about mFiddle */
+#endif
+
+ /*
+ * Document-class: Fiddle::Closure
+ *
+ * == Description
+ *
+ * An FFI closure wrapper, for handling callbacks.
+ *
+ * == Example
+ *
+ * closure = Class.new(Fiddle::Closure) {
+ * def call
+ * 10
+ * end
+ * }.new(Fiddle::TYPE_INT, [])
+ * => #<#<Class:0x0000000150d308>:0x0000000150d240>
+ * func = Fiddle::Function.new(closure, [], Fiddle::TYPE_INT)
+ * => #<Fiddle::Function:0x00000001516e58>
+ * func.call
+ * => 10
+ */
cFiddleClosure = rb_define_class_under(mFiddle, "Closure", rb_cObject);
rb_define_alloc_func(cFiddleClosure, allocate);
+ /*
+ * Document-method: new
+ *
+ * call-seq: new(ret, *args, abi = Fiddle::DEFAULT)
+ *
+ * Construct a new Closure object.
+ *
+ * * +ret+ is the C type to be returned
+ * * +args+ are passed the callback
+ * * +abi+ is the abi of the closure
+ *
+ * If there is an error in preparing the ffi_cif or ffi_prep_closure,
+ * then a RuntimeError will be raised.
+ */
rb_define_method(cFiddleClosure, "initialize", initialize, -1);
+
+ /*
+ * Document-method: to_i
+ *
+ * Returns the memory address for this closure
+ */
rb_define_method(cFiddleClosure, "to_i", to_i, 0);
}
/* vim: set noet sw=4 sts=4 */
diff --git a/ext/fiddle/fiddle.c b/ext/fiddle/fiddle.c
index 2580ac0e53..08fdb4484d 100644
--- a/ext/fiddle/fiddle.c
+++ b/ext/fiddle/fiddle.c
@@ -4,20 +4,76 @@ VALUE mFiddle;
void Init_fiddle()
{
+ /*
+ * Document-module: Fiddle
+ *
+ * == Description
+ *
+ * A libffi wrapper.
+ *
+ */
mFiddle = rb_define_module("Fiddle");
+ /* Document-const: TYPE_VOID
+ *
+ * C type - void
+ */
rb_define_const(mFiddle, "TYPE_VOID", INT2NUM(TYPE_VOID));
+
+ /* Document-const: TYPE_VOIDP
+ *
+ * C type - void*
+ */
rb_define_const(mFiddle, "TYPE_VOIDP", INT2NUM(TYPE_VOIDP));
+
+ /* Document-const: TYPE_CHAR
+ *
+ * C type - char
+ */
rb_define_const(mFiddle, "TYPE_CHAR", INT2NUM(TYPE_CHAR));
+
+ /* Document-const: TYPE_SHORT
+ *
+ * C type - short
+ */
rb_define_const(mFiddle, "TYPE_SHORT", INT2NUM(TYPE_SHORT));
+
+ /* Document-const: TYPE_INT
+ *
+ * C type - int
+ */
rb_define_const(mFiddle, "TYPE_INT", INT2NUM(TYPE_INT));
+
+ /* Document-const: TYPE_LONG
+ *
+ * C type - long
+ */
rb_define_const(mFiddle, "TYPE_LONG", INT2NUM(TYPE_LONG));
+
#if HAVE_LONG_LONG
+ /* Document-const: TYPE_LONG_LONG
+ *
+ * C type - long long
+ */
rb_define_const(mFiddle, "TYPE_LONG_LONG", INT2NUM(TYPE_LONG_LONG));
#endif
+
+ /* Document-const: TYPE_FLOAT
+ *
+ * C type - float
+ */
rb_define_const(mFiddle, "TYPE_FLOAT", INT2NUM(TYPE_FLOAT));
+
+ /* Document-const: TYPE_DOUBLE
+ *
+ * C type - double
+ */
rb_define_const(mFiddle, "TYPE_DOUBLE", INT2NUM(TYPE_DOUBLE));
+ /* Document-const: WINDOWS
+ *
+ * Returns a boolean regarding whether the host is WIN32
+ */
#if defined(_WIN32)
rb_define_const(mFiddle, "WINDOWS", Qtrue);
#else
diff --git a/ext/fiddle/function.c b/ext/fiddle/function.c
index 911c9b80fc..6e8909991a 100644
--- a/ext/fiddle/function.c
+++ b/ext/fiddle/function.c
@@ -138,17 +138,80 @@ function_call(int argc, VALUE argv[], VALUE self)
void
Init_fiddle_function(void)
{
+ /*
+ * Document-class: Fiddle::Function
+ *
+ * == Description
+ *
+ * A representation of a C function
+ *
+ * == Examples
+ *
+ * === 'strcpy'
+ *
+ * @libc = DL.dlopen "/lib/libc.so.6"
+ * => #<DL::Handle:0x00000001d7a8d8>
+ * f = Fiddle::Function.new(@libc['strcpy'], [TYPE_VOIDP, TYPE_VOIDP], TYPE_VOIDP)
+ * => #<Fiddle::Function:0x00000001d8ee00>
+ * buff = "000"
+ * => "000"
+ * str = f.call(buff, "123")
+ * => #<DL::CPtr:0x00000001d0c380 ptr=0x000000018a21b8 size=0 free=0x00000000000000>
+ * str.to_s
+ * => "123"
+ *
+ * === ABI check
+ *
+ * @libc = DL.dlopen "/lib/libc.so.6"
+ * => #<DL::Handle:0x00000001d7a8d8>
+ * f = Fiddle::Function.new(@libc['strcpy'], [TYPE_VOIDP, TYPE_VOIDP], TYPE_VOIDP)
+ * => #<Fiddle::Function:0x00000001d8ee00>
+ * f.abi == Fiddle::Function::DEFAULT
+ * => true
+ */
cFiddleFunction = rb_define_class_under(mFiddle, "Function", rb_cObject);
+ /*
+ * Document-const: DEFAULT
+ *
+ * Default ABI
+ *
+ */
rb_define_const(cFiddleFunction, "DEFAULT", INT2NUM(FFI_DEFAULT_ABI));
#ifdef FFI_STDCALL
+ /*
+ * Document-const: STDCALL
+ *
+ * FFI implementation of WIN32 stdcall convention
+ *
+ */
rb_define_const(cFiddleFunction, "STDCALL", INT2NUM(FFI_STDCALL));
#endif
rb_define_alloc_func(cFiddleFunction, allocate);
+ /*
+ * Document-method: call
+ *
+ * Calls the constructed Function, with +args+
+ *
+ * For an example see Fiddle::Function
+ *
+ */
rb_define_method(cFiddleFunction, "call", function_call, -1);
+
+ /*
+ * Document-method: new
+ * call-seq: new(ptr, *args, ret_type, abi = DEFAULT)
+ *
+ * Constructs a Function object.
+ * * +ptr+ is a referenced function, of a DL::Handle
+ * * +args+ is an Array of arguments, passed to the +ptr+ function
+ * * +ret_type+ is the return type of the function
+ * * +abi+ is the ABI of the function
+ *
+ */
rb_define_method(cFiddleFunction, "initialize", initialize, -1);
}
/* vim: set noet sws=4 sw=4: */
diff --git a/ext/fiddle/lib/fiddle.rb b/ext/fiddle/lib/fiddle.rb
index 8b8c069b03..7d55a1f7ad 100644
--- a/ext/fiddle/lib/fiddle.rb
+++ b/ext/fiddle/lib/fiddle.rb
@@ -4,22 +4,29 @@ require 'fiddle/closure'
require 'dl' unless Object.const_defined?(:DL)
module Fiddle
+
+ # A reference to DL::CPtr
Pointer = DL::CPtr
if WINDOWS
+ # Returns the last win32 +Error+ of the current executing +Thread+ or nil
+ # if none
def self.win32_last_error
Thread.current[:__FIDDLE_WIN32_LAST_ERROR__]
end
+ # Sets the last win32 +Error+ of the current executing +Thread+ to +error+
def self.win32_last_error= error
Thread.current[:__FIDDLE_WIN32_LAST_ERROR__] = error
end
end
+ # Returns the last +Error+ of the current executing +Thread+ or nil if none
def self.last_error
Thread.current[:__FIDDLE_LAST_ERROR__]
end
+ # Sets the last +Error+ of the current executing +Thread+ to +error+
def self.last_error= error
Thread.current[:__DL2_LAST_ERROR__] = error
Thread.current[:__FIDDLE_LAST_ERROR__] = error
diff --git a/ext/fiddle/lib/fiddle/closure.rb b/ext/fiddle/lib/fiddle/closure.rb
index dc2b7a65be..beb90ecbe5 100644
--- a/ext/fiddle/lib/fiddle/closure.rb
+++ b/ext/fiddle/lib/fiddle/closure.rb
@@ -1,14 +1,45 @@
module Fiddle
class Closure
+
+ # the C type of the return of the FFI closure
attr_reader :ctype
+
+ # arguments of the FFI closure
attr_reader :args
+ # Extends Fiddle::Closure to allow for building the closure in a block
class BlockCaller < Fiddle::Closure
+
+ # == Description
+ #
+ # Construct a new BlockCaller object.
+ #
+ # * +ctype+ is the C type to be returned
+ # * +args+ are passed the callback
+ # * +abi+ is the abi of the closure
+ #
+ # If there is an error in preparing the +ffi_cif+ or +ffi_prep_closure+,
+ # then a RuntimeError will be raised.
+ #
+ # == Example
+ #
+ # include Fiddle
+ #
+ # cb = Closure::BlockCaller.new(TYPE_INT, [TYPE_INT]) do |one|
+ # one
+ # end
+ #
+ # func = Function.new(cb, [TYPE_INT], TYPE_INT)
+ #
def initialize ctype, args, abi = Fiddle::Function::DEFAULT, &block
super(ctype, args, abi)
@block = block
end
+ # Calls the constructed BlockCaller, with +args+
+ #
+ # For an example see Fiddle::Closure::BlockCaller.new
+ #
def call *args
@block.call(*args)
end
diff --git a/ext/fiddle/lib/fiddle/function.rb b/ext/fiddle/lib/fiddle/function.rb
index 7b9e735874..1657682498 100644
--- a/ext/fiddle/lib/fiddle/function.rb
+++ b/ext/fiddle/lib/fiddle/function.rb
@@ -1,5 +1,6 @@
module Fiddle
class Function
+ # The ABI of the Function.
attr_reader :abi
end
end