diff options
author | Wayne Meissner <wmeissner@gmail.com> | 2009-11-27 15:07:35 +1000 |
---|---|---|
committer | Wayne Meissner <wmeissner@gmail.com> | 2009-11-27 15:07:35 +1000 |
commit | 9d68c7f87ad7c869ee1ce3139269525af70e5df4 (patch) | |
tree | bac4cdfc469e352d35cfaaa5d038e7b650d87f76 | |
parent | 772b5c3d21406b58766ec641452343bb58f5b2ce (diff) | |
download | ffi-9d68c7f87ad7c869ee1ce3139269525af70e5df4.tar.gz |
Add get/put functions on each internal StructField instance
-rw-r--r-- | ext/ffi_c/Struct.c | 35 | ||||
-rw-r--r-- | ext/ffi_c/Struct.h | 18 | ||||
-rw-r--r-- | ext/ffi_c/StructLayout.c | 52 |
3 files changed, 69 insertions, 36 deletions
diff --git a/ext/ffi_c/Struct.c b/ext/ffi_c/Struct.c index 68c9db0..a75632f 100644 --- a/ext/ffi_c/Struct.c +++ b/ext/ffi_c/Struct.c @@ -177,13 +177,17 @@ struct_aref(VALUE self, VALUE fieldName) rbField = struct_field(s, fieldName); f = (StructField *) DATA_PTR(rbField); - op = memory_get_op(s->pointer, f->type); - if (op != NULL) { + if (f->get != NULL) { + return (*f->get)(f, s); + + } else if ((op = memory_get_op(s->pointer, f->type)) != NULL) { return (*op->get)(s->pointer, f->offset); - } + + } else { - /* call up to the ruby code to fetch the value */ - return rb_funcall2(rbField, id_get, 1, &s->rbPointer); + /* call up to the ruby code to fetch the value */ + return rb_funcall2(rbField, id_get, 1, &s->rbPointer); + } } static VALUE @@ -198,19 +202,22 @@ struct_aset(VALUE self, VALUE fieldName, VALUE value) Data_Get_Struct(self, Struct, s); rbField = struct_field(s, fieldName); f = (StructField *) DATA_PTR(rbField); + if (f->put != NULL) { + (*f->put)(f, s, value); + + } else if ((op = memory_get_op(s->pointer, f->type)) != NULL) { - op = memory_get_op(s->pointer, f->type); - if (op != NULL) { (*op->put)(s->pointer, f->offset, value); - return self; - } - /* call up to the ruby code to set the value */ - argv[0] = s->rbPointer; - argv[1] = value; - rb_funcall2(rbField, id_put, 2, argv); + } else { + + /* call up to the ruby code to set the value */ + argv[0] = s->rbPointer; + argv[1] = value; + rb_funcall2(rbField, id_put, 2, argv); + } - return self; + return value; } static VALUE diff --git a/ext/ffi_c/Struct.h b/ext/ffi_c/Struct.h index bd9a53c..ba79818 100644 --- a/ext/ffi_c/Struct.h +++ b/ext/ffi_c/Struct.h @@ -39,16 +39,22 @@ extern "C" { extern void rbffi_Struct_Init(VALUE ffiModule); extern void rbffi_StructLayout_Init(VALUE ffiModule); + typedef struct StructField_ StructField; + typedef struct StructLayout_ StructLayout; + typedef struct Struct_ Struct; - typedef struct StructField_ { + struct StructField_ { Type* type; unsigned int offset; VALUE rbType; VALUE rbName; - } StructField; - typedef struct StructLayout_ { + VALUE (*get)(StructField* field, Struct* s); + void (*put)(StructField* field, Struct* s, VALUE value); + }; + + struct StructLayout_ { Type base; StructField** fields; unsigned int fieldCount; @@ -58,14 +64,14 @@ extern "C" { VALUE rbFieldNames; VALUE rbFieldMap; VALUE rbFields; - } StructLayout; + }; - typedef struct Struct { + struct Struct_ { StructLayout* layout; AbstractMemory* pointer; VALUE rbLayout; VALUE rbPointer; - } Struct; + }; extern VALUE rbffi_StructClass, rbffi_StructLayoutClass; extern VALUE rbffi_StructLayoutFieldClass, rbffi_StructLayoutFunctionFieldClass; diff --git a/ext/ffi_c/StructLayout.c b/ext/ffi_c/StructLayout.c index 86dad2e..a9aa796 100644 --- a/ext/ffi_c/StructLayout.c +++ b/ext/ffi_c/StructLayout.c @@ -50,6 +50,8 @@ static void struct_layout_mark(StructLayout *); static void struct_layout_free(StructLayout *); static void struct_field_mark(StructField* ); +static VALUE enum_field_op_get(StructField* f, Struct* s); +static void enum_field_op_put(StructField* f, Struct* s, VALUE value); VALUE rbffi_StructLayoutFieldClass = Qnil; VALUE rbffi_StructLayoutFunctionFieldClass = Qnil, rbffi_StructLayoutArrayFieldClass = Qnil; @@ -263,39 +265,56 @@ inline_struct_field_get(VALUE self, VALUE pointer) } static VALUE +enum_field_allocate(VALUE klass) +{ + StructField* field; + VALUE obj = struct_field_allocate(klass); + + field = (StructField *) DATA_PTR(obj); + + field->get = enum_field_op_get; + field->put = enum_field_op_put; + + return obj; +} + +static VALUE +enum_field_op_get(StructField* f, Struct* s) +{ + VALUE value = (*rbffi_AbstractMemoryOps.int32->get)(s->pointer, f->offset); + + return rb_funcall2(f->rbType, rb_intern("find"), 1, &value); +} + +static void +enum_field_op_put(StructField* f, Struct* s, VALUE value) +{ + (*rbffi_AbstractMemoryOps.int32->put)(s->pointer, f->offset, rb_funcall2(f->rbType, rb_intern("find"), 1, &value)); +} + +static VALUE enum_field_get(VALUE self, VALUE pointer) { StructField* f; - MemoryOp* op; + VALUE value; AbstractMemory* memory = MEMORY(pointer); Data_Get_Struct(self, StructField, f); - op = memory->ops->int32; - if (op == NULL) { - rb_raise(rb_eArgError, "get not supported for %s", rb_obj_classname(self)); - return Qnil; - } + value = (*rbffi_AbstractMemoryOps.int32->get)(memory, f->offset); - return rb_funcall(f->rbType, rb_intern("find"), 1, (*op->get)(memory, f->offset)); + return rb_funcall2(f->rbType, rb_intern("find"), 1, &value); } static VALUE enum_field_put(VALUE self, VALUE pointer, VALUE value) { StructField* f; - MemoryOp* op; AbstractMemory* memory = MEMORY(pointer); Data_Get_Struct(self, StructField, f); - op = memory->ops->int32; - if (op == NULL) { - rb_raise(rb_eArgError, "put not supported for %s", rb_obj_classname(self)); - return Qnil; - } - - (*op->put)(memory, f->offset, rb_funcall2(f->rbType, rb_intern("find"), 1, &value)); + (*rbffi_AbstractMemoryOps.int32->put)(memory, f->offset, rb_funcall2(f->rbType, rb_intern("find"), 1, &value)); - return self; + return value; } static VALUE @@ -470,6 +489,7 @@ rbffi_StructLayout_Init(VALUE moduleFFI) rb_define_method(rbffi_StructLayoutArrayFieldClass, "get", array_field_get, 1); rb_define_method(rbffi_StructLayoutStructFieldClass, "get", inline_struct_field_get, 1); + rb_define_alloc_func(rbffi_StructLayoutEnumFieldClass, enum_field_allocate); rb_define_method(rbffi_StructLayoutEnumFieldClass, "put", enum_field_put, 2); rb_define_method(rbffi_StructLayoutEnumFieldClass, "get", enum_field_get, 1); |