From d2f913c8aebb49fbb554519e0643ed7e2a480ad7 Mon Sep 17 00:00:00 2001 From: Jean Boussier Date: Thu, 2 Mar 2023 17:01:01 +0100 Subject: Convert FFI::Struct to TypedData Ref: https://github.com/ffi/ffi/pull/991 The old untyped DATA API is soft deprecated and this new one open the door to write barriers, compaction, memsize etc. --- ext/ffi_c/Call.c | 4 +++- ext/ffi_c/Function.c | 4 +++- ext/ffi_c/Struct.c | 48 ++++++++++++++++++++++++++++++------------------ ext/ffi_c/Struct.h | 2 ++ ext/ffi_c/StructLayout.c | 44 +++++++++++++++++++++++++++----------------- 5 files changed, 65 insertions(+), 37 deletions(-) diff --git a/ext/ffi_c/Call.c b/ext/ffi_c/Call.c index bd6c277..8aa8696 100644 --- a/ext/ffi_c/Call.c +++ b/ext/ffi_c/Call.c @@ -424,7 +424,9 @@ getPointer(VALUE value, int type) } else if (type == T_DATA && rb_obj_is_kind_of(value, rbffi_StructClass)) { - AbstractMemory* memory = ((Struct *) DATA_PTR(value))->pointer; + Struct* s; + TypedData_Get_Struct(value, Struct, &rbffi_struct_data_type, s); + AbstractMemory* memory = s->pointer; return memory != NULL ? memory->address : NULL; } else if (type == T_STRING) { diff --git a/ext/ffi_c/Function.c b/ext/ffi_c/Function.c index 1a57591..d850113 100644 --- a/ext/ffi_c/Function.c +++ b/ext/ffi_c/Function.c @@ -825,7 +825,9 @@ invoke_callback(VALUE data) case NATIVE_STRUCT: if (TYPE(rbReturnValue) == T_DATA && rb_obj_is_kind_of(rbReturnValue, rbffi_StructClass)) { - AbstractMemory* memory = ((Struct *) DATA_PTR(rbReturnValue))->pointer; + Struct* s; + TypedData_Get_Struct(rbReturnValue, Struct, &rbffi_struct_data_type, s); + AbstractMemory* memory = s->pointer; if (memory->address != NULL) { memcpy(retval, memory->address, returnType->ffiType->size); diff --git a/ext/ffi_c/Struct.c b/ext/ffi_c/Struct.c index 92731c8..df6c3e9 100644 --- a/ext/ffi_c/Struct.c +++ b/ext/ffi_c/Struct.c @@ -61,13 +61,22 @@ typedef struct InlineArray_ { } InlineArray; -static void struct_mark(Struct *); -static void struct_free(Struct *); +static void struct_mark(void *data); +static void struct_free(void *data); static VALUE struct_class_layout(VALUE klass); static void struct_malloc(Struct* s); static void inline_array_mark(InlineArray *); static void store_reference_value(StructField* f, Struct* s, VALUE value); +const rb_data_type_t rbffi_struct_data_type = { /* extern */ + .wrap_struct_name = "FFI::Struct", + .function = { + .dmark = struct_mark, + .dfree = struct_free, + .dsize = NULL, + }, + .flags = RUBY_TYPED_FREE_IMMEDIATELY +}; VALUE rbffi_StructClass = Qnil; VALUE rbffi_StructInlineArrayClass = Qnil; @@ -86,7 +95,7 @@ static VALUE struct_allocate(VALUE klass) { Struct* s; - VALUE obj = Data_Make_Struct(klass, Struct, struct_mark, struct_free, s); + VALUE obj = TypedData_Make_Struct(klass, Struct, &rbffi_struct_data_type, s); s->rbPointer = Qnil; s->rbLayout = Qnil; @@ -108,7 +117,7 @@ struct_initialize(int argc, VALUE* argv, VALUE self) VALUE rbPointer = Qnil, rest = Qnil, klass = CLASS_OF(self); int nargs; - Data_Get_Struct(self, Struct, s); + TypedData_Get_Struct(self, Struct, &rbffi_struct_data_type, s); nargs = rb_scan_args(argc, argv, "01*", &rbPointer, &rest); @@ -146,8 +155,8 @@ struct_initialize_copy(VALUE self, VALUE other) Struct* src; Struct* dst; - Data_Get_Struct(self, Struct, dst); - Data_Get_Struct(other, Struct, src); + TypedData_Get_Struct(self, Struct, &rbffi_struct_data_type, dst); + TypedData_Get_Struct(other, Struct, &rbffi_struct_data_type, src); if (dst == src) { return self; } @@ -196,7 +205,8 @@ struct_class_layout(VALUE klass) static StructLayout* struct_layout(VALUE self) { - Struct* s = (Struct *) DATA_PTR(self); + Struct* s; + TypedData_Get_Struct(self, Struct, &rbffi_struct_data_type, s); if (s->layout != NULL) { return s->layout; } @@ -213,7 +223,7 @@ static Struct* struct_validate(VALUE self) { Struct* s; - Data_Get_Struct(self, Struct, s); + TypedData_Get_Struct(self, Struct, &rbffi_struct_data_type, s); if (struct_layout(self) == NULL) { rb_raise(rb_eRuntimeError, "struct layout == null"); @@ -240,8 +250,9 @@ struct_malloc(Struct* s) } static void -struct_mark(Struct *s) +struct_mark(void *data) { + Struct *s = (Struct *)data; rb_gc_mark(s->rbPointer); rb_gc_mark(s->rbLayout); if (s->rbReferences != NULL) { @@ -250,8 +261,9 @@ struct_mark(Struct *s) } static void -struct_free(Struct* s) +struct_free(void *data) { + Struct *s = (Struct *)data; xfree(s->rbReferences); xfree(s); } @@ -383,7 +395,7 @@ struct_set_pointer(VALUE self, VALUE pointer) } - Data_Get_Struct(self, Struct, s); + TypedData_Get_Struct(self, Struct, &rbffi_struct_data_type, s); Data_Get_Struct(pointer, AbstractMemory, memory); layout = struct_layout(self); @@ -409,7 +421,7 @@ struct_get_pointer(VALUE self) { Struct* s; - Data_Get_Struct(self, Struct, s); + TypedData_Get_Struct(self, Struct, &rbffi_struct_data_type, s); return s->rbPointer; } @@ -424,7 +436,7 @@ static VALUE struct_set_layout(VALUE self, VALUE layout) { Struct* s; - Data_Get_Struct(self, Struct, s); + TypedData_Get_Struct(self, Struct, &rbffi_struct_data_type, s); if (!rb_obj_is_kind_of(layout, rbffi_StructLayoutClass)) { rb_raise(rb_eTypeError, "wrong argument type %s (expected %s)", @@ -448,7 +460,7 @@ struct_get_layout(VALUE self) { Struct* s; - Data_Get_Struct(self, Struct, s); + TypedData_Get_Struct(self, Struct, &rbffi_struct_data_type, s); return s->rbLayout; } @@ -463,7 +475,7 @@ struct_null_p(VALUE self) { Struct* s; - Data_Get_Struct(self, Struct, s); + TypedData_Get_Struct(self, Struct, &rbffi_struct_data_type, s); return s->pointer->address == NULL ? Qtrue : Qfalse; } @@ -476,7 +488,7 @@ struct_order(int argc, VALUE* argv, VALUE self) { Struct* s; - Data_Get_Struct(self, Struct, s); + TypedData_Get_Struct(self, Struct, &rbffi_struct_data_type, s); if (argc == 0) { return rb_funcall(s->rbPointer, rb_intern("order"), 0); @@ -526,7 +538,7 @@ inline_array_initialize(VALUE self, VALUE rbMemory, VALUE rbField) array->rbField = rbField; Data_Get_Struct(rbMemory, AbstractMemory, array->memory); - Data_Get_Struct(rbField, StructField, array->field); + TypedData_Get_Struct(rbField, StructField, &rbffi_struct_field_data_type, array->field); Data_Get_Struct(array->field->rbType, ArrayType, array->arrayType); Data_Get_Struct(array->arrayType->rbComponentType, Type, array->componentType); @@ -633,7 +645,7 @@ inline_array_aset(VALUE self, VALUE rbIndex, VALUE rbValue) checkWrite(array->memory); checkBounds(array->memory, offset, array->componentType->ffiType->size); - Data_Get_Struct(rbValue, Struct, s); + TypedData_Get_Struct(rbValue, Struct, &rbffi_struct_data_type, s); checkRead(s->pointer); checkBounds(s->pointer, 0, array->componentType->ffiType->size); diff --git a/ext/ffi_c/Struct.h b/ext/ffi_c/Struct.h index eb6edf2..77a6ff9 100644 --- a/ext/ffi_c/Struct.h +++ b/ext/ffi_c/Struct.h @@ -98,6 +98,8 @@ extern "C" { VALUE rbPointer; }; + extern const rb_data_type_t rbffi_struct_data_type; + extern const rb_data_type_t rbffi_struct_field_data_type; extern VALUE rbffi_StructClass, rbffi_StructLayoutClass; extern VALUE rbffi_StructLayoutFieldClass, rbffi_StructLayoutFunctionFieldClass; extern VALUE rbffi_StructLayoutArrayFieldClass; diff --git a/ext/ffi_c/StructLayout.c b/ext/ffi_c/StructLayout.c index d318b8c..50501dc 100644 --- a/ext/ffi_c/StructLayout.c +++ b/ext/ffi_c/StructLayout.c @@ -53,8 +53,17 @@ static void struct_layout_mark(StructLayout *); static void struct_layout_free(StructLayout *); -static void struct_field_mark(StructField* ); - +static void struct_field_mark(void *data); + +const rb_data_type_t rbffi_struct_field_data_type = { /* extern */ + .wrap_struct_name = "FFI::StructLayout::Field", + .function = { + .dmark = struct_field_mark, + .dfree = RUBY_TYPED_DEFAULT_FREE, + .dsize = NULL, + }, + .flags = RUBY_TYPED_FREE_IMMEDIATELY +}; VALUE rbffi_StructLayoutFieldClass = Qnil; VALUE rbffi_StructLayoutNumberFieldClass = Qnil, rbffi_StructLayoutPointerFieldClass = Qnil; VALUE rbffi_StructLayoutStringFieldClass = Qnil; @@ -69,7 +78,7 @@ struct_field_allocate(VALUE klass) StructField* field; VALUE obj; - obj = Data_Make_Struct(klass, StructField, struct_field_mark, -1, field); + obj = TypedData_Make_Struct(klass, StructField, &rbffi_struct_field_data_type, field); field->rbType = Qnil; field->rbName = Qnil; @@ -77,8 +86,9 @@ struct_field_allocate(VALUE klass) } static void -struct_field_mark(StructField* f) +struct_field_mark(void *data) { + StructField *f = (StructField *)data; rb_gc_mark(f->rbType); rb_gc_mark(f->rbName); } @@ -98,7 +108,7 @@ struct_field_initialize(int argc, VALUE* argv, VALUE self) StructField* field; int nargs; - Data_Get_Struct(self, StructField, field); + TypedData_Get_Struct(self, StructField, &rbffi_struct_field_data_type, field); nargs = rb_scan_args(argc, argv, "3", &rbName, &rbOffset, &rbType); @@ -147,7 +157,7 @@ static VALUE struct_field_offset(VALUE self) { StructField* field; - Data_Get_Struct(self, StructField, field); + TypedData_Get_Struct(self, StructField, &rbffi_struct_field_data_type, field); return UINT2NUM(field->offset); } @@ -160,7 +170,7 @@ static VALUE struct_field_size(VALUE self) { StructField* field; - Data_Get_Struct(self, StructField, field); + TypedData_Get_Struct(self, StructField, &rbffi_struct_field_data_type, field); return UINT2NUM(field->type->ffiType->size); } @@ -173,7 +183,7 @@ static VALUE struct_field_alignment(VALUE self) { StructField* field; - Data_Get_Struct(self, StructField, field); + TypedData_Get_Struct(self, StructField, &rbffi_struct_field_data_type, field); return UINT2NUM(field->type->ffiType->alignment); } @@ -186,7 +196,7 @@ static VALUE struct_field_type(VALUE self) { StructField* field; - Data_Get_Struct(self, StructField, field); + TypedData_Get_Struct(self, StructField, &rbffi_struct_field_data_type, field); return field->rbType; } @@ -200,7 +210,7 @@ static VALUE struct_field_name(VALUE self) { StructField* field; - Data_Get_Struct(self, StructField, field); + TypedData_Get_Struct(self, StructField, &rbffi_struct_field_data_type, field); return field->rbName; } @@ -215,7 +225,7 @@ struct_field_get(VALUE self, VALUE pointer) { StructField* f; - Data_Get_Struct(self, StructField, f); + TypedData_Get_Struct(self, StructField, &rbffi_struct_field_data_type, f); if (f->memoryOp == NULL) { rb_raise(rb_eArgError, "get not supported for %s", rb_obj_classname(f->rbType)); return Qnil; @@ -236,7 +246,7 @@ struct_field_put(VALUE self, VALUE pointer, VALUE value) { StructField* f; - Data_Get_Struct(self, StructField, f); + TypedData_Get_Struct(self, StructField, &rbffi_struct_field_data_type, f); if (f->memoryOp == NULL) { rb_raise(rb_eArgError, "put not supported for %s", rb_obj_classname(f->rbType)); return self; @@ -258,7 +268,7 @@ function_field_get(VALUE self, VALUE pointer) { StructField* f; - Data_Get_Struct(self, StructField, f); + TypedData_Get_Struct(self, StructField, &rbffi_struct_field_data_type, f); return rbffi_Function_NewInstance(f->rbType, (*rbffi_AbstractMemoryOps.pointer->get)(MEMORY(pointer), f->offset)); } @@ -278,7 +288,7 @@ function_field_put(VALUE self, VALUE pointer, VALUE proc) StructField* f; VALUE value = Qnil; - Data_Get_Struct(self, StructField, f); + TypedData_Get_Struct(self, StructField, &rbffi_struct_field_data_type, f); if (NIL_P(proc) || rb_obj_is_kind_of(proc, rbffi_FunctionClass)) { value = proc; @@ -313,7 +323,7 @@ array_field_get(VALUE self, VALUE pointer) ArrayType* array; VALUE argv[2]; - Data_Get_Struct(self, StructField, f); + TypedData_Get_Struct(self, StructField, &rbffi_struct_field_data_type, f); Data_Get_Struct(f->rbType, ArrayType, array); argv[0] = pointer; @@ -337,7 +347,7 @@ array_field_put(VALUE self, VALUE pointer, VALUE value) ArrayType* array; - Data_Get_Struct(self, StructField, f); + TypedData_Get_Struct(self, StructField, &rbffi_struct_field_data_type, f); Data_Get_Struct(f->rbType, ArrayType, array); if (isCharArray(array) && rb_obj_is_instance_of(value, rb_cString)) { @@ -470,7 +480,7 @@ struct_layout_initialize(VALUE self, VALUE fields, VALUE size, VALUE align) } rbName = rb_funcall2(rbField, rb_intern("name"), 0, NULL); - Data_Get_Struct(rbField, StructField, field); + TypedData_Get_Struct(rbField, StructField, &rbffi_struct_field_data_type, field); layout->fields[i] = field; if (field->type == NULL || field->type->ffiType == NULL) { -- cgit v1.2.1