[前][次][番号順一覧][スレッド一覧]

ruby-changes:14895

From: naruse <ko1@a...>
Date: Fri, 26 Feb 2010 07:49:44 +0900 (JST)
Subject: [ruby-changes:14895] Ruby:r26764 (trunk): * ext/dl: revert dl with libffi because it can't run on mswin now.

naruse	2010-02-26 07:49:20 +0900 (Fri, 26 Feb 2010)

  New Revision: 26764

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=26764

  Log:
    * ext/dl: revert dl with libffi because it can't run on mswin now.

  Added directories:
    trunk/ext/dl/callback/
  Added files:
    trunk/ext/dl/callback/depend
    trunk/ext/dl/callback/extconf.rb
    trunk/ext/dl/callback/mkcallback.rb
  Removed files:
    trunk/ext/dl/closure.c
    trunk/ext/dl/dl_conversions.c
    trunk/ext/dl/dl_conversions.h
    trunk/ext/dl/lib/dl/closure.rb
    trunk/ext/dl/method.c
  Modified files:
    trunk/ChangeLog
    trunk/ext/dl/cfunc.c
    trunk/ext/dl/cptr.c
    trunk/ext/dl/depend
    trunk/ext/dl/dl.c
    trunk/ext/dl/dl.h
    trunk/ext/dl/extconf.rb
    trunk/ext/dl/lib/dl/callback.rb
    trunk/ext/dl/lib/dl/func.rb
    trunk/ext/dl/lib/dl/import.rb
    trunk/ext/dl/lib/dl/value.rb

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 26763)
+++ ChangeLog	(revision 26764)
@@ -1,3 +1,7 @@
+Fri Feb 26 07:44:51 2010  NARUSE, Yui  <naruse@r...>
+
+	* ext/dl: revert dl with libffi because it can't run on mswin now.
+
 Thu Feb 25 22:59:46 2010  Tanaka Akira  <akr@f...>
 
 	* pack.c: consider DYNAMIC_ENDIAN.  refactored.
Index: ext/dl/method.c
===================================================================
--- ext/dl/method.c	(revision 26763)
+++ ext/dl/method.c	(revision 26764)
@@ -1,251 +0,0 @@
-/* -*- 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_LENINT(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 */
Index: ext/dl/dl_conversions.c
===================================================================
--- ext/dl/dl_conversions.c	(revision 26763)
+++ ext/dl/dl_conversions.c	(revision 26764)
@@ -1,40 +0,0 @@
-#include <dl_conversions.h>
-
-ffi_type *
-rb_dl_type_to_ffi_type(int dl_type)
-{
-    int signed_p = 1;
-
-    if (dl_type < 0) {
-	dl_type = -1 * dl_type;
-	signed_p = 0;
-    }
-
-#define rb_ffi_type_of(t) (signed_p ? &ffi_type_s##t : &ffi_type_u##t)
-
-    switch (dl_type) {
-      case DLTYPE_VOID:
-	return &ffi_type_void;
-      case DLTYPE_VOIDP:
-	return &ffi_type_pointer;
-      case DLTYPE_CHAR:
-	return rb_ffi_type_of(char);
-      case DLTYPE_SHORT:
-	return rb_ffi_type_of(short);
-      case DLTYPE_INT:
-	return rb_ffi_type_of(int);
-      case DLTYPE_LONG:
-	return rb_ffi_type_of(long);
-#if HAVE_LONG_LONG
-      case DLTYPE_LONG_LONG:
-	return rb_ffi_type_of(int64);
-#endif
-      case DLTYPE_FLOAT:
-	return &ffi_type_float;
-      case DLTYPE_DOUBLE:
-	return &ffi_type_double;
-      default:
-	rb_raise(rb_eRuntimeError, "unknown type %d", dl_type);
-    }
-    return &ffi_type_pointer;
-}
Index: ext/dl/closure.c
===================================================================
--- ext/dl/closure.c	(revision 26763)
+++ ext/dl/closure.c	(revision 26764)
@@ -1,230 +0,0 @@
-/* -*- C -*-
- * $Id$
- */
-
-#include <ruby.h>
-#include "dl.h"
-#include <sys/mman.h>
-#include <dl_conversions.h>
-
-VALUE rb_cDLClosure;
-
-typedef struct {
-    void * code;
-    ffi_closure *pcl;
-    ffi_cif * cif;
-    int argc;
-    ffi_type **argv;
-} dl_closure;
-
-static void
-dlclosure_free(void * ptr)
-{
-    dl_closure * cls = (dl_closure *)ptr;
-#ifdef USE_NEW_CLOSURE_API
-    ffi_closure_free(cls->pcl);
-#else
-    munmap(cls->pcl, sizeof(cls->pcl));
-#endif
-    xfree(cls->cif);
-    if (cls->argv) xfree(cls->argv);
-    xfree(cls);
-}
-
-static size_t
-dlclosure_memsize(const void * ptr)
-{
-    dl_closure * cls = (dl_closure *)ptr;
-    size_t size = 0;
-
-    if (ptr) {
-	size += sizeof(*cls);
-	size += ffi_raw_size(cls->cif);
-	size += sizeof(*cls->argv);
-	size += sizeof(ffi_closure);
-    }
-    return size;
-}
-
-const rb_data_type_t dlclosure_data_type = {
-    "dl/closure",
-    0, dlclosure_free, dlclosure_memsize,
-};
-
-void
-dlc_callback(ffi_cif *cif, void *resp, void **args, void *ctx)
-{
-    VALUE self      = (VALUE)ctx;
-    VALUE rbargs    = rb_iv_get(self, "@args");
-    VALUE ctype     = rb_iv_get(self, "@ctype");
-    int argc        = RARRAY_LENINT(rbargs);
-    VALUE *params   = xcalloc(argc, sizeof(VALUE *));
-    VALUE ret;
-    int i, dl_type;
-
-    for (i = 0; i < argc; i++) {
-        dl_type = NUM2INT(RARRAY_PTR(rbargs)[i]);
-        switch (dl_type) {
-	  case DLTYPE_VOID:
-	    argc = 0;
-	    break;
-	  case DLTYPE_INT:
-	    params[i] = INT2NUM(*(int *)args[i]);
-	    break;
-	  case DLTYPE_VOIDP:
-	    params[i] = rb_dlptr_new(*(void **)args[i], 0, NULL);
-	    break;
-	  case DLTYPE_LONG:
-	    params[i] = LONG2NUM(*(long *)args[i]);
-	    break;
-	  case DLTYPE_CHAR:
-	    params[i] = INT2NUM(*(char *)args[i]);
-	    break;
-	  case DLTYPE_DOUBLE:
-	    params[i] = rb_float_new(*(double *)args[i]);
-	    break;
-	  case DLTYPE_FLOAT:
-	    params[i] = rb_float_new(*(float *)args[i]);
-	    break;
-#if HAVE_LONG_LONG
-	  case DLTYPE_LONG_LONG:
-	    params[i] = rb_ull2inum(*(unsigned LONG_LONG *)args[i]);
-	    break;
-#endif
-	  default:
-	    rb_raise(rb_eRuntimeError, "closure args: %d", dl_type);
-        }
-    }
-
-    ret = rb_funcall2(self, rb_intern("call"), argc, params);
-
-    dl_type = NUM2INT(ctype);
-    switch (dl_type) {
-      case DLTYPE_VOID:
-	break;
-      case DLTYPE_LONG:
-	*(long *)resp = NUM2LONG(ret);
-	break;
-      case DLTYPE_CHAR:
-	*(char *)resp = NUM2INT(ret);
-	break;
-      case DLTYPE_VOIDP:
-	*(void **)resp = NUM2PTR(ret);
-	break;
-      case DLTYPE_INT:
-	*(int *)resp = NUM2INT(ret);
-	break;
-      case DLTYPE_DOUBLE:
-	*(double *)resp = NUM2DBL(ret);
-	break;
-      case DLTYPE_FLOAT:
-	*(float *)resp = (float)NUM2DBL(ret);
-	break;
-#if HAVE_LONG_LONG
-      case DLTYPE_LONG_LONG:
-	*(unsigned LONG_LONG *)resp = rb_big2ull(ret);
-	break;
-#endif
-      default:
-	rb_raise(rb_eRuntimeError, "closure retval: %d", dl_type);
-    }
-    xfree(params);
-}
-
-static VALUE
-rb_dlclosure_allocate(VALUE klass)
-{
-    dl_closure * closure;
-
-    VALUE i = TypedData_Make_Struct(klass, dl_closure,
-	    &dlclosure_data_type, closure);
-
-#ifdef USE_NEW_CLOSURE_API
-    closure->pcl = ffi_closure_alloc(sizeof(ffi_closure), &closure->code);
-#else
-    closure->pcl = mmap(NULL, sizeof(ffi_closure), PROT_READ | PROT_WRITE,
-        MAP_ANON | MAP_PRIVATE, -1, 0);
-#endif
-    closure->cif = xmalloc(sizeof(ffi_cif));
-
-    return i;
-}
-
-static VALUE
-rb_dlclosure_init(int rbargc, VALUE argv[], VALUE self)
-{
-    VALUE ret;
-    VALUE args;
-    VALUE abi;
-    dl_closure * cl;
-    ffi_cif * cif;
-    ffi_closure *pcl;
-    ffi_status result;
-    int i, argc;
-
-    if (2 == rb_scan_args(rbargc, argv, "21", &ret, &args, &abi))
-	abi = INT2NUM(FFI_DEFAULT_ABI);
-
-    argc = RARRAY_LENINT(args);
-
-    TypedData_Get_Struct(self, dl_closure, &dlclosure_data_type, cl);
-
-    cl->argv = (ffi_type **)xcalloc(argc + 1, sizeof(ffi_type *));
-
-    for (i = 0; i < argc; i++) {
-        int dltype = NUM2INT(RARRAY_PTR(args)[i]);
-        cl->argv[i] = DL2FFI_TYPE(dltype);
-    }
-    cl->argv[argc] = NULL;
-
-    rb_iv_set(self, "@ctype", ret);
-    rb_iv_set(self, "@args", args);
-
-    cif = cl->cif;
-    pcl = cl->pcl;
-
-    result = ffi_prep_cif(cif, NUM2INT(abi), argc,
-                DL2FFI_TYPE(NUM2INT(ret)),
-		cl->argv);
-
-    if (FFI_OK != result)
-	rb_raise(rb_eRuntimeError, "error prepping CIF %d", result);
-
-#ifdef USE_NEW_CLOSURE_API
-    result = ffi_prep_closure_loc(pcl, cif, dlc_callback,
-		(void *)self, cl->code);
-#else
-    result = ffi_prep_closure(pcl, cif, dlc_callback, (void *)self);
-    cl->code = (void *)pcl;
-    mprotect(pcl, sizeof(pcl), PROT_READ | PROT_EXEC);
-#endif
-
-    if (FFI_OK != result)
-	rb_raise(rb_eRuntimeError, "error prepping closure %d", result);
-
-    return self;
-}
-
-static VALUE
-rb_dlclosure_to_i(VALUE self)
-{
-    dl_closure * cl;
-    void *code;
-
-    TypedData_Get_Struct(self, dl_closure, &dlclosure_data_type, cl);
-
-    code = cl->code;
-
-    return PTR2NUM(code);
-}
-
-void
-Init_dlclosure(void)
-{
-    rb_cDLClosure = rb_define_class_under(rb_mDL, "Closure", rb_cObject);
-    rb_define_alloc_func(rb_cDLClosure, rb_dlclosure_allocate);
-
-    rb_define_method(rb_cDLClosure, "initialize", rb_dlclosure_init, -1);
-    rb_define_method(rb_cDLClosure, "to_i", rb_dlclosure_to_i, 0);
-}
-/* vim: set noet sw=4 sts=4 */
Index: ext/dl/dl_conversions.h
===================================================================
--- ext/dl/dl_conversions.h	(revision 26763)
+++ ext/dl/dl_conversions.h	(revision 26764)
@@ -1,10 +0,0 @@
-#ifndef DL_CONVERSIONS
-#define DL_CONVERSIONS
-
-#include <dl.h>
-
-#define DL2FFI_TYPE(a) rb_dl_type_to_ffi_type(a)
-
-ffi_type * rb_dl_type_to_ffi_type(int dl_type);
-
-#endif
Index: ext/dl/cfunc.c
===================================================================
--- ext/dl/cfunc.c	(revision 26763)
+++ ext/dl/cfunc.c	(revision 26764)
@@ -16,7 +16,7 @@
     return rb_thread_local_aref(rb_thread_current(), id_last_error);
 }
 
-VALUE
+static VALUE
 rb_dl_set_last_error(VALUE self, VALUE val)
 {
     rb_thread_local_aset(rb_thread_current(), id_last_error, val);
@@ -33,7 +33,7 @@
     return rb_thread_local_aref(rb_thread_current(), id_win32_last_error);
 }
 
-VALUE
+static VALUE
 rb_dl_set_win32_last_error(VALUE self, VALUE val)
 {
     rb_thread_local_aset(rb_thread_current(), id_win32_last_error, val);
@@ -147,12 +147,12 @@
     struct cfunc_data *data;
     void *saddr;
     const char *sname;
-
+    
     rb_scan_args(argc, argv, "13", &addr, &type, &name, &calltype);
-
+    
     saddr = (void*)(NUM2PTR(rb_Integer(addr)));
     sname = NIL_P(name) ? NULL : StringValuePtr(name);
-
+    
     TypedData_Get_Struct(self, struct cfunc_data, &dlcfunc_data_type, data);
     if( data->name ) xfree(data->name);
     data->ptr  = saddr;
@@ -284,11 +284,11 @@
 {
     VALUE val;
     char  *str;
-    size_t str_size;
+    int str_size;
     struct cfunc_data *cfunc;
-
+    
     TypedData_Get_Struct(self, struct cfunc_data, &dlcfunc_data_type, cfunc);
-
+    
     str_size = (cfunc->name ? strlen(cfunc->name) : 0) + 100;
     str = ruby_xmalloc(str_size);
     snprintf(str, str_size - 1,
@@ -339,31 +339,22 @@
 
     memset(stack, 0, sizeof(DLSTACK_TYPE) * DLSTACK_SIZE);
     Check_Type(ary, T_ARRAY);
-
+    
     TypedData_Get_Struct(self, struct cfunc_data, &dlcfunc_data_type, cfunc);
 
     if( cfunc->ptr == 0 ){
 	rb_raise(rb_eDLError, "can't call null-function");
 	return Qnil;
     }
-
-    if( RARRAY_LEN(ary) >= DLSTACK_SIZE ){
-	rb_raise(rb_eDLError, "too many arguments (stack overflow)");
-    }
+    
     for( i = 0; i < RARRAY_LEN(ary); i++ ){
-	unsigned long rb_big2ulong_pack(VALUE x);
-	VALUE arg = RARRAY_PTR(ary)[i];
-
-	rb_check_safe_obj(arg);
-	if (FIXNUM_P(arg)) {
-	    stack[i] = FIX2LONG(arg);
+	if( i >= DLSTACK_SIZE ){
+	    rb_raise(rb_eDLError, "too many arguments (stack overflow)");
 	}
-	else {
-	    Check_Type(arg, T_BIGNUM);
-	    stack[i] = rb_big2ulong_pack(arg);
-	}
+	rb_check_safe_obj(RARRAY_PTR(ary)[i]);
+	stack[i] = NUM2LONG(RARRAY_PTR(ary)[i]);
     }
-
+    
     /* calltype == CFUNC_CDECL */
     if( cfunc->calltype == CFUNC_CDECL
 #ifndef FUNC_STDCALL
Index: ext/dl/depend
===================================================================
--- ext/dl/depend	(revision 26763)
+++ ext/dl/depend	(revision 26764)
@@ -1,13 +1,7 @@
 cfunc.o: cfunc.c dl.h $(hdrdir)/ruby.h
 
-closure.o: closure.c dl.h dl_conversions.h $(hdrdir)/ruby.h
-
 cptr.o: cptr.c dl.h $(hdrdir)/ruby.h $(hdrdir)/io.h
 
 handle.o: handle.c dl.h $(hdrdir)/ruby.h
 
-method.o: method.c dl.h dl_conversions.h $(hdrdir)/ruby.h
-
 dl.o: dl.c dl.h $(hdrdir)/ruby.h $(hdrdir)/io.h
-
-dl_conversions.o: dl_conversions.c dl_conversions.h
Index: ext/dl/dl.c
===================================================================
--- ext/dl/dl.c	(revision 26763)
+++ ext/dl/dl.c	(revision 26764)
@@ -77,6 +77,19 @@
     return PTR2NUM((void*)val);
 }
 
+static void
+rb_dl_init_callbacks(VALUE dl)
+{
+    static const char cb[] = "dl/callback.so";
+
+    rb_autoload(dl, rb_intern_const("CdeclCallbackAddrs"), cb);
+    rb_autoload(dl, rb_intern_const("CdeclCallbackProcs"), cb);
+#ifdef FUNC_STDCALL
+    rb_autoload(dl, rb_intern_const("StdcallCallbackAddrs"), cb);
+    rb_autoload(dl, rb_intern_const("StdcallCallbackProcs"), cb);
+#endif
+}
+
 void
 Init_dl(void)
 {
@@ -94,6 +107,8 @@
     rb_define_const(rb_mDL, "MAX_CALLBACK", INT2NUM(MAX_CALLBACK));
     rb_define_const(rb_mDL, "DLSTACK_SIZE", INT2NUM(DLSTACK_SIZE));
 
+    rb_dl_init_callbacks(rb_mDL);
+
     rb_define_const(rb_mDL, "RTLD_GLOBAL", INT2NUM(RTLD_GLOBAL));
     rb_define_const(rb_mDL, "RTLD_LAZY",   INT2NUM(RTLD_LAZY));
     rb_define_const(rb_mDL, "RTLD_NOW",    INT2NUM(RTLD_NOW));
@@ -147,6 +162,4 @@
     Init_dlhandle();
     Init_dlcfunc();
     Init_dlptr();
-    Init_dlfunction();
-    Init_dlclosure();
 }
Index: ext/dl/dl.h
===================================================================
--- ext/dl/dl.h	(revision 26763)
+++ ext/dl/dl.h	(revision 26764)
@@ -3,12 +3,6 @@
 
 #include <ruby.h>
 
-#ifdef USE_HEADER_HACKS
-#include <ffi/ffi.h>
-#else
-#include <ffi.h>
-#endif
-
 #if !defined(FUNC_CDECL)
 #  define FUNC_CDECL(x) x
 #endif
@@ -136,7 +130,6 @@
 
 extern VALUE rb_mDL;
 extern VALUE rb_cDLHandle;
-extern VALUE rb_cDLCPtr;
 extern VALUE rb_cDLSymbol;
 extern VALUE rb_eDLError;
 extern VALUE rb_eDLTypeError;
@@ -228,9 +221,4 @@
 VALUE rb_dlptr_new2(VALUE klass, void *ptr, long size, freefunc_t func);
 VALUE rb_dlptr_malloc(long size, freefunc_t func);
 
-VALUE rb_dl_set_last_error(VALUE self, VALUE val);
-#if defined(HAVE_WINDOWS_H)
-VALUE rb_dl_set_win32_last_error(VALUE self, VALUE val);
 #endif
-
-#endif
Index: ext/dl/lib/dl/closure.rb
===================================================================
--- ext/dl/lib/dl/closure.rb	(revision 26763)
+++ ext/dl/lib/dl/closure.rb	(revision 26764)
@@ -1,19 +0,0 @@
-require 'dl'
-
-module DL
-  class Closure
-    attr_reader :ctype
-    attr_reader :args
-
-    class BlockCaller < DL::Closure
-      def initialize ctype, args, abi = DL::Function::DEFAULT, &block
-        super(ctype, args, abi)
-        @block = block
-      end
-
-      def call *args
-        @block.call(*args)
-      end
-    end
-  end
-end
Index: ext/dl/lib/dl/import.rb
===================================================================
--- ext/dl/lib/dl/import.rb	(revision 26763)
+++ ext/dl/lib/dl/import.rb	(revision 26764)
@@ -1,5 +1,4 @@
 require 'dl'
-require 'dl/closure'
 require 'dl/func.rb'
 require 'dl/struct.rb'
 require 'dl/cparser.rb'
@@ -212,11 +211,9 @@
     end
 
     def bind_function(name, ctype, argtype, call_type = nil, &block)
-      closure = Class.new(DL::Closure) {
-        define_method(:call, block)
-      }.new(ctype, argtype)
-
-      Function.new(closure, argtype)
+      f = Function.new(CFunc.new(0, ctype, name, call_type || :cdecl), argtype)
+      f.bind(&block)
+      f
     end
 
     def create_temp_function(name, ctype, argtype, call_type = nil)
Index: ext/dl/lib/dl/func.rb
===================================================================
--- ext/dl/lib/dl/func.rb	(revision 26763)
+++ ext/dl/lib/dl/func.rb	(revision 26764)
@@ -1,26 +1,26 @@
 require 'dl'
-require 'dl/closure'
 require 'dl/callback'
 require 'dl/stack'
 require 'dl/value'
 require 'thread'
 
 module DL
-  class Function < DL::Method
+  class Function
     include DL
     include ValueUtil
 
-    def initialize cfunc, argtypes, abi = DEFAULT, &block
-      if block_given?
-        @cfunc = Class.new(DL::Closure) {
-          define_method(:call, block)
-        }.new(cfunc.ctype, argtypes)
+    def initialize(cfunc, argtypes, &proc)
+      @cfunc = cfunc
+      @stack = Stack.new(argtypes.collect{|ty| ty.abs})
+      if( @cfunc.ctype < 0 )
+        @cfunc.ctype = @cfunc.ctype.abs
+        @unsigned = true
       else
-        @cfunc  = cfunc
+        @unsigned = false
       end
-
-      @args   = argtypes
-      super(@cfunc, @args.reject { |x| x == TYPE_VOID }, cfunc.ctype, abi)
+      if( proc )
+        bind(&proc)
+      end
     end
 
     def to_i()
@@ -32,10 +32,11 @@
     end
 
     def call(*args, &block)
-      if block_given?
-        args.find { |a| DL::Function === a }.bind_at_call(&block)
-      end
-      super
+      funcs = []
+      args = wrap_args(args, @stack.types, funcs, &block)
+      r = @cfunc.call(@stack.pack(args))
+      funcs.each{|f| f.unbind_at_call()}
+      return wrap_result(r)
     end
 
     def wrap_result(r)
@@ -51,16 +52,33 @@
     end
 
     def bind(&block)
-      @cfunc = Class.new(DL::Closure) {
-        def initialize ctype, args, block
-          super(ctype, args)
-          @block = block
+      if( !block )
+        raise(RuntimeError, "block must be given.")
+      end
+      if( @cfunc.ptr == 0 )
+        cb = Proc.new{|*args|
+          ary = @stack.unpack(args)
+          @stack.types.each_with_index{|ty, idx|
+            case ty
+            when TYPE_VOIDP
+              ary[idx] = CPtr.new(ary[idx])
+            end
+          }
+          r = block.call(*ary)
+          wrap_arg(r, @cfunc.ctype, [])
+        }
+        case @cfunc.calltype
+        when :cdecl
+          @cfunc.ptr = set_cdecl_callback(@cfunc.ctype, @stack.size, &cb)
+        when :stdcall
+          @cfunc.ptr = set_stdcall_callback(@cfunc.ctype, @stack.size, &cb)
+        else
+          raise(RuntimeError, "unsupported calltype: #{@cfunc.calltype}")
         end
-
-        def call *args
-          @block.call(*args)
+        if( @cfunc.ptr == 0 )
+          raise(RuntimeException, "can't bind C function.")
         end
-      }.new(@cfunc.ctype, @args, block)
+      end
     end
 
     def unbind()
Index: ext/dl/lib/dl/callback.rb
===================================================================
--- ext/dl/lib/dl/callback.rb	(revision 26763)
+++ ext/dl/lib/dl/callback.rb	(revision 26764)
@@ -1,21 +1,26 @@
 require 'dl'
-require 'dl/closure'
 require 'thread'
 
 module DL
   SEM = Mutex.new
 
-  CdeclCallbackProcs = {}
-  CdeclCallbackAddrs = {}
-
-  def set_callback_internal(proc_entry, addr_entry, argc, ty, abi = DL::Function::DEFAULT, &cbp)
+  def set_callback_internal(proc_entry, addr_entry, argc, ty, &cbp)
     if( argc < 0 )
       raise(ArgumentError, "arity should not be less than 0.")
     end
-
-    closure = DL::Closure::BlockCaller.new(ty, [TYPE_VOIDP] * argc, abi, &cbp)
-    proc_entry[closure.to_i] = closure
-    closure.to_i
+    addr = nil
+    SEM.synchronize{
+      ary = proc_entry[ty]
+      (0...MAX_CALLBACK).each{|n|
+        idx = (n * DLSTACK_SIZE) + argc
+        if( ary[idx].nil? )
+          ary[idx] = cbp
+          addr = addr_entry[ty][idx]
+          break
+        end
+      }
+    }
+    addr
   end
 
   def set_cdecl_callback(ty, argc, &cbp)
@@ -23,14 +28,32 @@
   end
 
   def set_stdcall_callback(ty, argc, &cbp)
-    set_callback_internal(StdcallCallbackProcs, StdcallCallbackAddrs, argc, ty, DL::Function::STDCALL, &cbp)
+    set_callback_internal(StdcallCallbackProcs, StdcallCallbackAddrs, argc, ty, &cbp)
   end
 
   def remove_callback_internal(proc_entry, addr_entry, addr, ctype = nil)
-    addr = addr.to_i
-    return false unless proc_entry.key?(addr)
-    proc_entry.delete(addr)
-    true
+    index = nil
+    if( ctype )
+      addr_entry[ctype].each_with_index{|xaddr, idx|
+        if( xaddr == addr )
+          index = idx
+        end
+      }
+    else
+      addr_entry.each{|ty,entry|
+        entry.each_with_index{|xaddr, idx|
+          if( xaddr == addr )
+            index = idx
+          end
+        }
+      }
+    end
+    if( index and proc_entry[ctype][index] )
+      proc_entry[ctype][index] = nil
+      return true
+    else
+      return false
+    end
   end
 
   def remove_cdecl_callback(addr, ctype = nil)
Index: ext/dl/lib/dl/value.rb
===================================================================
--- ext/dl/lib/dl/value.rb	(revision 26763)
+++ ext/dl/lib/dl/value.rb	(revision 26764)
@@ -36,7 +36,16 @@
       end
     end
 
-    def wrap_arg(arg, ty, funcs = [], &block)
+    def wrap_args(args, tys, funcs, &block)
+      result = []
+      tys ||= []
+      args.each_with_index{|arg, idx|
+        result.push(wrap_arg(arg, tys[idx], funcs, &block))
+      }
+      result
+    end
+
+    def wrap_arg(arg, ty, funcs, &block)
         funcs ||= []
         case arg
         when nil
Index: ext/dl/extconf.rb
===================================================================
--- ext/dl/extconf.rb	(revision 26763)
+++ ext/dl/extconf.rb	(revision 26764)
@@ -8,30 +8,8 @@
   ["dl.h", "$(HDRDIR)"],
 ]
 
-if pkg_config("libffi")
-  # libffi closure api must be switched depending on the version
-  if system("pkg-config --atleast-version=3.0.9 libffi")
-    $defs.push(format('-DUSE_NEW_CLOSURE_API'))
-  end
-else
-  dir_config('ffi', '/usr/include', '/usr/lib')
-end
-
-unless have_header('ffi.h')
-  if have_header('ffi/ffi.h')
-    $defs.push(format('-DUSE_HEADER_HACKS'))
-  else
-    abort "ffi is missing"
-  end
-end
-
-unless have_library('ffi')
-  abort "ffi is missing"
-end
-
 check = true
 if( have_header("dlfcn.h") )
-
   have_library("dl")
   check &&= have_func("dlopen")
   check &&= have_func("dlclose")
Index: ext/dl/cptr.c
===================================================================
--- ext/dl/cptr.c	(revision 26763)
+++ ext/dl/cptr.c	(revision 26764)
@@ -104,7 +104,7 @@
     else{
 	rb_raise(rb_eTypeError, "DL::PtrData was expected");
     }
-
+    
     return ptr;
 }
 
@@ -186,7 +186,7 @@
 rb_dlptr_s_malloc(int argc, VALUE argv[], VALUE klass)
 {
     VALUE size, sym, obj;
-    long s;
+    int   s;
     freefunc_t f;
 
     switch (rb_scan_args(argc, argv, "11", &size, &sym)) {
Index: ext/dl/callback/depend
===================================================================
--- ext/dl/callback/depend	(revision 0)
+++ ext/dl/callback/depend	(revision 26764)
@@ -0,0 +1,15 @@
+src: callback.c \
+     callback-0.c callback-1.c callback-2.c \
+     callback-3.c callback-4.c callback-5.c \
+     callback-6.c callback-7.c callback-8.c
+
+$(OBJS): $(hdrdir)/ruby.h
+
+callback-0.c callback-1.c callback-2.c \
+callback-3.c callback-4.c callback-5.c \
+callback-6.c callback-7.c callback-8.c \
+	: callback.c
+
+callback.c: $(srcdir)/mkcallback.rb $(srcdir)/../dl.h
+	@echo "generating callback.c"
+	@$(RUBY) $(srcdir)/mkcallback.rb -output=callback $(srcdir)/../dl.h
Index: ext/dl/callback/mkcallback.rb
===================================================================
--- ext/dl/callback/mkcallback.rb	(revision 0)
+++ ext/dl/callback/mkcallback.rb	(revision 26764)
@@ -0,0 +1,238 @@
+#!ruby -s
+$output ||= "callback"
+$out = open("#{$output}.c", "w")
+
+$dl_h = ARGV[0] || "dl.h"
+
+# import DLSTACK_SIZE, DLSTACK_ARGS and so on
+File.open($dl_h){|f|
+  pre = ""
+  f.each{|line|
+    line.chop!
+    if( line[-1] == ?\\ )
+      line.chop!
+      line.concat(" ")
+      pre += line
+      next
+    end
+    if( pre.size > 0 )
+      line = pre + line
+      pre  = ""
+    end
+    case line
+    when /#define\s+DLSTACK_SIZE\s+\(?(\d+)\)?/
+      DLSTACK_SIZE = $1.to_i
+    when /#define\s+DLSTACK_ARGS\s+(.+)/
+      DLSTACK_ARGS = $1.to_i
+    when /#define\s+DLTYPE_([A-Z_]+)\s+\(?(\d+)\)?/
+      eval("#{$1} = #{$2}")
+    when /#define\s+MAX_DLTYPE\s+\(?(\d+)\)?/
+      MAX_DLTYPE  = $1.to_i
+    when /#define\s+MAX_CALLBACK\s+\(?(\d+)\)?/
+      MAX_CALLBACK = $1.to_i
+    end
+  }
+}
+
+CDECL = "cdecl"
+STDCALL = "stdcall"
+
+CALLTYPES = [CDECL, STDCALL]
+
+DLTYPE = {
+  VOID => {
+    :name => 'void',
+    :type => 'void',
+    :conv => nil,
+  },
+  CHAR => {
+    :name => 'char',
+    :type => 'char',
+    :conv => 'NUM2CHR(%s)'
+  },
+  SHORT => {
+    :name => 'short',
+    :type => 'short',
+    :conv => 'NUM2INT(%s)',
+  },
+  INT => {
+    :name => 'int',
+    :type => 'int',
+    :conv => 'NUM2INT(%s)',
+  },
+  LONG  => {
+    :name => 'long',
+    :type => 'long',
+    :conv => 'NUM2LONG(%s)',
+  },
+  LONG_LONG => {
+    :name => 'long_long',
+    :type => 'LONG_LONG',
+    :conv => 'NUM2LL(%s)',
+  },
+  FLOAT => {
+    :name => 'float',
+    :type => 'float',
+    :conv => '(float)RFLOAT_VALUE(%s)',
+  },
+  DOUBLE => {
+    :name => 'double',
+    :type => 'double',
+    :conv => 'RFLOAT_VALUE(%s)',
+  },
+  VOIDP => {
+    :name => 'ptr',
+    :type => 'void *',
+    :conv => 'NUM2PTR(%s)',
+  },
+}
+
+
+def func_name(ty, argc, n, calltype)
+  "rb_dl_callback_#{DLTYPE[ty][:name]}_#{argc}_#{n}_#{calltype}"
+end
+
+$out << (<<EOS)
+#include "ruby.h"
+
+VALUE rb_DLCdeclCallbackAddrs, rb_DLCdeclCallbackProcs;
+#ifdef FUNC_STDCALL
+VALUE rb_DLStdcallCallbackAddrs, rb_DLStdcallCallbackProcs;
+#endif
+/*static void *cdecl_callbacks[MAX_DLTYPE][MAX_CALLBACK];*/
+#ifdef FUNC_STDCALL
+/*static void *stdcall_callbacks[MAX_DLTYPE][MAX_CALLBACK];*/
+#endif
+ID   rb_dl_cb_call;
+EOS
+
+def foreach_proc_entry
+  for calltype in CALLTYPES
+    case calltype
+    when CDECL
+      proc_entry = "rb_DLCdeclCallbackProcs"
+    when STDCALL
+      proc_entry = "rb_DLStdcallCallbackProcs"
+    else
+      raise "unknown calltype: #{calltype}"
+    end
+    yield calltype, proc_entry
+  end
+end
+
+def gencallback(ty, calltype, proc_entry, argc, n)
+  <<-EOS
+#{calltype == STDCALL ? "\n#ifdef FUNC_STDCALL" : ""}
+static #{DLTYPE[ty][:type]}
+FUNC_#{calltype.upcase}(#{func_name(ty,argc,n,calltype)})(#{(0...argc).collect{|i| "DLSTACK_TYPE stack" + i.to_s}.join(", ")})
+{
+    VALUE ret, cb#{argc > 0 ? ", args[#{argc}]" : ""};
+#{
+      (0...argc).collect{|i|
+	"    args[%d] = LONG2NUM(stack%d);" % [i,i]
+      }.join("\n")
+}
+    cb = rb_ary_entry(rb_ary_entry(#{proc_entry}, #{ty}), #{(n * DLSTACK_SIZE) + argc});
+    ret = rb_funcall2(cb, rb_dl_cb_call, #{argc}, #{argc > 0 ? 'args' : 'NULL'});
+    return #{DLTYPE[ty][:conv] ? DLTYPE[ty][:conv] % "ret" : ""};
+}
+#{calltype == STDCALL ? "#endif\n" : ""}
+  EOS
+end
+
+def gen_push_proc_ary(ty, aryname)
+  sprintf("    rb_ary_push(#{aryname}, rb_ary_new3(%d,%s));",
+          MAX_CALLBACK * DLSTACK_SIZE,
+          (0...MAX_CALLBACK).collect{
+            (0...DLSTACK_SIZE).collect{ "Qnil" }.join(",")
+          }.join(","))
+end
+
+def gen_push_addr_ary(ty, aryname, calltype)
+  sprintf("    rb_ary_push(#{aryname}, rb_ary_new3(%d,%s));",
+          MAX_CALLBACK * DLSTACK_SIZE,
+          (0...MAX_CALLBACK).collect{|i|
+            (0...DLSTACK_SIZE).collect{|argc|
+              "PTR2NUM(%s)" % func_name(ty,argc,i,calltype)
+            }.join(",")
+          }.join(","))
+end
+
+def gen_callback_file(ty)
+  filename = "#{$output}-#{ty}.c"
+  initname = "rb_dl_init_callbacks_#{ty}"
+  body = <<-EOS
+#include "dl.h"
+
+extern VALUE rb_DLCdeclCallbackAddrs, rb_DLCdeclCallbackProcs;
+#ifdef FUNC_STDCALL
+extern VALUE rb_DLStdcallCallbackAddrs, rb_DLStdcallCallbackProcs;
+#endif
+extern ID   rb_dl_cb_call;
+    EOS
+  yield body
+  body << <<-EOS
+void
+#{initname}()
+{
+#{gen_push_proc_ary(ty, "rb_DLCdeclCallbackProcs")}
+#{gen_push_addr_ary(ty, "rb_DLCdeclCallbackAddrs", CDECL)}
+#ifdef FUNC_STDCALL
+#{gen_push_proc_ary(ty, "rb_DLStdcallCallbackProcs")}
+#{gen_push_addr_ary(ty, "rb_DLStdcallCallbackAddrs", STDCALL)}
+#endif
+}
+    EOS
+  [filename, initname, body]
+end
+
+callbacks = []
+for ty in 0...MAX_DLTYPE
+  filename, initname, body = gen_callback_file(ty) {|f|
+    foreach_proc_entry do |calltype, proc_entry|
+      for argc in 0...DLSTACK_SIZE
+        for n in 0...MAX_CALLBACK
+          f << gencallback(ty, calltype, proc_entry, argc, n)
+        end
+      end
+    end
+  }
+  $out << "void #{initname}();\n"
+  callbacks << [filename, body]
+end
+
+$out << (<<EOS)
+void
+Init_callback(void)
+{
+    VALUE tmp;
+    VALUE rb_mDL = rb_path2class("DL");
+
+    rb_dl_cb_call = rb_intern("call");
+
+    tmp = rb_DLCdeclCallbackProcs = rb_ary_new();
+    rb_define_const(rb_mDL, "CdeclCallbackProcs", tmp);
+
+    tmp = rb_DLCdeclCallbackAddrs = rb_ary_new();
+    rb_define_const(rb_mDL, "CdeclCallbackAddrs", tmp);
+
+#ifdef FUNC_STDCALL
+    tmp = rb_DLStdcallCallbackProcs = rb_ary_new();
+    rb_define_const(rb_mDL, "StdcallCallbackProcs", tmp);
+
+    tmp = rb_DLStdcallCallbackAddrs = rb_ary_new();
+    rb_define_const(rb_mDL, "StdcallCallbackAddrs", tmp);
+#endif
+
+#{
+    (0...MAX_DLTYPE).collect{|ty|
+      "    rb_dl_init_callbacks_#{ty}();"
+    }.join("\n")
+}
+}
+EOS
+$out.close
+
+for filename, body in callbacks
+  open(filename, "wb") {|f| f.puts body}
+end
Index: ext/dl/callback/extconf.rb
===================================================================
--- ext/dl/callback/extconf.rb	(revision 0)
+++ ext/dl/callback/extconf.rb	(revision 26764)
@@ -0,0 +1,14 @@
+require 'mkmf'
+
+if compiled?("dl")
+  callbacks = (0..8).map{|i| "callback-#{i}"}.unshift("callback")
+  callback_srcs = callbacks.map{|basename| "#{basename}.c"}
+  callback_objs = callbacks.map{|basename| "#{basename}.o"}
+
+  $distcleanfiles << '$(SRCS)'
+  $srcs = callback_srcs
+  $objs = callback_objs
+  $INCFLAGS << " -I$(srcdir)/.."
+
+  create_makefile("dl/callback")
+end

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]