diff --git a/ext/ffi_c/AbstractMemory.c b/ext/ffi_c/AbstractMemory.c index 1a7fcde4d..7e6360003 100644 --- a/ext/ffi_c/AbstractMemory.c +++ b/ext/ffi_c/AbstractMemory.c @@ -86,8 +86,7 @@ static VALUE memory_put_##name(VALUE self, VALUE offset, VALUE value); \ static VALUE \ memory_put_##name(VALUE self, VALUE offset, VALUE value) \ { \ - AbstractMemory* memory; \ - Data_Get_Struct(self, AbstractMemory, memory); \ + AbstractMemory* memory = MEMORY(self); \ memory_op_put_##name(memory, NUM2LONG(offset), value); \ return self; \ } \ @@ -95,8 +94,7 @@ static VALUE memory_write_##name(VALUE self, VALUE value); \ static VALUE \ memory_write_##name(VALUE self, VALUE value) \ { \ - AbstractMemory* memory; \ - Data_Get_Struct(self, AbstractMemory, memory); \ + AbstractMemory* memory = MEMORY(self); \ memory_op_put_##name(memory, 0, value); \ return self; \ } \ @@ -114,16 +112,14 @@ static VALUE memory_get_##name(VALUE self, VALUE offset); \ static VALUE \ memory_get_##name(VALUE self, VALUE offset) \ { \ - AbstractMemory* memory; \ - Data_Get_Struct(self, AbstractMemory, memory); \ + AbstractMemory* memory = MEMORY(self); \ return memory_op_get_##name(memory, NUM2LONG(offset)); \ } \ static VALUE memory_read_##name(VALUE self); \ static VALUE \ memory_read_##name(VALUE self) \ { \ - AbstractMemory* memory; \ - Data_Get_Struct(self, AbstractMemory, memory); \ + AbstractMemory* memory = MEMORY(self); \ return memory_op_get_##name(memory, 0); \ } \ static MemoryOp memory_op_##name = { memory_op_get_##name, memory_op_put_##name }; \ @@ -319,11 +315,7 @@ memory_clear(VALUE self) static VALUE memory_size(VALUE self) { - AbstractMemory* ptr; - - Data_Get_Struct(self, AbstractMemory, ptr); - - return LONG2NUM(ptr->size); + return LONG2NUM(MEMORY_LEN(self)); } /* @@ -337,14 +329,13 @@ memory_size(VALUE self) static VALUE memory_get(VALUE self, VALUE type_name, VALUE offset) { - AbstractMemory* ptr; VALUE nType; Type *type; nType = rbffi_Type_Lookup(type_name); if(NIL_P(nType)) goto undefined_type; - Data_Get_Struct(self, AbstractMemory, ptr); + AbstractMemory* ptr = MEMORY(self); Data_Get_Struct(nType, Type, type); MemoryOp *op = get_memory_op(type); @@ -369,14 +360,13 @@ undefined_type: { static VALUE memory_put(VALUE self, VALUE type_name, VALUE offset, VALUE value) { - AbstractMemory* ptr; VALUE nType; Type *type; nType = rbffi_Type_Lookup(type_name); if(NIL_P(nType)) goto undefined_type; - Data_Get_Struct(self, AbstractMemory, ptr); + AbstractMemory* ptr = MEMORY(self); Data_Get_Struct(nType, Type, type); MemoryOp *op = get_memory_op(type); @@ -433,7 +423,6 @@ static VALUE memory_get_array_of_string(int argc, VALUE* argv, VALUE self) { VALUE offset = Qnil, countnum = Qnil, retVal = Qnil; - AbstractMemory* ptr; long off; int count; @@ -442,7 +431,7 @@ memory_get_array_of_string(int argc, VALUE* argv, VALUE self) count = (countnum == Qnil ? 0 : NUM2INT(countnum)); retVal = rb_ary_new2(count); - Data_Get_Struct(self, AbstractMemory, ptr); + AbstractMemory* ptr = MEMORY(self); checkRead(ptr); if (countnum != Qnil) { @@ -631,10 +620,7 @@ memory_write_bytes(int argc, VALUE* argv, VALUE self) static VALUE memory_type_size(VALUE self) { - AbstractMemory* ptr; - - Data_Get_Struct(self, AbstractMemory, ptr); - + AbstractMemory* ptr = MEMORY(self); return INT2NUM(ptr->typeSize); } @@ -648,11 +634,9 @@ memory_type_size(VALUE self) static VALUE memory_aref(VALUE self, VALUE idx) { - AbstractMemory* ptr; + AbstractMemory* ptr = MEMORY(self); VALUE rbOffset = Qnil; - Data_Get_Struct(self, AbstractMemory, ptr); - rbOffset = ULONG2NUM(NUM2ULONG(idx) * ptr->typeSize); return rb_funcall2(self, id_plus, 1, &rbOffset); @@ -667,11 +651,7 @@ memory_address(VALUE obj) static VALUE memory_copy_from(VALUE self, VALUE rbsrc, VALUE rblen) { - AbstractMemory* dst; - - Data_Get_Struct(self, AbstractMemory, dst); - - memcpy(dst->address, rbffi_AbstractMemory_Cast(rbsrc, rbffi_AbstractMemoryClass)->address, NUM2INT(rblen)); + memcpy(MEMORY_PTR(self), MEMORY_PTR(rbsrc), NUM2INT(rblen)); return self; } @@ -680,8 +660,7 @@ AbstractMemory* rbffi_AbstractMemory_Cast(VALUE obj, VALUE klass) { if (rb_obj_is_kind_of(obj, klass)) { - AbstractMemory* memory; - Data_Get_Struct(obj, AbstractMemory, memory); + AbstractMemory* memory = RTYPEDDATA_DATA(obj); return memory; } diff --git a/ext/ffi_c/Buffer.c b/ext/ffi_c/Buffer.c index b5f39a488..4e4f1d8ad 100644 --- a/ext/ffi_c/Buffer.c +++ b/ext/ffi_c/Buffer.c @@ -49,10 +49,20 @@ typedef struct Buffer { static VALUE buffer_allocate(VALUE klass); static VALUE buffer_initialize(int argc, VALUE* argv, VALUE self); -static void buffer_release(Buffer* ptr); -static void buffer_mark(Buffer* ptr); +static void buffer_release(void* data); +static void buffer_mark(void* data); static VALUE buffer_free(VALUE self); +static const rb_data_type_t buffer_data_type = { + .wrap_struct_name = "FFI::Buffer", + .function = { + .dmark = buffer_mark, + .dfree = buffer_release, + .dsize = NULL, + }, + .flags = RUBY_TYPED_FREE_IMMEDIATELY +}; + static VALUE BufferClass = Qnil; static VALUE @@ -61,7 +71,7 @@ buffer_allocate(VALUE klass) Buffer* buffer; VALUE obj; - obj = Data_Make_Struct(klass, Buffer, NULL, buffer_release, buffer); + obj = TypedData_Make_Struct(klass, Buffer, &buffer_data_type, buffer); buffer->data.rbParent = Qnil; buffer->memory.flags = MEM_RD | MEM_WR; @@ -69,8 +79,9 @@ buffer_allocate(VALUE klass) } static void -buffer_release(Buffer* ptr) +buffer_release(void *data) { + Buffer* ptr = (Buffer *)data; if ((ptr->memory.flags & MEM_EMBED) == 0 && ptr->data.storage != NULL) { xfree(ptr->data.storage); ptr->data.storage = NULL; @@ -95,7 +106,7 @@ buffer_initialize(int argc, VALUE* argv, VALUE self) Buffer* p; int nargs; - Data_Get_Struct(self, Buffer, p); + TypedData_Get_Struct(self, Buffer, &buffer_data_type, p); nargs = rb_scan_args(argc, argv, "12", &rbSize, &rbCount, &rbClear); p->memory.typeSize = rbffi_type_size(rbSize); @@ -138,7 +149,7 @@ buffer_initialize_copy(VALUE self, VALUE other) AbstractMemory* src; Buffer* dst; - Data_Get_Struct(self, Buffer, dst); + TypedData_Get_Struct(self, Buffer, &buffer_data_type, dst); src = rbffi_AbstractMemory_Cast(other, BufferClass); if ((dst->memory.flags & MEM_EMBED) == 0 && dst->data.storage != NULL) { xfree(dst->data.storage); @@ -172,10 +183,10 @@ slice(VALUE self, long offset, long len) Buffer* result; VALUE obj = Qnil; - Data_Get_Struct(self, Buffer, ptr); + TypedData_Get_Struct(self, Buffer, &buffer_data_type, ptr); checkBounds(&ptr->memory, offset, len); - obj = Data_Make_Struct(BufferClass, Buffer, buffer_mark, -1, result); + obj = TypedData_Make_Struct(BufferClass, Buffer, &buffer_data_type, result); result->memory.address = ptr->memory.address + offset; result->memory.size = len; result->memory.flags = ptr->memory.flags; @@ -197,7 +208,7 @@ buffer_plus(VALUE self, VALUE rbOffset) Buffer* ptr; long offset = NUM2LONG(rbOffset); - Data_Get_Struct(self, Buffer, ptr); + TypedData_Get_Struct(self, Buffer, &buffer_data_type, ptr); return slice(self, offset, ptr->memory.size - offset); } @@ -226,7 +237,7 @@ buffer_inspect(VALUE self) char tmp[100]; Buffer* ptr; - Data_Get_Struct(self, Buffer, ptr); + TypedData_Get_Struct(self, Buffer, &buffer_data_type, ptr); snprintf(tmp, sizeof(tmp), "#", ptr, ptr->memory.address, ptr->memory.size); @@ -255,7 +266,7 @@ buffer_order(int argc, VALUE* argv, VALUE self) { Buffer* ptr; - Data_Get_Struct(self, Buffer, ptr); + TypedData_Get_Struct(self, Buffer, &buffer_data_type, ptr); if (argc == 0) { int order = (ptr->memory.flags & MEM_SWAP) == 0 ? BYTE_ORDER : SWAPPED_ORDER; return order == BIG_ENDIAN ? ID2SYM(rb_intern("big")) : ID2SYM(rb_intern("little")); @@ -279,7 +290,7 @@ buffer_order(int argc, VALUE* argv, VALUE self) Buffer* p2; VALUE retval = slice(self, 0, ptr->memory.size); - Data_Get_Struct(retval, Buffer, p2); + TypedData_Get_Struct(retval, Buffer, &buffer_data_type, p2); p2->memory.flags |= MEM_SWAP; return retval; } @@ -294,7 +305,7 @@ buffer_free(VALUE self) { Buffer* ptr; - Data_Get_Struct(self, Buffer, ptr); + TypedData_Get_Struct(self, Buffer, &buffer_data_type, ptr); if ((ptr->memory.flags & MEM_EMBED) == 0 && ptr->data.storage != NULL) { xfree(ptr->data.storage); ptr->data.storage = NULL; @@ -304,9 +315,12 @@ buffer_free(VALUE self) } static void -buffer_mark(Buffer* ptr) +buffer_mark(void *data) { - rb_gc_mark(ptr->data.rbParent); + Buffer* ptr = (Buffer *)data; + if ((ptr->memory.flags & MEM_EMBED) != 0) { + rb_gc_mark(ptr->data.rbParent); + } } void diff --git a/ext/ffi_c/Call.c b/ext/ffi_c/Call.c index bd6c2776b..098456577 100644 --- a/ext/ffi_c/Call.c +++ b/ext/ffi_c/Call.c @@ -439,7 +439,7 @@ getPointer(VALUE value, int type) VALUE ptr = rb_funcall2(value, id_to_ptr, 0, NULL); if (rb_obj_is_kind_of(ptr, rbffi_AbstractMemoryClass) && TYPE(ptr) == T_DATA) { - return ((AbstractMemory *) DATA_PTR(ptr))->address; + return MEMORY_PTR(ptr); } rb_raise(rb_eArgError, "to_ptr returned an invalid pointer"); } @@ -465,15 +465,13 @@ callback_param(VALUE proc, VALUE cbInfo) /* Handle Function pointers here */ if (rb_obj_is_kind_of(proc, rbffi_FunctionClass)) { - AbstractMemory* ptr; - Data_Get_Struct(proc, AbstractMemory, ptr); - return ptr->address; + return MEMORY_PTR(proc); } callback = rbffi_Function_ForProc(cbInfo, proc); RB_GC_GUARD(callback); - return ((AbstractMemory *) DATA_PTR(callback))->address; + return MEMORY_PTR(callback); } diff --git a/ext/ffi_c/DynamicLibrary.c b/ext/ffi_c/DynamicLibrary.c index 78b3de60e..1923cdc08 100644 --- a/ext/ffi_c/DynamicLibrary.c +++ b/ext/ffi_c/DynamicLibrary.c @@ -57,10 +57,19 @@ typedef struct LibrarySymbol_ { static VALUE library_initialize(VALUE self, VALUE libname, VALUE libflags); static void library_free(Library* lib); - static VALUE symbol_allocate(VALUE klass); static VALUE symbol_new(VALUE library, void* address, VALUE name); -static void symbol_mark(LibrarySymbol* sym); +static void symbol_mark(void *); + +static const rb_data_type_t symbol_data_type = { + .wrap_struct_name = "FFI::DynamicLibrary::Symbol", + .function = { + .dmark = symbol_mark, + .dfree = RUBY_DEFAULT_FREE, + .dsize = NULL, + }, + .flags = RUBY_TYPED_FREE_IMMEDIATELY +}; static VALUE LibraryClass = Qnil, SymbolClass = Qnil; @@ -198,7 +207,7 @@ static VALUE symbol_allocate(VALUE klass) { LibrarySymbol* sym; - VALUE obj = Data_Make_Struct(klass, LibrarySymbol, NULL, -1, sym); + VALUE obj = TypedData_Make_Struct(SymbolClass, LibrarySymbol, &symbol_data_type, sym); sym->name = Qnil; sym->library = Qnil; sym->base.rbParent = Qnil; @@ -224,7 +233,7 @@ static VALUE symbol_new(VALUE library, void* address, VALUE name) { LibrarySymbol* sym; - VALUE obj = Data_Make_Struct(SymbolClass, LibrarySymbol, symbol_mark, -1, sym); + VALUE obj = TypedData_Make_Struct(SymbolClass, LibrarySymbol, &symbol_data_type, sym); sym->base.memory.address = address; sym->base.memory.size = LONG_MAX; @@ -237,10 +246,12 @@ symbol_new(VALUE library, void* address, VALUE name) } static void -symbol_mark(LibrarySymbol* sym) +symbol_mark(void *data) { + LibrarySymbol *sym = (LibrarySymbol *)data; rb_gc_mark(sym->library); rb_gc_mark(sym->name); + rb_gc_mark(sym->base.rbParent); } /* @@ -254,7 +265,7 @@ symbol_inspect(VALUE self) LibrarySymbol* sym; char buf[256]; - Data_Get_Struct(self, LibrarySymbol, sym); + TypedData_Get_Struct(self, LibrarySymbol, &symbol_data_type, sym); snprintf(buf, sizeof(buf), "#", StringValueCStr(sym->name), sym->base.memory.address); return rb_str_new2(buf); diff --git a/ext/ffi_c/Function.c b/ext/ffi_c/Function.c index 1a575911c..083245f38 100644 --- a/ext/ffi_c/Function.c +++ b/ext/ffi_c/Function.c @@ -75,8 +75,6 @@ typedef struct Function_ { VALUE rbFunctionInfo; } Function; -static void function_mark(Function *); -static void function_free(Function *); static VALUE function_init(VALUE self, VALUE rbFunctionInfo, VALUE rbProc); static void callback_invoke(ffi_cif* cif, void* retval, void** parameters, void* user_data); static bool callback_prep(void* ctx, void* code, Closure* closure, char* errmsg, size_t errmsgsize); @@ -132,35 +130,19 @@ static struct gvl_callback* async_cb_list = NULL; # endif #endif - -static VALUE -function_allocate(VALUE klass) -{ - Function *fn; - VALUE obj; - - obj = Data_Make_Struct(klass, Function, function_mark, function_free, fn); - - fn->base.memory.flags = MEM_RD; - fn->base.rbParent = Qnil; - fn->rbProc = Qnil; - fn->rbFunctionInfo = Qnil; - fn->autorelease = true; - - return obj; -} - static void -function_mark(Function *fn) +function_mark(void *data) { + Function *fn = (Function *)data; rb_gc_mark(fn->base.rbParent); rb_gc_mark(fn->rbProc); rb_gc_mark(fn->rbFunctionInfo); } static void -function_free(Function *fn) +function_free(void *data) { + Function *fn = (Function *)data; if (fn->methodHandle != NULL) { rbffi_MethodHandle_Free(fn->methodHandle); } @@ -172,6 +154,33 @@ function_free(Function *fn) xfree(fn); } +static const rb_data_type_t function_data_type = { + .wrap_struct_name = "FFI::Function", + .function = { + .dmark = function_mark, + .dfree = function_free, + .dsize = NULL, + }, + .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED +}; + +static VALUE +function_allocate(VALUE klass) +{ + Function *fn; + VALUE obj; + + obj = TypedData_Make_Struct(klass, Function, &function_data_type, fn); + + fn->base.memory.flags = MEM_RD; + fn->base.rbParent = Qnil; + fn->rbProc = Qnil; + fn->rbFunctionInfo = Qnil; + fn->autorelease = true; + + return obj; +} + /* * @param [Type, Symbol] return_type return type for the function * @param [Array] param_types array of parameters types @@ -254,7 +263,7 @@ rbffi_Function_ForProc(VALUE rbFunctionInfo, VALUE proc) /* If the first callback reference has the same function function signature, use it */ if (cbref != Qnil && CLASS_OF(cbref) == rbffi_FunctionClass) { Function* fp; - Data_Get_Struct(cbref, Function, fp); + TypedData_Get_Struct(cbref, Function, &function_data_type, fp); if (fp->rbFunctionInfo == rbFunctionInfo) { return cbref; } @@ -298,17 +307,16 @@ function_init(VALUE self, VALUE rbFunctionInfo, VALUE rbProc) { Function* fn = NULL; - Data_Get_Struct(self, Function, fn); + TypedData_Get_Struct(self, Function, &function_data_type, fn); - fn->rbFunctionInfo = rbFunctionInfo; + RB_OBJ_WRITE(self, &fn->rbFunctionInfo, rbFunctionInfo); Data_Get_Struct(fn->rbFunctionInfo, FunctionType, fn->info); if (rb_obj_is_kind_of(rbProc, rbffi_PointerClass)) { - Pointer* orig; - Data_Get_Struct(rbProc, Pointer, orig); + Pointer* orig = rbffi_Pointer_Cast(rbProc, rbffi_PointerClass); fn->base.memory = orig->memory; - fn->base.rbParent = rbProc; + RB_OBJ_WRITE(self, &fn->base.rbParent, rbProc); } else if (rb_obj_is_kind_of(rbProc, rb_cProc) || rb_respond_to(rbProc, id_call)) { if (fn->info->closurePool == NULL) { @@ -344,7 +352,7 @@ function_init(VALUE self, VALUE rbFunctionInfo, VALUE rbProc) rb_obj_classname(rbProc)); } - fn->rbProc = rbProc; + RB_OBJ_WRITE(self, &fn->rbProc, rbProc); return self; } @@ -360,7 +368,7 @@ function_call(int argc, VALUE* argv, VALUE self) { Function* fn; - Data_Get_Struct(self, Function, fn); + TypedData_Get_Struct(self, Function, &function_data_type, fn); return (*fn->info->invoke)(argc, argv, fn->base.memory.address, fn->info); } @@ -378,7 +386,7 @@ function_attach(VALUE self, VALUE module, VALUE name) Function* fn; char var[1024]; - Data_Get_Struct(self, Function, fn); + TypedData_Get_Struct(self, Function, &function_data_type, fn); if (fn->info->parameterCount == -1) { rb_raise(rb_eRuntimeError, "cannot attach variadic functions"); @@ -421,7 +429,7 @@ function_set_autorelease(VALUE self, VALUE autorelease) { Function* fn; - Data_Get_Struct(self, Function, fn); + TypedData_Get_Struct(self, Function, &function_data_type, fn); fn->autorelease = RTEST(autorelease); @@ -433,7 +441,7 @@ function_autorelease_p(VALUE self) { Function* fn; - Data_Get_Struct(self, Function, fn); + TypedData_Get_Struct(self, Function, &function_data_type, fn); return fn->autorelease ? Qtrue : Qfalse; } @@ -448,7 +456,7 @@ function_release(VALUE self) { Function* fn; - Data_Get_Struct(self, Function, fn); + TypedData_Get_Struct(self, Function, &function_data_type, fn); if (fn->closure == NULL) { rb_raise(rb_eRuntimeError, "cannot free function which was not allocated"); diff --git a/ext/ffi_c/Pointer.c b/ext/ffi_c/Pointer.c index 79886811f..89115a458 100644 --- a/ext/ffi_c/Pointer.c +++ b/ext/ffi_c/Pointer.c @@ -36,13 +36,50 @@ #include "AbstractMemory.h" #include "Pointer.h" -#define POINTER(obj) rbffi_AbstractMemory_Cast((obj), rbffi_PointerClass) +#define POINTER(obj) rbffi_Pointer_Cast((obj), rbffi_PointerClass) VALUE rbffi_PointerClass = Qnil; VALUE rbffi_NullPointerSingleton = Qnil; -static void ptr_release(Pointer* ptr); -static void ptr_mark(Pointer* ptr); +static void +ptr_release(void *data) +{ + Pointer *ptr = (Pointer *)data; + if (ptr->autorelease && ptr->allocated && ptr->storage != NULL) { + xfree(ptr->storage); + ptr->storage = NULL; + } + xfree(ptr); +} + +static void +ptr_mark(void *data) +{ + Pointer *ptr = (Pointer *)data; + rb_gc_mark(ptr->rbParent); +} + +static const rb_data_type_t pointer_data_type = { + .wrap_struct_name = "FFI::Pointer", + .function = { + .dmark = ptr_mark, + .dfree = ptr_release, + .dsize = NULL, + }, + .flags = RUBY_TYPED_FREE_IMMEDIATELY +}; + +Pointer* +rbffi_Pointer_Cast(VALUE obj, VALUE klass) +{ + if (rb_obj_is_kind_of(obj, klass)) { + Pointer* ptr = RTYPEDDATA_DATA(obj); + return ptr; + } + + rb_raise(rb_eArgError, "Invalid Pointer object"); + return NULL; +} VALUE rbffi_Pointer_NewInstance(void* addr) @@ -54,7 +91,7 @@ rbffi_Pointer_NewInstance(void* addr) return rbffi_NullPointerSingleton; } - obj = Data_Make_Struct(rbffi_PointerClass, Pointer, NULL, -1, p); + obj = TypedData_Make_Struct(rbffi_PointerClass, Pointer, &pointer_data_type, p); p->memory.address = addr; p->memory.size = LONG_MAX; p->memory.flags = (addr == NULL) ? 0 : (MEM_RD | MEM_WR); @@ -70,7 +107,7 @@ ptr_allocate(VALUE klass) Pointer* p; VALUE obj; - obj = Data_Make_Struct(klass, Pointer, ptr_mark, ptr_release, p); + obj = TypedData_Make_Struct(klass, Pointer, &pointer_data_type, p); p->rbParent = Qnil; p->memory.flags = MEM_RD | MEM_WR; @@ -91,12 +128,10 @@ ptr_allocate(VALUE klass) static VALUE ptr_initialize(int argc, VALUE* argv, VALUE self) { - Pointer* p; + Pointer* p = POINTER(self); VALUE rbType = Qnil, rbAddress = Qnil; int typeSize = 1; - Data_Get_Struct(self, Pointer, p); - switch (rb_scan_args(argc, argv, "11", &rbType, &rbAddress)) { case 1: rbAddress = rbType; @@ -121,10 +156,8 @@ ptr_initialize(int argc, VALUE* argv, VALUE self) default: if (rb_obj_is_kind_of(rbAddress, rbffi_PointerClass)) { - Pointer* orig; - p->rbParent = rbAddress; - Data_Get_Struct(rbAddress, Pointer, orig); + Pointer* orig = POINTER(rbAddress); p->memory = orig->memory; } else { rb_raise(rb_eTypeError, "wrong argument type, expected Integer or FFI::Pointer"); @@ -150,11 +183,9 @@ ptr_initialize(int argc, VALUE* argv, VALUE self) static VALUE ptr_initialize_copy(VALUE self, VALUE other) { - AbstractMemory* src; - Pointer* dst; + AbstractMemory* src = MEMORY(other); + Pointer* dst = POINTER(self); - Data_Get_Struct(self, Pointer, dst); - src = POINTER(other); if (src->size == LONG_MAX) { rb_raise(rb_eRuntimeError, "cannot duplicate unbounded memory area"); return Qnil; @@ -191,11 +222,10 @@ ptr_initialize_copy(VALUE self, VALUE other) static VALUE slice(VALUE self, long offset, long size) { - AbstractMemory* ptr; + AbstractMemory* ptr = MEMORY(self); Pointer* p; VALUE retval; - Data_Get_Struct(self, AbstractMemory, ptr); checkBounds(ptr, offset, size == LONG_MAX ? 1 : size); retval = Data_Make_Struct(rbffi_PointerClass, Pointer, ptr_mark, -1, p); @@ -219,12 +249,9 @@ slice(VALUE self, long offset, long size) static VALUE ptr_plus(VALUE self, VALUE offset) { - AbstractMemory* ptr; long off = NUM2LONG(offset); - - Data_Get_Struct(self, AbstractMemory, ptr); - - return slice(self, off, ptr->size == LONG_MAX ? LONG_MAX : ptr->size - off); + long size = MEMORY_LEN(self); + return slice(self, off, size == LONG_MAX ? LONG_MAX : size - off); } /* @@ -250,9 +277,7 @@ static VALUE ptr_inspect(VALUE self) { char buf[100]; - Pointer* ptr; - - Data_Get_Struct(self, Pointer, ptr); + Pointer* ptr = POINTER(self); if (ptr->memory.size != LONG_MAX) { snprintf(buf, sizeof(buf), "#<%s address=%p size=%lu>", @@ -273,11 +298,7 @@ ptr_inspect(VALUE self) static VALUE ptr_null_p(VALUE self) { - Pointer* ptr; - - Data_Get_Struct(self, Pointer, ptr); - - return ptr->memory.address == NULL ? Qtrue : Qfalse; + return MEMORY_PTR(self) == NULL ? Qtrue : Qfalse; } /* @@ -289,15 +310,11 @@ ptr_null_p(VALUE self) static VALUE ptr_equals(VALUE self, VALUE other) { - Pointer* ptr; - - Data_Get_Struct(self, Pointer, ptr); - if (NIL_P(other)) { - return ptr->memory.address == NULL ? Qtrue : Qfalse; + return MEMORY_PTR(self) == NULL ? Qtrue : Qfalse; } - return ptr->memory.address == POINTER(other)->address ? Qtrue : Qfalse; + return MEMORY_PTR(self) == MEMORY_PTR(other) ? Qtrue : Qfalse; } /* @@ -308,11 +325,7 @@ ptr_equals(VALUE self, VALUE other) static VALUE ptr_address(VALUE self) { - Pointer* ptr; - - Data_Get_Struct(self, Pointer, ptr); - - return ULL2NUM((uintptr_t) ptr->memory.address); + return ULL2NUM((uintptr_t)MEMORY_PTR(self)); } #if BYTE_ORDER == LITTLE_ENDIAN @@ -333,9 +346,8 @@ ptr_address(VALUE self) static VALUE ptr_order(int argc, VALUE* argv, VALUE self) { - Pointer* ptr; + Pointer* ptr = POINTER(self); - Data_Get_Struct(self, Pointer, ptr); if (argc == 0) { int order = (ptr->memory.flags & MEM_SWAP) == 0 ? BYTE_ORDER : SWAPPED_ORDER; return order == BIG_ENDIAN ? ID2SYM(rb_intern("big")) : ID2SYM(rb_intern("little")); @@ -358,10 +370,8 @@ ptr_order(int argc, VALUE* argv, VALUE self) } } if (order != BYTE_ORDER) { - Pointer* p2; VALUE retval = slice(self, 0, ptr->memory.size); - - Data_Get_Struct(retval, Pointer, p2); + Pointer* p2 = POINTER(retval); p2->memory.flags |= MEM_SWAP; return retval; } @@ -379,9 +389,7 @@ ptr_order(int argc, VALUE* argv, VALUE self) static VALUE ptr_free(VALUE self) { - Pointer* ptr; - - Data_Get_Struct(self, Pointer, ptr); + Pointer* ptr = POINTER(self); if (ptr->allocated) { if (ptr->storage != NULL) { @@ -402,10 +410,7 @@ ptr_free(VALUE self) static VALUE ptr_type_size(VALUE self) { - Pointer* ptr; - - Data_Get_Struct(self, Pointer, ptr); - + Pointer* ptr = POINTER(self); return INT2NUM(ptr->memory.typeSize); } @@ -418,11 +423,8 @@ ptr_type_size(VALUE self) static VALUE ptr_autorelease(VALUE self, VALUE autorelease) { - Pointer* ptr; - - Data_Get_Struct(self, Pointer, ptr); + Pointer* ptr = POINTER(self); ptr->autorelease = autorelease == Qtrue; - return autorelease; } @@ -434,30 +436,10 @@ ptr_autorelease(VALUE self, VALUE autorelease) static VALUE ptr_autorelease_p(VALUE self) { - Pointer* ptr; - - Data_Get_Struct(self, Pointer, ptr); - + Pointer* ptr = POINTER(self); return ptr->autorelease ? Qtrue : Qfalse; } - -static void -ptr_release(Pointer* ptr) -{ - if (ptr->autorelease && ptr->allocated && ptr->storage != NULL) { - xfree(ptr->storage); - ptr->storage = NULL; - } - xfree(ptr); -} - -static void -ptr_mark(Pointer* ptr) -{ - rb_gc_mark(ptr->rbParent); -} - void rbffi_Pointer_Init(VALUE moduleFFI) { diff --git a/ext/ffi_c/Pointer.h b/ext/ffi_c/Pointer.h index b3d6c85f1..e58d97aec 100644 --- a/ext/ffi_c/Pointer.h +++ b/ext/ffi_c/Pointer.h @@ -38,11 +38,6 @@ extern "C" { #include "AbstractMemory.h" -extern void rbffi_Pointer_Init(VALUE moduleFFI); -extern VALUE rbffi_Pointer_NewInstance(void* addr); -extern VALUE rbffi_PointerClass; -extern VALUE rbffi_NullPointerSingleton; - typedef struct Pointer { AbstractMemory memory; VALUE rbParent; @@ -51,6 +46,12 @@ typedef struct Pointer { bool allocated; } Pointer; +extern void rbffi_Pointer_Init(VALUE moduleFFI); +extern VALUE rbffi_Pointer_NewInstance(void* addr); +extern Pointer *rbffi_Pointer_Cast(VALUE obj, VALUE klass); +extern VALUE rbffi_PointerClass; +extern VALUE rbffi_NullPointerSingleton; + #ifdef __cplusplus } #endif diff --git a/ext/ffi_c/Struct.c b/ext/ffi_c/Struct.c index 92731c813..5a6fb3c76 100644 --- a/ext/ffi_c/Struct.c +++ b/ext/ffi_c/Struct.c @@ -61,8 +61,8 @@ typedef struct InlineArray_ { } InlineArray; -static void struct_mark(Struct *); -static void struct_free(Struct *); +static void struct_mark(void *); +static void struct_free(void *); static VALUE struct_class_layout(VALUE klass); static void struct_malloc(Struct* s); static void inline_array_mark(InlineArray *); @@ -76,6 +76,16 @@ VALUE rbffi_StructLayoutCharArrayClass = Qnil; static ID id_pointer_ivar = 0, id_layout_ivar = 0; static ID id_get = 0, id_put = 0, id_to_ptr = 0, id_to_s = 0, id_layout = 0; +static const rb_data_type_t struct_data_type = { + .wrap_struct_name = "FFI::Struct", + .function = { + .dmark = struct_mark, + .dfree = struct_free, + .dsize = NULL, + }, + .flags = RUBY_TYPED_FREE_IMMEDIATELY +}; + static inline char* memory_address(VALUE self) { @@ -86,7 +96,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, &struct_data_type, s); s->rbPointer = Qnil; s->rbLayout = Qnil; @@ -108,7 +118,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, &struct_data_type, s); nargs = rb_scan_args(argc, argv, "01*", &rbPointer, &rest); @@ -146,8 +156,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, &struct_data_type, dst); + TypedData_Get_Struct(other, Struct, &struct_data_type, src); if (dst == src) { return self; } @@ -213,7 +223,7 @@ static Struct* struct_validate(VALUE self) { Struct* s; - Data_Get_Struct(self, Struct, s); + TypedData_Get_Struct(self, Struct, &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, &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, &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, &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, &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, &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, &struct_data_type, s); if (argc == 0) { return rb_funcall(s->rbPointer, rb_intern("order"), 0); @@ -495,7 +507,7 @@ inline_array_allocate(VALUE klass) InlineArray* array; VALUE obj; - obj = Data_Make_Struct(klass, InlineArray, inline_array_mark, -1, array); + obj = Data_Make_Struct(klass, InlineArray, inline_array_mark, RUBY_DEFAULT_FREE, array); array->rbField = Qnil; array->rbMemory = Qnil; @@ -525,7 +537,7 @@ inline_array_initialize(VALUE self, VALUE rbMemory, VALUE rbField) array->rbMemory = rbMemory; array->rbField = rbField; - Data_Get_Struct(rbMemory, AbstractMemory, array->memory); + array->memory = rbffi_AbstractMemory_Cast(rbMemory, rbffi_AbstractMemoryClass); Data_Get_Struct(rbField, StructField, 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, &struct_data_type, s); checkRead(s->pointer); checkBounds(s->pointer, 0, array->componentType->ffiType->size);