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

ruby-changes:63636

From: Sutou <ko1@a...>
Date: Wed, 18 Nov 2020 09:05:39 +0900 (JST)
Subject: [ruby-changes:63636] ae7b53546c (master): [ruby/fiddle] Add TYPE_CONST_STRING and SIZEOF_CONST_STRING for "const char *"

https://git.ruby-lang.org/ruby.git/commit/?id=ae7b53546c

From ae7b53546ca18b56c23f612b6935e98268a07602 Mon Sep 17 00:00:00 2001
From: Sutou Kouhei <kou@c...>
Date: Thu, 9 Jul 2020 20:19:20 +0900
Subject: [ruby/fiddle] Add TYPE_CONST_STRING and SIZEOF_CONST_STRING for
 "const char *"

Add rb_fiddle_ prefix to conversion functions.h to keep backward
compatibility but value_to_generic() isn't safe for TYPE_CONST_STRING
and not String src. Use rb_fiddle_value_to_generic() instead.

https://github.com/ruby/fiddle/commit/0ffcaa39e5

diff --git a/ext/fiddle/conversions.c b/ext/fiddle/conversions.c
index d40ddc1..19bdd8a 100644
--- a/ext/fiddle/conversions.c
+++ b/ext/fiddle/conversions.c
@@ -1,7 +1,7 @@ https://github.com/ruby/ruby/blob/trunk/ext/fiddle/conversions.c#L1
 #include <fiddle.h>
 
 ffi_type *
-int_to_ffi_type(int type)
+rb_fiddle_int_to_ffi_type(int type)
 {
     int signed_p = 1;
 
@@ -33,66 +33,90 @@ int_to_ffi_type(int type) https://github.com/ruby/ruby/blob/trunk/ext/fiddle/conversions.c#L33
 	return &ffi_type_float;
       case TYPE_DOUBLE:
 	return &ffi_type_double;
+      case TYPE_CONST_STRING:
+	return &ffi_type_pointer;
       default:
 	rb_raise(rb_eRuntimeError, "unknown type %d", type);
     }
     return &ffi_type_pointer;
 }
 
+ffi_type *
+int_to_ffi_type(int type)
+{
+    return rb_fiddle_int_to_ffi_type(type);
+}
+
 void
-value_to_generic(int type, VALUE src, fiddle_generic * dst)
+rb_fiddle_value_to_generic(int type, VALUE *src, fiddle_generic *dst)
 {
     switch (type) {
       case TYPE_VOID:
 	break;
       case TYPE_VOIDP:
-	dst->pointer = NUM2PTR(rb_Integer(src));
+	dst->pointer = NUM2PTR(rb_Integer(*src));
 	break;
       case TYPE_CHAR:
-	dst->schar = (signed char)NUM2INT(src);
+	dst->schar = (signed char)NUM2INT(*src);
 	break;
       case -TYPE_CHAR:
-	dst->uchar = (unsigned char)NUM2UINT(src);
+	dst->uchar = (unsigned char)NUM2UINT(*src);
 	break;
       case TYPE_SHORT:
-	dst->sshort = (unsigned short)NUM2INT(src);
+	dst->sshort = (unsigned short)NUM2INT(*src);
 	break;
       case -TYPE_SHORT:
-	dst->sshort = (signed short)NUM2UINT(src);
+	dst->sshort = (signed short)NUM2UINT(*src);
 	break;
       case TYPE_INT:
-	dst->sint = NUM2INT(src);
+	dst->sint = NUM2INT(*src);
 	break;
       case -TYPE_INT:
-	dst->uint = NUM2UINT(src);
+	dst->uint = NUM2UINT(*src);
 	break;
       case TYPE_LONG:
-	dst->slong = NUM2LONG(src);
+	dst->slong = NUM2LONG(*src);
 	break;
       case -TYPE_LONG:
-	dst->ulong = NUM2ULONG(src);
+	dst->ulong = NUM2ULONG(*src);
 	break;
 #if HAVE_LONG_LONG
       case TYPE_LONG_LONG:
-	dst->slong_long = NUM2LL(src);
+	dst->slong_long = NUM2LL(*src);
 	break;
       case -TYPE_LONG_LONG:
-	dst->ulong_long = NUM2ULL(src);
+	dst->ulong_long = NUM2ULL(*src);
 	break;
 #endif
       case TYPE_FLOAT:
-	dst->ffloat = (float)NUM2DBL(src);
+	dst->ffloat = (float)NUM2DBL(*src);
 	break;
       case TYPE_DOUBLE:
-	dst->ddouble = NUM2DBL(src);
+	dst->ddouble = NUM2DBL(*src);
+	break;
+      case TYPE_CONST_STRING:
+        if (NIL_P(*src)) {
+            dst->pointer = NULL;
+        }
+        else {
+            dst->pointer = rb_string_value_cstr(src);
+        }
 	break;
       default:
 	rb_raise(rb_eRuntimeError, "unknown type %d", type);
     }
 }
 
+void
+value_to_generic(int type, VALUE src, fiddle_generic *dst)
+{
+    /* src isn't safe from GC when type is TYPE_CONST_STRING and src
+     * isn't String. */
+    return rb_fiddle_value_to_generic(type, &src, dst);
+}
+
 VALUE
-generic_to_value(VALUE rettype, fiddle_generic retval)
+rb_fiddle_generic_to_value(VALUE rettype, fiddle_generic retval)
 {
     int type = NUM2INT(rettype);
     VALUE cPointer;
@@ -131,6 +155,13 @@ generic_to_value(VALUE rettype, fiddle_generic retval) https://github.com/ruby/ruby/blob/trunk/ext/fiddle/conversions.c#L155
 	return rb_float_new(retval.ffloat);
       case TYPE_DOUBLE:
 	return rb_float_new(retval.ddouble);
+      case TYPE_CONST_STRING:
+        if (retval.pointer) {
+            return rb_str_new_cstr(retval.pointer);
+        }
+        else {
+            return Qnil;
+        }
       default:
 	rb_raise(rb_eRuntimeError, "unknown type %d", type);
     }
@@ -138,4 +169,10 @@ generic_to_value(VALUE rettype, fiddle_generic retval) https://github.com/ruby/ruby/blob/trunk/ext/fiddle/conversions.c#L169
     UNREACHABLE;
 }
 
+VALUE
+generic_to_value(VALUE rettype, fiddle_generic retval)
+{
+    return rb_fiddle_generic_to_value(rettype, retval);
+}
+
 /* vim: set noet sw=4 sts=4 */
diff --git a/ext/fiddle/conversions.h b/ext/fiddle/conversions.h
index cbc610b..f900efa 100644
--- a/ext/fiddle/conversions.h
+++ b/ext/fiddle/conversions.h
@@ -24,13 +24,22 @@ typedef union https://github.com/ruby/ruby/blob/trunk/ext/fiddle/conversions.h#L24
     void * pointer;        /* ffi_type_pointer */
 } fiddle_generic;
 
+/* Deprecated. Use rb_fiddle_*() version. */
+ffi_type * rb_fiddle_int_to_ffi_type(int type);
+void rb_fiddle_value_to_generic(int type, VALUE *src, fiddle_generic *dst);
+VALUE rb_fiddle_generic_to_value(VALUE rettype, fiddle_generic retval);
+
+/* Deprecated. Use rb_fiddle_*() version. */
 ffi_type * int_to_ffi_type(int type);
-void value_to_generic(int type, VALUE src, fiddle_generic * dst);
+void value_to_generic(int type, VALUE src, fiddle_generic *dst);
 VALUE generic_to_value(VALUE rettype, fiddle_generic retval);
 
-#define VALUE2GENERIC(_type, _src, _dst) value_to_generic((_type), (_src), (_dst))
-#define INT2FFI_TYPE(_type) int_to_ffi_type(_type)
-#define GENERIC2VALUE(_type, _retval) generic_to_value((_type), (_retval))
+#define VALUE2GENERIC(_type, _src, _dst)        \
+    rb_fiddle_value_to_generic((_type), &(_src), (_dst))
+#define INT2FFI_TYPE(_type)                     \
+    rb_fiddle_int_to_ffi_type(_type)
+#define GENERIC2VALUE(_type, _retval)           \
+    rb_fiddle_generic_to_value((_type), (_retval))
 
 #if SIZEOF_VOIDP == SIZEOF_LONG
 # define PTR2NUM(x)   (LONG2NUM((long)(x)))
diff --git a/ext/fiddle/fiddle.c b/ext/fiddle/fiddle.c
index 8fb20e8..be287e6 100644
--- a/ext/fiddle/fiddle.c
+++ b/ext/fiddle/fiddle.c
@@ -235,6 +235,12 @@ Init_fiddle(void) https://github.com/ruby/ruby/blob/trunk/ext/fiddle/fiddle.c#L235
     rb_define_const(mFiddle, "TYPE_VARIADIC",  INT2NUM(TYPE_VARIADIC));
 #endif
 
+    /* Document-const: TYPE_CONST_STRING
+     *
+     * C type - const char* ('\0' terminated const char*)
+     */
+    rb_define_const(mFiddle, "TYPE_CONST_STRING",  INT2NUM(TYPE_CONST_STRING));
+
     /* Document-const: TYPE_SIZE_T
      *
      * C type - size_t
@@ -435,6 +441,12 @@ Init_fiddle(void) https://github.com/ruby/ruby/blob/trunk/ext/fiddle/fiddle.c#L441
      */
     rb_define_const(mFiddle, "SIZEOF_UINTPTR_T",  INT2NUM(sizeof(uintptr_t)));
 
+    /* Document-const: SIZEOF_CONST_STRING
+     *
+     * size of a const char*
+     */
+    rb_define_const(mFiddle, "SIZEOF_CONST_STRING", INT2NUM(sizeof(const char*)));
+
     /* Document-const: RUBY_FREE
      *
      * Address of the ruby_xfree() function
diff --git a/ext/fiddle/fiddle.h b/ext/fiddle/fiddle.h
index 2dddc0b..f142229 100644
--- a/ext/fiddle/fiddle.h
+++ b/ext/fiddle/fiddle.h
@@ -116,6 +116,7 @@ https://github.com/ruby/ruby/blob/trunk/ext/fiddle/fiddle.h#L116
 #define TYPE_FLOAT 7
 #define TYPE_DOUBLE 8
 #define TYPE_VARIADIC 9
+#define TYPE_CONST_STRING 10
 
 #define ALIGN_OF(type) offsetof(struct {char align_c; type align_x;}, align_x)
 
diff --git a/ext/fiddle/function.c b/ext/fiddle/function.c
index e96313a..8771dd3 100644
--- a/ext/fiddle/function.c
+++ b/ext/fiddle/function.c
@@ -207,6 +207,7 @@ function_call(int argc, VALUE argv[], VALUE self) https://github.com/ruby/ruby/blob/trunk/ext/fiddle/function.c#L207
     int n_call_args = 0;
     int i;
     int i_call;
+    VALUE converted_args = Qnil;
     VALUE alloc_buffer = 0;
 
     cfunc    = rb_iv_get(self, "@ptr");
@@ -313,6 +314,7 @@ function_call(int argc, VALUE argv[], VALUE self) https://github.com/ruby/ruby/blob/trunk/ext/fiddle/function.c#L314
          i++, i_call++) {
         VALUE arg_type;
         int c_arg_type;
+        VALUE original_src;
         VALUE src;
         arg_type = RARRAY_AREF(arg_types, i_call);
         c_arg_type = FIX2INT(arg_type);
@@ -327,11 +329,22 @@ function_call(int argc, VALUE argv[], VALUE self) https://github.com/ruby/ruby/blob/trunk/ext/fiddle/function.c#L329
             }
             else if (cPointer != CLASS_OF(src)) {
                 src = rb_funcall(cPointer, rb_intern("[]"), 1, src);
+                if (NIL_P(converted_args)) {
+                    converted_args = rb_ary_new();
+                }
+                rb_ary_push(converted_args, src);
             }
             src = rb_Integer(src);
         }
 
+        original_src = src;
         VALUE2GENERIC(c_arg_type, src, &generic_args[i_call]);
+        if (src != original_src) {
+            if (NIL_P(converted_args)) {
+                converted_args = rb_ary_new();
+            }
+            rb_ary_push(converted_args, src);
+        }
         args.values[i_call] = (void *)&generic_args[i_call];
     }
     args.values[i_call] = NULL;
diff --git a/ext/fiddle/lib/fiddle/import.rb b/ext/fiddle/lib/fiddle/import.rb
index 178ebb8..5fcbb1c 100644
--- a/ext/fiddle/lib/fiddle/import.rb
+++ b/ext/fiddle/lib/fiddle/import.rb
@@ -121,6 +121,8 @@ module Fiddle https://github.com/ruby/ruby/blob/trunk/ext/fiddle/lib/fiddle/import.rb#L121
           return SIZEOF_DOUBLE
         when TYPE_VOIDP
           return SIZEOF_VOIDP
+        when TYPE_CONST_STRING
+          return SIZEOF_CONST_STRING
         else
           if defined?(TYPE_LONG_LONG) and
             ty == TYPE_LONG_LONG
diff --git a/test/fiddle/test_func.rb b/test/fiddle/test_func.rb
index 29a0a45..ca9d4cc 100644
--- a/test/fiddle/test_func.rb
+++ b/test/fiddle/test_func.rb
@@ -98,7 +98,7 @@ module Fiddle https://github.com/ruby/ruby/blob/trunk/test/fiddle/test_func.rb#L98
                               [
                                 TYPE_VOIDP,
                                 TYPE_SIZE_T,
-     (... truncated)

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

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