diff options
Diffstat (limited to 'ext/ffi_c/AbstractMemory.c')
-rw-r--r-- | ext/ffi_c/AbstractMemory.c | 90 |
1 files changed, 56 insertions, 34 deletions
diff --git a/ext/ffi_c/AbstractMemory.c b/ext/ffi_c/AbstractMemory.c index 1a7fcde..49da32e 100644 --- a/ext/ffi_c/AbstractMemory.c +++ b/ext/ffi_c/AbstractMemory.c @@ -55,21 +55,30 @@ # define RB_OBJ_STRING(obj) StringValueCStr(obj) #endif +static size_t memsize(const void *data); static inline char* memory_address(VALUE self); VALUE rbffi_AbstractMemoryClass = Qnil; static VALUE NullPointerErrorClass = Qnil; static ID id_to_ptr = 0, id_plus = 0, id_call = 0; -static VALUE -memory_allocate(VALUE klass) -{ - AbstractMemory* memory; - VALUE obj; - obj = Data_Make_Struct(klass, AbstractMemory, NULL, -1, memory); - memory->flags = MEM_RD | MEM_WR; +const rb_data_type_t rbffi_abstract_memory_data_type = { /* extern */ + .wrap_struct_name = "FFI::AbstractMemory", + .function = { + .dmark = NULL, + .dfree = RUBY_TYPED_DEFAULT_FREE, + .dsize = memsize, + }, + // IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE() + // macro to update VALUE references, as to trigger write barriers. + .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | FFI_RUBY_TYPED_FROZEN_SHAREABLE +}; - return obj; +static size_t +memsize(const void *data) +{ + return sizeof(AbstractMemory); } + #define VAL(x, swap) (unlikely(((memory->flags & MEM_SWAP) != 0)) ? swap((x)) : (x)) #define NUM_OP(name, type, toNative, fromNative, swap) \ @@ -87,7 +96,7 @@ static VALUE \ memory_put_##name(VALUE self, VALUE offset, VALUE value) \ { \ AbstractMemory* memory; \ - Data_Get_Struct(self, AbstractMemory, memory); \ + TypedData_Get_Struct(self, AbstractMemory, &rbffi_abstract_memory_data_type, memory); \ memory_op_put_##name(memory, NUM2LONG(offset), value); \ return self; \ } \ @@ -96,7 +105,7 @@ static VALUE \ memory_write_##name(VALUE self, VALUE value) \ { \ AbstractMemory* memory; \ - Data_Get_Struct(self, AbstractMemory, memory); \ + TypedData_Get_Struct(self, AbstractMemory, &rbffi_abstract_memory_data_type, memory); \ memory_op_put_##name(memory, 0, value); \ return self; \ } \ @@ -115,7 +124,7 @@ static VALUE \ memory_get_##name(VALUE self, VALUE offset) \ { \ AbstractMemory* memory; \ - Data_Get_Struct(self, AbstractMemory, memory); \ + TypedData_Get_Struct(self, AbstractMemory, &rbffi_abstract_memory_data_type, memory); \ return memory_op_get_##name(memory, NUM2LONG(offset)); \ } \ static VALUE memory_read_##name(VALUE self); \ @@ -123,7 +132,7 @@ static VALUE \ memory_read_##name(VALUE self) \ { \ AbstractMemory* memory; \ - Data_Get_Struct(self, AbstractMemory, memory); \ + TypedData_Get_Struct(self, AbstractMemory, &rbffi_abstract_memory_data_type, memory); \ return memory_op_get_##name(memory, 0); \ } \ static MemoryOp memory_op_##name = { memory_op_get_##name, memory_op_put_##name }; \ @@ -141,7 +150,7 @@ memory_put_array_of_##name(VALUE self, VALUE offset, VALUE ary) \ if (likely(count > 0)) checkWrite(memory); \ checkBounds(memory, off, count * sizeof(type)); \ for (i = 0; i < count; i++) { \ - type tmp = (type) VAL(toNative(RARRAY_PTR(ary)[i]), swap); \ + type tmp = (type) VAL(toNative(RARRAY_AREF(ary, i)), swap); \ memcpy(memory->address + off + (i * sizeof(type)), &tmp, sizeof(tmp)); \ } \ return self; \ @@ -307,6 +316,7 @@ static VALUE memory_clear(VALUE self) { AbstractMemory* ptr = MEMORY(self); + checkWrite(ptr); memset(ptr->address, 0, ptr->size); return self; } @@ -321,7 +331,7 @@ memory_size(VALUE self) { AbstractMemory* ptr; - Data_Get_Struct(self, AbstractMemory, ptr); + TypedData_Get_Struct(self, AbstractMemory, &rbffi_abstract_memory_data_type, ptr); return LONG2NUM(ptr->size); } @@ -344,8 +354,8 @@ memory_get(VALUE self, VALUE type_name, VALUE offset) nType = rbffi_Type_Lookup(type_name); if(NIL_P(nType)) goto undefined_type; - Data_Get_Struct(self, AbstractMemory, ptr); - Data_Get_Struct(nType, Type, type); + TypedData_Get_Struct(self, AbstractMemory, &rbffi_abstract_memory_data_type, ptr); + TypedData_Get_Struct(nType, Type, &rbffi_type_data_type, type); MemoryOp *op = get_memory_op(type); if(op == NULL) goto undefined_type; @@ -376,8 +386,8 @@ memory_put(VALUE self, VALUE type_name, VALUE offset, VALUE value) nType = rbffi_Type_Lookup(type_name); if(NIL_P(nType)) goto undefined_type; - Data_Get_Struct(self, AbstractMemory, ptr); - Data_Get_Struct(nType, Type, type); + TypedData_Get_Struct(self, AbstractMemory, &rbffi_abstract_memory_data_type, ptr); + TypedData_Get_Struct(nType, Type, &rbffi_type_data_type, type); MemoryOp *op = get_memory_op(type); if(op == NULL) goto undefined_type; @@ -442,7 +452,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); + TypedData_Get_Struct(self, AbstractMemory, &rbffi_abstract_memory_data_type, ptr); checkRead(ptr); if (countnum != Qnil) { @@ -633,7 +643,7 @@ memory_type_size(VALUE self) { AbstractMemory* ptr; - Data_Get_Struct(self, AbstractMemory, ptr); + TypedData_Get_Struct(self, AbstractMemory, &rbffi_abstract_memory_data_type, ptr); return INT2NUM(ptr->typeSize); } @@ -651,7 +661,7 @@ memory_aref(VALUE self, VALUE idx) AbstractMemory* ptr; VALUE rbOffset = Qnil; - Data_Get_Struct(self, AbstractMemory, ptr); + TypedData_Get_Struct(self, AbstractMemory, &rbffi_abstract_memory_data_type, ptr); rbOffset = ULONG2NUM(NUM2ULONG(idx) * ptr->typeSize); @@ -661,7 +671,9 @@ memory_aref(VALUE self, VALUE idx) static inline char* memory_address(VALUE obj) { - return ((AbstractMemory *) DATA_PTR(obj))->address; + AbstractMemory *mem; + TypedData_Get_Struct(obj, AbstractMemory, &rbffi_abstract_memory_data_type, mem); + return mem->address; } static VALUE @@ -669,24 +681,33 @@ memory_copy_from(VALUE self, VALUE rbsrc, VALUE rblen) { AbstractMemory* dst; - Data_Get_Struct(self, AbstractMemory, dst); + TypedData_Get_Struct(self, AbstractMemory, &rbffi_abstract_memory_data_type, dst); - memcpy(dst->address, rbffi_AbstractMemory_Cast(rbsrc, rbffi_AbstractMemoryClass)->address, NUM2INT(rblen)); + memcpy(dst->address, rbffi_AbstractMemory_Cast(rbsrc, &rbffi_abstract_memory_data_type)->address, NUM2INT(rblen)); return self; } -AbstractMemory* -rbffi_AbstractMemory_Cast(VALUE obj, VALUE klass) +/* + * call-seq: + * res.freeze + * + * Freeze the AbstractMemory object and unset the writable flag. + */ +static VALUE +memory_freeze(VALUE self) { - if (rb_obj_is_kind_of(obj, klass)) { - AbstractMemory* memory; - Data_Get_Struct(obj, AbstractMemory, memory); - return memory; - } + AbstractMemory* ptr = MEMORY(self); + ptr->flags &= ~MEM_WR; + return rb_call_super(0, NULL); +} - rb_raise(rb_eArgError, "Invalid Memory object"); - return NULL; +AbstractMemory* +rbffi_AbstractMemory_Cast(VALUE obj, const rb_data_type_t *data_type) +{ + AbstractMemory* memory; + TypedData_Get_Struct(obj, AbstractMemory, data_type, memory); + return memory; } void @@ -781,7 +802,7 @@ rbffi_AbstractMemory_Init(VALUE moduleFFI) * Document-variable: FFI::AbstractMemory */ rb_global_variable(&rbffi_AbstractMemoryClass); - rb_define_alloc_func(classMemory, memory_allocate); + rb_undef_alloc_func(classMemory); NullPointerErrorClass = rb_define_class_under(moduleFFI, "NullPointerError", rb_eRuntimeError); /* Document-variable: NullPointerError */ @@ -1096,6 +1117,7 @@ rbffi_AbstractMemory_Init(VALUE moduleFFI) rb_define_method(classMemory, "type_size", memory_type_size, 0); rb_define_method(classMemory, "[]", memory_aref, 1); rb_define_method(classMemory, "__copy_from__", memory_copy_from, 2); + rb_define_method(classMemory, "freeze", memory_freeze, 0 ); id_to_ptr = rb_intern("to_ptr"); id_call = rb_intern("call"); |