summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWayne Meissner <wmeissner@gmail.com>2009-11-27 15:07:35 +1000
committerWayne Meissner <wmeissner@gmail.com>2009-11-27 15:07:35 +1000
commit9d68c7f87ad7c869ee1ce3139269525af70e5df4 (patch)
treebac4cdfc469e352d35cfaaa5d038e7b650d87f76
parent772b5c3d21406b58766ec641452343bb58f5b2ce (diff)
downloadffi-9d68c7f87ad7c869ee1ce3139269525af70e5df4.tar.gz
Add get/put functions on each internal StructField instance
-rw-r--r--ext/ffi_c/Struct.c35
-rw-r--r--ext/ffi_c/Struct.h18
-rw-r--r--ext/ffi_c/StructLayout.c52
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);