summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJean Boussier <jean.boussier@gmail.com>2023-03-02 17:01:01 +0100
committerJean Boussier <jean.boussier@gmail.com>2023-03-02 17:15:54 +0100
commitd2f913c8aebb49fbb554519e0643ed7e2a480ad7 (patch)
tree3bb75af7e879f6cc705913a2d09d8958a53dce45
parent227d1ce472ec90144249f8cf85b52d85cbab925c (diff)
downloadffi-d2f913c8aebb49fbb554519e0643ed7e2a480ad7.tar.gz
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.
-rw-r--r--ext/ffi_c/Call.c4
-rw-r--r--ext/ffi_c/Function.c4
-rw-r--r--ext/ffi_c/Struct.c48
-rw-r--r--ext/ffi_c/Struct.h2
-rw-r--r--ext/ffi_c/StructLayout.c44
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) {