From 8f8947a260891f265d4f3881f6ebac7fbbc96d7a Mon Sep 17 00:00:00 2001 From: tenderlove Date: Tue, 16 Feb 2010 02:05:46 +0000 Subject: * ext/dl/method.c: Adding DL::Method as a superclass for DL::Function git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@26677 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ext/dl/dl.h | 1 + ext/dl/function.c | 238 ---------------------------------------------- ext/dl/lib/dl/func.rb | 6 +- ext/dl/lib/dl/value.rb | 13 --- ext/dl/method.c | 251 +++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 255 insertions(+), 254 deletions(-) delete mode 100644 ext/dl/function.c create mode 100644 ext/dl/method.c (limited to 'ext') diff --git a/ext/dl/dl.h b/ext/dl/dl.h index da5695d3fa..81c8ee3bd9 100644 --- a/ext/dl/dl.h +++ b/ext/dl/dl.h @@ -136,6 +136,7 @@ extern VALUE rb_mDL; extern VALUE rb_cDLHandle; +extern VALUE rb_cDLCPtr; extern VALUE rb_cDLSymbol; extern VALUE rb_eDLError; extern VALUE rb_eDLTypeError; diff --git a/ext/dl/function.c b/ext/dl/function.c deleted file mode 100644 index 377d2fe054..0000000000 --- a/ext/dl/function.c +++ /dev/null @@ -1,238 +0,0 @@ -/* -*- C -*- - * $Id$ - */ - -#include -#include -#include "dl.h" -#include - -VALUE rb_cDLFunction; - -typedef union -{ - unsigned char uchar; /* ffi_type_uchar */ - signed char schar; /* ffi_type_schar */ - unsigned short ushort; /* ffi_type_sshort */ - signed short sshort; /* ffi_type_ushort */ - unsigned int uint; /* ffi_type_uint */ - signed int sint; /* ffi_type_sint */ - unsigned long ulong; /* ffi_type_ulong */ - signed long slong; /* ffi_type_slong */ - float ffloat; /* ffi_type_float */ - double ddouble; /* ffi_type_double */ -#if HAVE_LONG_LONG - unsigned LONG_LONG long_long; /* ffi_type_uint64 */ -#endif - void * pointer; /* ffi_type_pointer */ -} dl_generic; - -static void -dlfunction_free(void *p) -{ - ffi_cif *ptr = p; - if (ptr->arg_types) xfree(ptr->arg_types); - xfree(ptr); -} - -static size_t -dlfunction_memsize(const void *p) -{ - /* const */ffi_cif *ptr = (ffi_cif *)p; - size_t size = 0; - - if (ptr) { - size += sizeof(*ptr); - size += ffi_raw_size(ptr); - } - return size; -} - -const rb_data_type_t dlfunction_data_type = { - "dl/function", - 0, dlfunction_free, dlfunction_memsize, -}; - -static VALUE -rb_dlfunc_allocate(VALUE klass) -{ - ffi_cif * cif; - - return TypedData_Make_Struct(klass, ffi_cif, &dlfunction_data_type, cif); -} - -static VALUE -rb_dlfunction_native_init(VALUE self, VALUE args, VALUE ret_type, VALUE abi) -{ - ffi_cif * cif; - ffi_type **arg_types; - ffi_status result; - int i; - - TypedData_Get_Struct(self, ffi_cif, &dlfunction_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] = DL2FFI_TYPE(type); - } - arg_types[RARRAY_LEN(args)] = NULL; - - result = ffi_prep_cif ( - cif, - NUM2INT(abi), - RARRAY_LEN(args), - DL2FFI_TYPE(NUM2INT(ret_type)), - arg_types); - - if (result) - rb_raise(rb_eRuntimeError, "error creating CIF %d", result); - - return self; -} - -static void -dl2generic(int dl_type, VALUE src, dl_generic * dst) -{ - int signed_p = 1; - - if (dl_type < 0) { - dl_type = -1 * dl_type; - signed_p = 0; - } - - switch (dl_type) { - case DLTYPE_VOID: - break; - case DLTYPE_VOIDP: - dst->pointer = NUM2PTR(rb_Integer(src)); - break; - case DLTYPE_CHAR: - case DLTYPE_SHORT: - case DLTYPE_INT: - dst->sint = NUM2INT(src); - break; - case DLTYPE_LONG: - if (signed_p) - dst->slong = NUM2LONG(src); - else - dst->ulong = NUM2LONG(src); - break; -#if HAVE_LONG_LONG - case DLTYPE_LONG_LONG: - dst->long_long = rb_big2ull(src); - break; -#endif - case DLTYPE_FLOAT: - dst->ffloat = (float)NUM2DBL(src); - break; - case DLTYPE_DOUBLE: - dst->ddouble = NUM2DBL(src); - break; - default: - rb_raise(rb_eRuntimeError, "unknown type %d", dl_type); - } -} - -static VALUE -unwrap_ffi(VALUE rettype, dl_generic retval) -{ - int signed_p = 1; - int dl_type = NUM2INT(rettype); - - if (dl_type < 0) { - dl_type = -1 * dl_type; - signed_p = 0; - } - - switch (dl_type) { - case DLTYPE_VOID: - return Qnil; - case DLTYPE_VOIDP: - return rb_dlptr_new((void *)retval.pointer, 0, NULL); - case DLTYPE_CHAR: - case DLTYPE_SHORT: - case DLTYPE_INT: - return INT2NUM(retval.sint); - case DLTYPE_LONG: - if (signed_p) return LONG2NUM(retval.slong); - return ULONG2NUM(retval.ulong); -#if HAVE_LONG_LONG - case DLTYPE_LONG_LONG: - return rb_ll2inum(retval.long_long); - break; -#endif - case DLTYPE_FLOAT: - return rb_float_new(retval.ffloat); - case DLTYPE_DOUBLE: - return rb_float_new(retval.ddouble); - default: - rb_raise(rb_eRuntimeError, "unknown type %d", dl_type); - } -} - -static VALUE -rb_dlfunction_call(int argc, VALUE argv[], VALUE self) -{ - ffi_cif * cif; - dl_generic retval; - dl_generic *generic_args; - void **values; - void * fun_ptr; - VALUE cfunc, types; - int i; - - TypedData_Get_Struct(self, ffi_cif, &dlfunction_data_type, cif); - - values = xcalloc((size_t)argc + 1, (size_t)sizeof(void *)); - generic_args = xcalloc((size_t)argc, (size_t)sizeof(dl_generic)); - - cfunc = rb_iv_get(self, "@cfunc"); - types = rb_iv_get(self, "@args"); - - for (i = 0; i < argc; i++) { - VALUE dl_type = RARRAY_PTR(types)[i]; - VALUE src = rb_funcall(self, - rb_intern("ruby2ffi"), - 2, - argv[i], - dl_type - ); - - dl2generic(NUM2INT(dl_type), src, &generic_args[i]); - values[i] = (void *)&generic_args[i]; - } - values[argc] = NULL; - - ffi_call(cif, NUM2PTR(rb_Integer(cfunc)), &retval, values); - - rb_dl_set_last_error(self, INT2NUM(errno)); -#if defined(HAVE_WINDOWS_H) - rb_dl_set_win32_last_error(self, INT2NUM(GetLastError())); -#endif - - xfree(values); - xfree(generic_args); - - return unwrap_ffi(rb_funcall(cfunc, rb_intern("ctype"), 0), retval); -} - -void -Init_dlfunction(void) -{ - rb_cDLFunction = rb_define_class_under(rb_mDL, "Function", rb_cObject); - - rb_define_const(rb_cDLFunction, "DEFAULT", INT2NUM(FFI_DEFAULT_ABI)); - -#ifdef FFI_STDCALL - rb_define_const(rb_cDLFunction, "STDCALL", INT2NUM(FFI_STDCALL)); -#endif - - rb_define_alloc_func(rb_cDLFunction, rb_dlfunc_allocate); - - rb_define_private_method(rb_cDLFunction, "native_call", rb_dlfunction_call, -1); - - rb_define_private_method(rb_cDLFunction, "native_init", rb_dlfunction_native_init, 3); -} -/* vim: set noet sw=4 sts=4 */ diff --git a/ext/dl/lib/dl/func.rb b/ext/dl/lib/dl/func.rb index 0ee2df1f23..c5a2dda355 100644 --- a/ext/dl/lib/dl/func.rb +++ b/ext/dl/lib/dl/func.rb @@ -6,7 +6,7 @@ require 'dl/value' require 'thread' module DL - class Function + class Function < DL::Method include DL include ValueUtil @@ -20,7 +20,7 @@ module DL end @args = argtypes - native_init(@args.reject { |x| x == TYPE_VOID }, cfunc.ctype, abi) + super(@cfunc, @args.reject { |x| x == TYPE_VOID }, cfunc.ctype, abi) end def to_i() @@ -35,7 +35,7 @@ module DL if block_given? args.find { |a| DL::Function === a }.bind_at_call(&block) end - native_call(*args) + super end def wrap_result(r) diff --git a/ext/dl/lib/dl/value.rb b/ext/dl/lib/dl/value.rb index c613afe5cf..cc6da6a7fb 100644 --- a/ext/dl/lib/dl/value.rb +++ b/ext/dl/lib/dl/value.rb @@ -36,19 +36,6 @@ module DL end end - def ruby2ffi arg, type - return arg unless type == TYPE_VOIDP - case arg - when nil - 0 - when CPtr - arg.to_i - else - CPtr[arg].to_i - end - end - private :ruby2ffi - def wrap_arg(arg, ty, funcs = [], &block) funcs ||= [] case arg diff --git a/ext/dl/method.c b/ext/dl/method.c new file mode 100644 index 0000000000..8462292d98 --- /dev/null +++ b/ext/dl/method.c @@ -0,0 +1,251 @@ +/* -*- C -*- + * $Id$ + */ + +#include +#include +#include "dl.h" +#include + +VALUE rb_cDLMethod; + +typedef union +{ + unsigned char uchar; /* ffi_type_uchar */ + signed char schar; /* ffi_type_schar */ + unsigned short ushort; /* ffi_type_sshort */ + signed short sshort; /* ffi_type_ushort */ + unsigned int uint; /* ffi_type_uint */ + signed int sint; /* ffi_type_sint */ + unsigned long ulong; /* ffi_type_ulong */ + signed long slong; /* ffi_type_slong */ + float ffloat; /* ffi_type_float */ + double ddouble; /* ffi_type_double */ +#if HAVE_LONG_LONG + unsigned LONG_LONG long_long; /* ffi_type_uint64 */ +#endif + void * pointer; /* ffi_type_pointer */ +} dl_generic; + +static void +dlfunction_free(void *p) +{ + ffi_cif *ptr = p; + if (ptr->arg_types) xfree(ptr->arg_types); + xfree(ptr); +} + +static size_t +dlfunction_memsize(const void *p) +{ + /* const */ffi_cif *ptr = (ffi_cif *)p; + size_t size = 0; + + if (ptr) { + size += sizeof(*ptr); + size += ffi_raw_size(ptr); + } + return size; +} + +const rb_data_type_t dlfunction_data_type = { + "dl/method", + 0, dlfunction_free, dlfunction_memsize, +}; + +static VALUE +rb_dlfunc_allocate(VALUE klass) +{ + ffi_cif * cif; + + return TypedData_Make_Struct(klass, ffi_cif, &dlfunction_data_type, cif); +} + +static VALUE +rb_dlfunction_initialize(int argc, VALUE argv[], VALUE self) +{ + ffi_cif * cif; + ffi_type **arg_types; + ffi_status result; + VALUE ptr, args, ret_type, abi; + int i; + + rb_scan_args(argc, argv, "31", &ptr, &args, &ret_type, &abi); + if(NIL_P(abi)) abi = INT2NUM(FFI_DEFAULT_ABI); + + 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); + + TypedData_Get_Struct(self, ffi_cif, &dlfunction_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] = DL2FFI_TYPE(type); + } + arg_types[RARRAY_LEN(args)] = NULL; + + result = ffi_prep_cif ( + cif, + NUM2INT(abi), + RARRAY_LEN(args), + DL2FFI_TYPE(NUM2INT(ret_type)), + arg_types); + + if (result) + rb_raise(rb_eRuntimeError, "error creating CIF %d", result); + + return self; +} + +static void +dl2generic(int dl_type, VALUE src, dl_generic * dst) +{ + int signed_p = 1; + + if (dl_type < 0) { + dl_type = -1 * dl_type; + signed_p = 0; + } + + switch (dl_type) { + case DLTYPE_VOID: + break; + case DLTYPE_VOIDP: + dst->pointer = NUM2PTR(rb_Integer(src)); + break; + case DLTYPE_CHAR: + case DLTYPE_SHORT: + case DLTYPE_INT: + dst->sint = NUM2INT(src); + break; + case DLTYPE_LONG: + if (signed_p) + dst->slong = NUM2LONG(src); + else + dst->ulong = NUM2LONG(src); + break; +#if HAVE_LONG_LONG + case DLTYPE_LONG_LONG: + dst->long_long = rb_big2ull(src); + break; +#endif + case DLTYPE_FLOAT: + dst->ffloat = (float)NUM2DBL(src); + break; + case DLTYPE_DOUBLE: + dst->ddouble = NUM2DBL(src); + break; + default: + rb_raise(rb_eRuntimeError, "unknown type %d", dl_type); + } +} + +static VALUE +unwrap_ffi(VALUE rettype, dl_generic retval) +{ + int signed_p = 1; + int dl_type = NUM2INT(rettype); + + if (dl_type < 0) { + dl_type = -1 * dl_type; + signed_p = 0; + } + + switch (dl_type) { + case DLTYPE_VOID: + return Qnil; + case DLTYPE_VOIDP: + return rb_dlptr_new((void *)retval.pointer, 0, NULL); + case DLTYPE_CHAR: + case DLTYPE_SHORT: + case DLTYPE_INT: + return INT2NUM(retval.sint); + case DLTYPE_LONG: + if (signed_p) return LONG2NUM(retval.slong); + return ULONG2NUM(retval.ulong); +#if HAVE_LONG_LONG + case DLTYPE_LONG_LONG: + return rb_ll2inum(retval.long_long); + break; +#endif + case DLTYPE_FLOAT: + return rb_float_new(retval.ffloat); + case DLTYPE_DOUBLE: + return rb_float_new(retval.ddouble); + default: + rb_raise(rb_eRuntimeError, "unknown type %d", dl_type); + } +} + +static VALUE +rb_dlfunction_call(int argc, VALUE argv[], VALUE self) +{ + ffi_cif * cif; + dl_generic retval; + dl_generic *generic_args; + void **values; + void * fun_ptr; + VALUE cfunc, types; + int i; + + TypedData_Get_Struct(self, ffi_cif, &dlfunction_data_type, cif); + + values = xcalloc((size_t)argc + 1, (size_t)sizeof(void *)); + generic_args = xcalloc((size_t)argc, (size_t)sizeof(dl_generic)); + + cfunc = rb_iv_get(self, "@ptr"); + types = rb_iv_get(self, "@args"); + + for (i = 0; i < argc; i++) { + VALUE dl_type = RARRAY_PTR(types)[i]; + VALUE src = argv[i]; + + if(NUM2INT(dl_type) == DLTYPE_VOIDP) { + if(NIL_P(src)) { + src = INT2NUM(0); + } else if(rb_cDLCPtr != CLASS_OF(src)) { + src = rb_funcall(rb_cDLCPtr, rb_intern("[]"), 1, src); + } + src = rb_Integer(src); + } + + dl2generic(NUM2INT(dl_type), src, &generic_args[i]); + values[i] = (void *)&generic_args[i]; + } + values[argc] = NULL; + + ffi_call(cif, NUM2PTR(rb_Integer(cfunc)), &retval, values); + + rb_dl_set_last_error(self, INT2NUM(errno)); +#if defined(HAVE_WINDOWS_H) + rb_dl_set_win32_last_error(self, INT2NUM(GetLastError())); +#endif + + xfree(values); + xfree(generic_args); + + return unwrap_ffi(rb_iv_get(self, "@return_type"), retval); +} + +void +Init_dlfunction(void) +{ + rb_cDLMethod = rb_define_class_under(rb_mDL, "Method", rb_cObject); + + rb_define_const(rb_cDLMethod, "DEFAULT", INT2NUM(FFI_DEFAULT_ABI)); + +#ifdef FFI_STDCALL + rb_define_const(rb_cDLMethod, "STDCALL", INT2NUM(FFI_STDCALL)); +#endif + + rb_define_alloc_func(rb_cDLMethod, rb_dlfunc_allocate); + + rb_define_method(rb_cDLMethod, "call", rb_dlfunction_call, -1); + + rb_define_method(rb_cDLMethod, "initialize", rb_dlfunction_initialize, -1); +} +/* vim: set noet sw=4 sts=4 */ -- cgit v1.2.3