ffi 0.3.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of ffi might be problematic. Click here for more details.

data/Rakefile CHANGED
@@ -31,9 +31,8 @@ PROJ.name = 'ffi'
31
31
  PROJ.authors = 'Wayne Meissner'
32
32
  PROJ.email = 'wmeissner@gmail.com'
33
33
  PROJ.url = 'http://kenai.com/projects/ruby-ffi'
34
- PROJ.version = '0.3.0'
34
+ PROJ.version = '0.3.1'
35
35
  PROJ.rubyforge.name = 'ffi'
36
-
37
36
  PROJ.readme_file = 'README.rdoc'
38
37
 
39
38
  # Annoucement
@@ -52,6 +51,13 @@ PROJ.gem.extensions = %w(ext/ffi_c/extconf.rb gen/Rakefile)
52
51
  PROJ.rdoc.exclude << '^ext\/'
53
52
  PROJ.rdoc.opts << '-x' << 'ext'
54
53
 
54
+ # Ruby
55
+ PROJ.ruby_opts = []
56
+ PROJ.ruby_opts << '-I' << "\"#{BUILD_DIR}\"" unless RUBY_PLATFORM == "java"
57
+
58
+ #RSpec
59
+ PROJ.spec.opts << '--color' << '-fs'
60
+
55
61
  TEST_DEPS = [ LIBTEST ]
56
62
  if RUBY_PLATFORM == "java"
57
63
  desc "Run all specs"
@@ -121,3 +127,6 @@ namespace :bench do
121
127
  end
122
128
  end
123
129
  end
130
+
131
+ task 'spec:run' => TEST_DEPS
132
+ task 'spec:specdoc' => TEST_DEPS
@@ -9,41 +9,60 @@
9
9
  #include "Pointer.h"
10
10
  #include "Callback.h"
11
11
 
12
- static VALUE memory_put_float32(VALUE self, VALUE offset, VALUE value);
13
- static VALUE memory_get_float32(VALUE self, VALUE offset);
14
- static VALUE memory_put_float64(VALUE self, VALUE offset, VALUE value);
15
- static VALUE memory_get_float64(VALUE self, VALUE offset);
16
- static VALUE memory_put_pointer(VALUE self, VALUE offset, VALUE value);
17
- static VALUE memory_get_pointer(VALUE self, VALUE offset);
18
12
 
19
13
  static inline char* memory_address(VALUE self);
20
14
  VALUE rb_FFI_AbstractMemory_class = Qnil;
21
15
  static VALUE classMemory = Qnil;
22
16
  static ID to_ptr = 0;
23
17
 
18
+ static VALUE
19
+ memory_allocate(VALUE klass)
20
+ {
21
+ AbstractMemory* memory;
22
+ VALUE obj;
23
+ obj = Data_Make_Struct(klass, AbstractMemory, NULL, -1, memory);
24
+ memory->ops = &rb_FFI_AbstractMemory_ops;
25
+
26
+ return obj;
27
+ }
28
+
24
29
  #define NUM_OP(name, type, toNative, fromNative) \
25
- static VALUE memory_put_##name(VALUE self, VALUE offset, VALUE value); \
26
- static VALUE \
27
- memory_put_##name(VALUE self, VALUE offset, VALUE value) \
30
+ static void memory_op_put_##name(AbstractMemory* memory, long off, VALUE value); \
31
+ static void \
32
+ memory_op_put_##name(AbstractMemory* memory, long off, VALUE value) \
28
33
  { \
29
- long off = NUM2LONG(offset); \
30
- AbstractMemory* memory = MEMORY(self); \
31
34
  type tmp = (type) toNative(value); \
32
35
  checkBounds(memory, off, sizeof(type)); \
33
36
  memcpy(memory->address + off, &tmp, sizeof(tmp)); \
37
+ } \
38
+ static VALUE memory_put_##name(VALUE self, VALUE offset, VALUE value); \
39
+ static VALUE \
40
+ memory_put_##name(VALUE self, VALUE offset, VALUE value) \
41
+ { \
42
+ AbstractMemory* memory; \
43
+ Data_Get_Struct(self, AbstractMemory, memory); \
44
+ memory_op_put_##name(memory, NUM2LONG(offset), value); \
34
45
  return self; \
35
46
  } \
36
- static VALUE memory_get_##name(VALUE self, VALUE offset); \
47
+ static VALUE memory_op_get_##name(AbstractMemory* memory, long off); \
37
48
  static VALUE \
38
- memory_get_##name(VALUE self, VALUE offset) \
49
+ memory_op_get_##name(AbstractMemory* memory, long off) \
39
50
  { \
40
- long off = NUM2LONG(offset); \
41
- AbstractMemory* memory = MEMORY(self); \
42
51
  type tmp; \
43
52
  checkBounds(memory, off, sizeof(type)); \
44
53
  memcpy(&tmp, memory->address + off, sizeof(tmp)); \
45
54
  return fromNative(tmp); \
46
55
  } \
56
+ static VALUE memory_get_##name(VALUE self, VALUE offset); \
57
+ static VALUE \
58
+ memory_get_##name(VALUE self, VALUE offset) \
59
+ { \
60
+ AbstractMemory* memory; \
61
+ Data_Get_Struct(self, AbstractMemory, memory); \
62
+ return memory_op_get_##name(memory, NUM2LONG(offset)); \
63
+ } \
64
+ static MemoryOp memory_op_##name = { memory_op_get_##name, memory_op_put_##name }; \
65
+ \
47
66
  static VALUE memory_put_array_of_##name(VALUE self, VALUE offset, VALUE ary); \
48
67
  static VALUE \
49
68
  memory_put_array_of_##name(VALUE self, VALUE offset, VALUE ary) \
@@ -88,11 +107,9 @@ NUM_OP(uint64, uint64_t, NUM2ULL, ULL2NUM);
88
107
  NUM_OP(float32, float, NUM2DBL, rb_float_new);
89
108
  NUM_OP(float64, double, NUM2DBL, rb_float_new);
90
109
 
91
- static VALUE
92
- memory_put_pointer(VALUE self, VALUE offset, VALUE value)
110
+ static void
111
+ memory_op_put_pointer(AbstractMemory* memory, long off, VALUE value)
93
112
  {
94
- AbstractMemory* memory = MEMORY(self);
95
- long off = NUM2LONG(offset);
96
113
  const int type = TYPE(value);
97
114
  checkBounds(memory, off, sizeof(void *));
98
115
 
@@ -115,20 +132,39 @@ memory_put_pointer(VALUE self, VALUE offset, VALUE value)
115
132
  } else {
116
133
  rb_raise(rb_eArgError, "value is not a pointer");
117
134
  }
118
- return self;
119
135
  }
120
136
 
121
137
  static VALUE
122
- memory_get_pointer(VALUE self, VALUE offset)
138
+ memory_op_get_pointer(AbstractMemory* memory, long off)
123
139
  {
124
- AbstractMemory* memory = MEMORY(self);
125
- long off = NUM2LONG(offset);
126
140
  void* tmp;
141
+
127
142
  checkBounds(memory, off, sizeof(tmp));
128
143
  memcpy(&tmp, memory->address + off, sizeof(tmp));
129
144
  return rb_FFI_Pointer_new(tmp);
130
145
  }
131
146
 
147
+ static VALUE
148
+ memory_put_pointer(VALUE self, VALUE offset, VALUE value)
149
+ {
150
+ AbstractMemory* memory;
151
+
152
+ Data_Get_Struct(self, AbstractMemory, memory);
153
+ memory_op_put_pointer(memory, NUM2LONG(offset), value);
154
+
155
+ return self;
156
+ }
157
+
158
+ static VALUE
159
+ memory_get_pointer(VALUE self, VALUE offset)
160
+ {
161
+ AbstractMemory* memory;
162
+
163
+ Data_Get_Struct(self, AbstractMemory, memory);
164
+
165
+ return memory_op_get_pointer(memory, NUM2LONG(offset));
166
+ }
167
+
132
168
  static VALUE
133
169
  memory_put_callback(VALUE self, VALUE offset, VALUE proc, VALUE cbInfo)
134
170
  {
@@ -184,8 +220,10 @@ memory_put_string(VALUE self, VALUE offset, VALUE str)
184
220
  AbstractMemory* ptr = MEMORY(self);
185
221
  long off, len;
186
222
 
223
+ Check_Type(str, T_STRING);
187
224
  off = NUM2LONG(offset);
188
225
  len = RSTRING_LEN(str);
226
+
189
227
  checkBounds(ptr, off, len);
190
228
  if (rb_safe_level() >= 1 && OBJ_TAINTED(str)) {
191
229
  rb_raise(rb_eSecurityError, "Writing unsafe string to memory");
@@ -215,6 +253,8 @@ memory_put_bytes(int argc, VALUE* argv, VALUE self)
215
253
  long off, len, idx;
216
254
  int nargs = rb_scan_args(argc, argv, "22", &offset, &str, &rbIndex, &rbLength);
217
255
 
256
+ Check_Type(str, T_STRING);
257
+
218
258
  off = NUM2LONG(offset);
219
259
  idx = nargs > 2 ? NUM2LONG(rbIndex) : 0;
220
260
  if (idx < 0) {
@@ -249,11 +289,51 @@ rb_FFI_AbstractMemory_cast(VALUE obj, VALUE klass)
249
289
  rb_raise(rb_eArgError, "Invalid Memory object");
250
290
  }
251
291
 
292
+ static VALUE
293
+ memory_op_get_strptr(AbstractMemory* ptr, long offset)
294
+ {
295
+ void* tmp = NULL;
296
+
297
+ if (ptr != NULL && ptr->address != NULL) {
298
+ checkBounds(ptr, offset, sizeof(tmp));
299
+ memcpy(&tmp, ptr->address + offset, sizeof(tmp));
300
+ }
301
+
302
+ return tmp != NULL ? rb_tainted_str_new2(tmp) : Qnil;
303
+ }
304
+
305
+ static void
306
+ memory_op_put_strptr(AbstractMemory* ptr, long offset, VALUE value)
307
+ {
308
+ rb_raise(rb_eArgError, "Cannot set :string fields");
309
+ }
310
+
311
+ static MemoryOp memory_op_strptr = { memory_op_get_strptr, memory_op_put_strptr };
312
+
313
+ static MemoryOp memory_op_pointer = { memory_op_get_pointer, memory_op_put_pointer };
314
+
315
+ MemoryOps rb_FFI_AbstractMemory_ops = {
316
+ .int8 = &memory_op_int8,
317
+ .uint8 = &memory_op_uint8,
318
+ .int16 = &memory_op_int16,
319
+ .uint16 = &memory_op_uint16,
320
+ .int32 = &memory_op_int32,
321
+ .uint32 = &memory_op_uint32,
322
+ .int64 = &memory_op_int64,
323
+ .uint64 = &memory_op_uint64,
324
+ .float32 = &memory_op_float32,
325
+ .float64 = &memory_op_float64,
326
+ .pointer = &memory_op_pointer,
327
+ .strptr = &memory_op_strptr,
328
+ };
329
+
252
330
  void
253
331
  rb_FFI_AbstractMemory_Init()
254
332
  {
255
333
  VALUE moduleFFI = rb_define_module("FFI");
256
334
  rb_FFI_AbstractMemory_class = classMemory = rb_define_class_under(moduleFFI, "AbstractMemory", rb_cObject);
335
+
336
+ rb_define_alloc_func(classMemory, memory_allocate);
257
337
  #undef INT
258
338
  #define INT(type) \
259
339
  rb_define_method(classMemory, "put_" #type, memory_put_##type, 2); \
@@ -9,10 +9,34 @@
9
9
  extern "C" {
10
10
  #endif
11
11
 
12
+ typedef struct AbstractMemory_ AbstractMemory;
13
+
14
+ typedef struct {
15
+ VALUE (*get)(AbstractMemory* ptr, long offset);
16
+ void (*put)(AbstractMemory* ptr, long offset, VALUE value);
17
+ } MemoryOp;
18
+
12
19
  typedef struct {
20
+ MemoryOp* int8;
21
+ MemoryOp* uint8;
22
+ MemoryOp* int16;
23
+ MemoryOp* uint16;
24
+ MemoryOp* int32;
25
+ MemoryOp* uint32;
26
+ MemoryOp* int64;
27
+ MemoryOp* uint64;
28
+ MemoryOp* float32;
29
+ MemoryOp* float64;
30
+ MemoryOp* pointer;
31
+ MemoryOp* strptr;
32
+ } MemoryOps;
33
+
34
+ struct AbstractMemory_ {
13
35
  char* address; // Use char* instead of void* to ensure adding to it works correctly
14
36
  long size;
15
- } AbstractMemory;
37
+ MemoryOps* ops;
38
+ };
39
+
16
40
 
17
41
  static inline void
18
42
  checkBounds(AbstractMemory* mem, long off, long len)
@@ -30,6 +54,8 @@ checkBounds(AbstractMemory* mem, long off, long len)
30
54
  extern AbstractMemory* rb_FFI_AbstractMemory_cast(VALUE obj, VALUE klass);
31
55
 
32
56
  extern VALUE rb_FFI_AbstractMemory_class;
57
+ extern MemoryOps rb_FFI_AbstractMemory_ops;
58
+
33
59
  #ifdef __cplusplus
34
60
  }
35
61
  #endif
@@ -13,17 +13,20 @@ typedef struct AutoPointer {
13
13
  VALUE parent;
14
14
  } AutoPointer;
15
15
 
16
- VALUE rb_FFI_AutoPointer_class;
17
- static VALUE classAutoPointer = Qnil;
18
16
  static void autoptr_mark(AutoPointer* ptr);
19
- static void autoptr_free(AutoPointer* ptr);
17
+ static VALUE autoptr_allocate(VALUE klass);
18
+ static VALUE autoptr_set_parent(VALUE self, VALUE parent);
19
+
20
+ VALUE rb_FFI_AutoPointer_class = Qnil;
20
21
 
21
22
  static VALUE
22
23
  autoptr_allocate(VALUE klass)
23
24
  {
24
25
  AutoPointer* p;
25
- VALUE obj = Data_Make_Struct(klass, AutoPointer, autoptr_mark, autoptr_free, p);
26
+ VALUE obj = Data_Make_Struct(klass, AutoPointer, autoptr_mark, -1, p);
26
27
  p->parent = Qnil;
28
+ p->memory.ops = &rb_FFI_AbstractMemory_ops;
29
+
27
30
  return obj;
28
31
  }
29
32
 
@@ -43,21 +46,16 @@ autoptr_set_parent(VALUE self, VALUE parent)
43
46
  static void
44
47
  autoptr_mark(AutoPointer* ptr)
45
48
  {
46
- if (ptr->parent != Qnil) {
47
- rb_gc_mark(ptr->parent);
48
- }
49
- }
50
- static void
51
- autoptr_free(AutoPointer* ptr)
52
- {
53
- xfree(ptr);
49
+ rb_gc_mark(ptr->parent);
54
50
  }
55
51
 
56
52
  void
57
53
  rb_FFI_AutoPointer_Init()
58
54
  {
59
55
  VALUE moduleFFI = rb_define_module("FFI");
60
- rb_FFI_AutoPointer_class = classAutoPointer = rb_define_class_under(moduleFFI, "AutoPointer", rb_FFI_Pointer_class);
61
- rb_define_alloc_func(classAutoPointer, autoptr_allocate);
62
- rb_define_protected_method(classAutoPointer, "parent=", autoptr_set_parent, 1);
56
+ rb_FFI_AutoPointer_class = rb_define_class_under(moduleFFI, "AutoPointer", rb_FFI_Pointer_class);
57
+ rb_global_variable(&rb_FFI_AutoPointer_class);
58
+
59
+ rb_define_alloc_func(rb_FFI_AutoPointer_class, autoptr_allocate);
60
+ rb_define_protected_method(rb_FFI_AutoPointer_class, "parent=", autoptr_set_parent, 1);
63
61
  }
@@ -25,7 +25,24 @@ static VALUE
25
25
  buffer_allocate(VALUE klass)
26
26
  {
27
27
  Buffer* buffer;
28
- return Data_Make_Struct(klass, Buffer, buffer_mark, buffer_release, buffer);
28
+ VALUE obj;
29
+
30
+ obj = Data_Make_Struct(klass, Buffer, NULL, buffer_release, buffer);
31
+ buffer->parent = Qnil;
32
+ buffer->memory.ops = &rb_FFI_AbstractMemory_ops;
33
+
34
+ return obj;
35
+ }
36
+
37
+ static void
38
+ buffer_release(Buffer* ptr)
39
+ {
40
+ if (ptr->storage != NULL) {
41
+ free(ptr->storage);
42
+ ptr->storage = NULL;
43
+ }
44
+
45
+ xfree(ptr);
29
46
  }
30
47
 
31
48
  static VALUE
@@ -34,27 +51,30 @@ buffer_initialize(int argc, VALUE* argv, VALUE self)
34
51
  VALUE size = Qnil, count = Qnil, clear = Qnil;
35
52
  Buffer* p;
36
53
  unsigned long msize;
37
- void* memory;
38
54
  int nargs;
39
-
55
+
40
56
  nargs = rb_scan_args(argc, argv, "12", &size, &count, &clear);
41
57
  msize = rb_FFI_type_size(size) * (nargs > 1 ? NUM2LONG(count) : 1);
42
- memory = malloc(msize + 7);
43
- if (memory == NULL) {
44
- rb_raise(rb_eNoMemError, "Failed to allocate memory size=%lu bytes", msize);
45
- }
58
+
46
59
  Data_Get_Struct(self, Buffer, p);
47
- p->storage = memory;
48
60
  p->memory.size = msize;
61
+
62
+ p->storage = malloc(msize + 7);
63
+ if (p->storage == NULL) {
64
+ rb_raise(rb_eNoMemError, "Failed to allocate memory size=%lu bytes", msize);
65
+ }
66
+
49
67
  /* ensure the memory is aligned on at least a 8 byte boundary */
50
- p->memory.address = (void *) (((uintptr_t) memory + 0x7) & (uintptr_t) ~0x7UL);
51
- p->parent = Qnil;
68
+ p->memory.address = (void *) (((uintptr_t) p->storage + 0x7) & (uintptr_t) ~0x7UL);
69
+
52
70
  if (nargs > 2 && RTEST(clear) && p->memory.size > 0) {
53
71
  memset(p->memory.address, 0, p->memory.size);
54
72
  }
73
+
55
74
  if (rb_block_given_p()) {
56
- return rb_rescue(rb_yield, self, buffer_free, self);
75
+ return rb_ensure(rb_yield, self, buffer_free, self);
57
76
  }
77
+
58
78
  return self;
59
79
  }
60
80
 
@@ -73,10 +93,13 @@ buffer_plus(VALUE self, VALUE offset)
73
93
  long off = NUM2LONG(offset);
74
94
 
75
95
  checkBounds(&ptr->memory, off, 1);
76
- retval = Data_Make_Struct(classBuffer, Buffer, buffer_mark, buffer_release, p);
77
- p->memory.address = ptr->memory.address + off;;
96
+
97
+ retval = Data_Make_Struct(classBuffer, Buffer, buffer_mark, -1, p);
98
+ p->memory.address = ptr->memory.address + off;
78
99
  p->memory.size = ptr->memory.size - off;
100
+ p->memory.ops = &rb_FFI_AbstractMemory_ops;
79
101
  p->parent = self;
102
+
80
103
  return retval;
81
104
  }
82
105
 
@@ -84,7 +107,9 @@ static VALUE
84
107
  buffer_inspect(VALUE self)
85
108
  {
86
109
  char tmp[100];
110
+
87
111
  snprintf(tmp, sizeof(tmp), "#<Buffer size=%ld>", BUFFER(self)->memory.size);
112
+
88
113
  return rb_str_new2(tmp);
89
114
  }
90
115
 
@@ -92,30 +117,21 @@ buffer_inspect(VALUE self)
92
117
  static VALUE
93
118
  buffer_free(VALUE self)
94
119
  {
95
- Buffer* ptr = BUFFER(self);
96
- if (ptr->parent == Qnil && ptr->storage != NULL) {
97
- free(ptr->storage);
98
- ptr->storage = NULL;
99
- }
100
- return self;
101
- }
120
+ Buffer* ptr;
102
121
 
103
- static void
104
- buffer_release(Buffer* ptr)
105
- {
106
- if (ptr->parent == Qnil && ptr->storage != NULL) {
122
+ Data_Get_Struct(self, Buffer, ptr);
123
+ if (ptr->storage != NULL) {
107
124
  free(ptr->storage);
108
125
  ptr->storage = NULL;
109
126
  }
110
- xfree(ptr);
127
+
128
+ return self;
111
129
  }
112
130
 
113
131
  static void
114
132
  buffer_mark(Buffer* ptr)
115
133
  {
116
- if (ptr->parent != Qnil) {
117
- rb_gc_mark(ptr->parent);
118
- }
134
+ rb_gc_mark(ptr->parent);
119
135
  }
120
136
 
121
137
  void
@@ -123,6 +139,8 @@ rb_FFI_Buffer_Init()
123
139
  {
124
140
  VALUE moduleFFI = rb_define_module("FFI");
125
141
  classBuffer = rb_define_class_under(moduleFFI, "Buffer", rb_FFI_AbstractMemory_class);
142
+
143
+ rb_global_variable(&classBuffer);
126
144
  rb_define_alloc_func(classBuffer, buffer_allocate);
127
145
 
128
146
  rb_define_singleton_method(classBuffer, "alloc_inout", buffer_alloc_inout, -1);
@@ -133,4 +151,3 @@ rb_FFI_Buffer_Init()
133
151
  rb_define_method(classBuffer, "inspect", buffer_inspect, 0);
134
152
  rb_define_method(classBuffer, "+", buffer_plus, 1);
135
153
  }
136
-