summaryrefslogtreecommitdiff
path: root/ext/fiddle/function.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/fiddle/function.c')
-rw-r--r--ext/fiddle/function.c264
1 files changed, 0 insertions, 264 deletions
diff --git a/ext/fiddle/function.c b/ext/fiddle/function.c
deleted file mode 100644
index 89239bbb69..0000000000
--- a/ext/fiddle/function.c
+++ /dev/null
@@ -1,264 +0,0 @@
-#include <fiddle.h>
-
-#ifdef PRIsVALUE
-# define RB_OBJ_CLASSNAME(obj) rb_obj_class(obj)
-# define RB_OBJ_STRING(obj) (obj)
-#else
-# define PRIsVALUE "s"
-# define RB_OBJ_CLASSNAME(obj) rb_obj_classname(obj)
-# define RB_OBJ_STRING(obj) StringValueCStr(obj)
-#endif
-
-VALUE cFiddleFunction;
-
-static void
-deallocate(void *p)
-{
- ffi_cif *ptr = p;
- if (ptr->arg_types) xfree(ptr->arg_types);
- xfree(ptr);
-}
-
-static size_t
-function_memsize(const void *p)
-{
- /* const */ffi_cif *ptr = (ffi_cif *)p;
- size_t size = 0;
-
- if (ptr) {
- size += sizeof(*ptr);
-#if !defined(FFI_NO_RAW_API) || !FFI_NO_RAW_API
- size += ffi_raw_size(ptr);
-#endif
- }
- return size;
-}
-
-const rb_data_type_t function_data_type = {
- "fiddle/function",
- {0, deallocate, function_memsize,},
-};
-
-static VALUE
-allocate(VALUE klass)
-{
- ffi_cif * cif;
-
- return TypedData_Make_Struct(klass, ffi_cif, &function_data_type, cif);
-}
-
-VALUE
-rb_fiddle_new_function(VALUE address, VALUE arg_types, VALUE ret_type)
-{
- VALUE argv[3];
-
- argv[0] = address;
- argv[1] = arg_types;
- argv[2] = ret_type;
-
- return rb_class_new_instance(3, argv, cFiddleFunction);
-}
-
-static int
-parse_keyword_arg_i(VALUE key, VALUE value, VALUE self)
-{
- if (key == ID2SYM(rb_intern("name"))) {
- rb_iv_set(self, "@name", value);
- } else {
- rb_raise(rb_eArgError, "unknown keyword: %"PRIsVALUE,
- RB_OBJ_STRING(key));
- }
- return ST_CONTINUE;
-}
-
-static VALUE
-initialize(int argc, VALUE argv[], VALUE self)
-{
- ffi_cif * cif;
- ffi_type **arg_types;
- ffi_status result;
- VALUE ptr, args, ret_type, abi, kwds;
- int i;
-
- rb_scan_args(argc, argv, "31:", &ptr, &args, &ret_type, &abi, &kwds);
- if(NIL_P(abi)) abi = INT2NUM(FFI_DEFAULT_ABI);
-
- Check_Type(args, T_ARRAY);
-
- rb_iv_set(self, "@ptr", ptr);
- rb_iv_set(self, "@args", args);
- rb_iv_set(self, "@return_type", ret_type);
- rb_iv_set(self, "@abi", abi);
-
- if (!NIL_P(kwds)) rb_hash_foreach(kwds, parse_keyword_arg_i, self);
-
- TypedData_Get_Struct(self, ffi_cif, &function_data_type, cif);
-
- arg_types = xcalloc(RARRAY_LEN(args) + 1, sizeof(ffi_type *));
-
- for (i = 0; i < RARRAY_LEN(args); i++) {
- int type = NUM2INT(RARRAY_PTR(args)[i]);
- arg_types[i] = INT2FFI_TYPE(type);
- }
- arg_types[RARRAY_LEN(args)] = NULL;
-
- result = ffi_prep_cif (
- cif,
- NUM2INT(abi),
- RARRAY_LENINT(args),
- INT2FFI_TYPE(NUM2INT(ret_type)),
- arg_types);
-
- if (result)
- rb_raise(rb_eRuntimeError, "error creating CIF %d", result);
-
- return self;
-}
-
-static VALUE
-function_call(int argc, VALUE argv[], VALUE self)
-{
- ffi_cif * cif;
- fiddle_generic retval;
- fiddle_generic *generic_args;
- void **values;
- VALUE cfunc, types, cPointer;
- int i;
-
- cfunc = rb_iv_get(self, "@ptr");
- types = rb_iv_get(self, "@args");
- cPointer = rb_const_get(mFiddle, rb_intern("Pointer"));
-
- if(argc != RARRAY_LENINT(types)) {
- rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
- argc, RARRAY_LENINT(types));
- }
-
- TypedData_Get_Struct(self, ffi_cif, &function_data_type, cif);
-
- if (rb_safe_level() >= 1) {
- for (i = 0; i < argc; i++) {
- VALUE src = argv[i];
- if (OBJ_TAINTED(src)) {
- rb_raise(rb_eSecurityError, "tainted parameter not allowed");
- }
- }
- }
-
- values = xcalloc((size_t)argc + 1, (size_t)sizeof(void *));
- generic_args = xcalloc((size_t)argc, (size_t)sizeof(fiddle_generic));
-
- for (i = 0; i < argc; i++) {
- VALUE type = RARRAY_PTR(types)[i];
- VALUE src = argv[i];
-
- if(NUM2INT(type) == TYPE_VOIDP) {
- if(NIL_P(src)) {
- src = INT2NUM(0);
- } else if(cPointer != CLASS_OF(src)) {
- src = rb_funcall(cPointer, rb_intern("[]"), 1, src);
- }
- src = rb_Integer(src);
- }
-
- VALUE2GENERIC(NUM2INT(type), src, &generic_args[i]);
- values[i] = (void *)&generic_args[i];
- }
- values[argc] = NULL;
-
- ffi_call(cif, NUM2PTR(rb_Integer(cfunc)), &retval, values);
-
- rb_funcall(mFiddle, rb_intern("last_error="), 1, INT2NUM(errno));
-#if defined(_WIN32)
- rb_funcall(mFiddle, rb_intern("win32_last_error="), 1, INT2NUM(errno));
-#endif
-
- xfree(values);
- xfree(generic_args);
-
- return GENERIC2VALUE(rb_iv_get(self, "@return_type"), retval);
-}
-
-void
-Init_fiddle_function(void)
-{
- /*
- * Document-class: Fiddle::Function
- *
- * == Description
- *
- * A representation of a C function
- *
- * == Examples
- *
- * === 'strcpy'
- *
- * @libc = Fiddle.dlopen "/lib/libc.so.6"
- * #=> #<Fiddle::Handle:0x00000001d7a8d8>
- * f = Fiddle::Function.new(
- * @libc['strcpy'],
- * [Fiddle::TYPE_VOIDP, Fiddle::TYPE_VOIDP],
- * Fiddle::TYPE_VOIDP)
- * #=> #<Fiddle::Function:0x00000001d8ee00>
- * buff = "000"
- * #=> "000"
- * str = f.call(buff, "123")
- * #=> #<Fiddle::Pointer:0x00000001d0c380 ptr=0x000000018a21b8 size=0 free=0x00000000000000>
- * str.to_s
- * => "123"
- *
- * === ABI check
- *
- * @libc = DL.dlopen "/lib/libc.so.6"
- * #=> #<Fiddle::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 HAVE_CONST_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 Fiddle::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: */