ruby-changes:14815
From: tenderlove <ko1@a...>
Date: Tue, 16 Feb 2010 11:06:14 +0900 (JST)
Subject: [ruby-changes:14815] Ruby:r26677 (trunk): * ext/dl/method.c: Adding DL::Method as a superclass for DL::Function
tenderlove 2010-02-16 11:05:46 +0900 (Tue, 16 Feb 2010) New Revision: 26677 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=26677 Log: * ext/dl/method.c: Adding DL::Method as a superclass for DL::Function Added files: trunk/ext/dl/method.c trunk/test/dl/test_method.rb Removed files: trunk/ext/dl/function.c Modified files: trunk/ChangeLog trunk/ext/dl/dl.h trunk/ext/dl/lib/dl/func.rb trunk/ext/dl/lib/dl/value.rb Index: ChangeLog =================================================================== --- ChangeLog (revision 26676) +++ ChangeLog (revision 26677) @@ -1,3 +1,7 @@ +Tue Feb 16 11:03:19 2010 Aaron Patterson <aaron@t...> + + * ext/dl/method.c: Adding DL::Method as a superclass for DL::Function + Mon Feb 15 23:37:30 2010 Tanaka Akira <akr@f...> * io.c: check lseek error by errno. NetBSD 4.0.1 may return -1 as Index: ext/dl/function.c =================================================================== --- ext/dl/function.c (revision 26676) +++ ext/dl/function.c (revision 26677) @@ -1,238 +0,0 @@ -/* -*- C -*- - * $Id$ - */ - -#include <ruby.h> -#include <errno.h> -#include "dl.h" -#include <dl_conversions.h> - -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 */ Index: ext/dl/method.c =================================================================== --- ext/dl/method.c (revision 0) +++ ext/dl/method.c (revision 26677) @@ -0,0 +1,251 @@ +/* -*- C -*- + * $Id$ + */ + +#include <ruby.h> +#include <errno.h> +#include "dl.h" +#include <dl_conversions.h> + +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 */ Property changes on: ext/dl/method.c ___________________________________________________________________ Name: svn:eol-style + LF Index: ext/dl/dl.h =================================================================== --- ext/dl/dl.h (revision 26676) +++ ext/dl/dl.h (revision 26677) @@ -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; Index: ext/dl/lib/dl/func.rb =================================================================== --- ext/dl/lib/dl/func.rb (revision 26676) +++ ext/dl/lib/dl/func.rb (revision 26677) @@ -6,7 +6,7 @@ require 'thread' module DL - class Function + class Function < DL::Method include DL include ValueUtil @@ -20,7 +20,7 @@ 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 @@ if block_given? args.find { |a| DL::Function === a }.bind_at_call(&block) end - native_call(*args) + super end def wrap_result(r) Index: ext/dl/lib/dl/value.rb =================================================================== --- ext/dl/lib/dl/value.rb (revision 26676) +++ ext/dl/lib/dl/value.rb (revision 26677) @@ -36,19 +36,6 @@ 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 Index: test/dl/test_method.rb =================================================================== --- test/dl/test_method.rb (revision 0) +++ test/dl/test_method.rb (revision 26677) @@ -0,0 +1,11 @@ +require_relative 'test_base' +require 'dl/func' + +module DL + class TestMethod < TestBase + def test_method_call + f = Method.new(@libc['sinf'], [TYPE_FLOAT], TYPE_FLOAT) + assert_in_delta 1.0, f.call(90 * Math::PI / 180), 0.0001 + end + end +end -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/