ffi 0.1.1 → 0.2.0

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.

Files changed (62) hide show
  1. data/Rakefile +52 -29
  2. data/ext/AbstractMemory.c +72 -28
  3. data/ext/AutoPointer.c +54 -0
  4. data/ext/AutoPointer.h +18 -0
  5. data/ext/Buffer.c +21 -17
  6. data/ext/Callback.c +81 -43
  7. data/ext/Callback.h +1 -1
  8. data/ext/Invoker.c +465 -108
  9. data/ext/MemoryPointer.c +25 -90
  10. data/ext/NativeLibrary.c +90 -0
  11. data/ext/NativeLibrary.h +22 -0
  12. data/ext/Platform.c +21 -2
  13. data/ext/Pointer.c +107 -0
  14. data/ext/Pointer.h +21 -0
  15. data/ext/Types.c +16 -5
  16. data/ext/Types.h +3 -1
  17. data/ext/compat.h +14 -0
  18. data/ext/extconf.rb +13 -1
  19. data/ext/ffi.c +11 -1
  20. data/ext/ffi.mk +3 -3
  21. data/ext/libffi.darwin.mk +19 -8
  22. data/gen/Rakefile +12 -0
  23. data/lib/ffi/autopointer.rb +61 -0
  24. data/lib/ffi/errno.rb +8 -0
  25. data/lib/ffi/ffi.rb +38 -201
  26. data/lib/ffi/io.rb +7 -0
  27. data/lib/ffi/library.rb +116 -0
  28. data/lib/ffi/managedstruct.rb +55 -0
  29. data/lib/ffi/memorypointer.rb +3 -96
  30. data/lib/ffi/platform.rb +8 -5
  31. data/lib/ffi/pointer.rb +105 -0
  32. data/lib/ffi/struct.rb +97 -42
  33. data/lib/ffi/tools/const_generator.rb +177 -0
  34. data/lib/ffi/tools/generator.rb +58 -0
  35. data/lib/ffi/tools/generator_task.rb +35 -0
  36. data/lib/ffi/tools/struct_generator.rb +194 -0
  37. data/lib/ffi/tools/types_generator.rb +123 -0
  38. data/lib/ffi/types.rb +150 -0
  39. data/lib/ffi/variadic.rb +30 -0
  40. data/nbproject/Makefile-Default.mk +6 -3
  41. data/nbproject/Makefile-impl.mk +5 -5
  42. data/nbproject/Package-Default.bash +72 -0
  43. data/nbproject/configurations.xml +139 -25
  44. data/nbproject/private/configurations.xml +1 -1
  45. data/nbproject/project.xml +4 -0
  46. data/samples/gettimeofday.rb +6 -2
  47. data/samples/inotify.rb +59 -0
  48. data/samples/pty.rb +75 -0
  49. data/specs/buffer_spec.rb +64 -9
  50. data/specs/callback_spec.rb +308 -4
  51. data/specs/errno_spec.rb +13 -0
  52. data/specs/library_spec.rb +55 -0
  53. data/specs/managed_struct_spec.rb +40 -0
  54. data/specs/number_spec.rb +183 -0
  55. data/specs/pointer_spec.rb +126 -0
  56. data/specs/rbx/memory_pointer_spec.rb +7 -7
  57. data/specs/spec_helper.rb +7 -0
  58. data/specs/string_spec.rb +34 -0
  59. data/specs/struct_spec.rb +223 -0
  60. data/specs/typedef_spec.rb +48 -0
  61. data/specs/variadic_spec.rb +84 -0
  62. metadata +270 -237
@@ -4,113 +4,65 @@
4
4
  #include <ruby.h>
5
5
  #include "rbffi.h"
6
6
  #include "AbstractMemory.h"
7
+ #include "Pointer.h"
7
8
  #include "MemoryPointer.h"
8
9
 
9
10
  typedef struct MemoryPointer {
10
11
  AbstractMemory memory;
11
- VALUE parent;
12
+ caddr_t address;
12
13
  bool autorelease;
13
14
  bool allocated;
14
15
  } MemoryPointer;
15
16
 
16
17
  static VALUE memptr_allocate(VALUE self, VALUE size, VALUE count, VALUE clear);
17
18
  static void memptr_release(MemoryPointer* ptr);
18
- static void memptr_mark(MemoryPointer* ptr);
19
19
 
20
20
  VALUE rb_FFI_MemoryPointer_class;
21
21
  static VALUE classMemoryPointer = Qnil;
22
22
 
23
- VALUE
24
- rb_FFI_MemoryPointer_new(caddr_t addr)
25
- {
26
- MemoryPointer* p;
27
-
28
- p = ALLOC(MemoryPointer);
29
- memset(p, 0, sizeof(*p));
30
- p->memory.address = addr;
31
- p->memory.size = LONG_MAX;
32
- p->parent = Qnil;
33
- return Data_Wrap_Struct(classMemoryPointer, memptr_mark, memptr_release, p);
34
- }
35
-
36
23
  static VALUE
37
24
  memptr_allocate(VALUE self, VALUE size, VALUE count, VALUE clear)
38
25
  {
39
26
  MemoryPointer* p;
40
-
41
- p = ALLOC(MemoryPointer);
42
- memset(p, 0, sizeof(*p));
27
+ VALUE retval;
28
+ caddr_t memory;
29
+ unsigned long msize = NUM2LONG(size) * (count == Qnil ? 1 : NUM2LONG(count));
30
+ memory = malloc(msize + 7);
31
+ if (memory == NULL) {
32
+ rb_raise(rb_eNoMemError, "Failed to allocate memory size=%ld bytes", msize);
33
+ }
34
+ retval = Data_Make_Struct(classMemoryPointer, MemoryPointer, NULL, memptr_release, p);
35
+ p->address = memory;
43
36
  p->autorelease = true;
44
- p->memory.size = NUM2LONG(size) * (count == Qnil ? 1 : NUM2LONG(count));
45
- p->memory.address = p->memory.size > 0 ? malloc(p->memory.size) : NULL;
46
- p->parent = Qnil;
37
+ p->memory.size = msize;
38
+ /* ensure the memory is aligned on at least a 8 byte boundary */
39
+ p->memory.address = (caddr_t) (((uintptr_t) memory + 0x7) & (uintptr_t) ~0x7UL);;
47
40
  p->allocated = true;
48
-
49
- if (p->memory.address == NULL) {
50
- long size = p->memory.size;
51
- xfree(p);
52
- rb_raise(rb_eNoMemError, "Failed to allocate memory size=%ld bytes", size);
53
- }
54
- if (TYPE(clear) == T_TRUE) {
41
+ if (TYPE(clear) == T_TRUE && p->memory.size > 0) {
55
42
  memset(p->memory.address, 0, p->memory.size);
56
43
  }
57
- return Data_Wrap_Struct(classMemoryPointer, memptr_mark, memptr_release, p);
44
+ return retval;
58
45
  }
59
46
 
60
- static VALUE
61
- memptr_plus(VALUE self, VALUE offset)
62
- {
63
- MemoryPointer* ptr = (MemoryPointer *) DATA_PTR(self);
64
- MemoryPointer* p;
65
- long off = NUM2LONG(offset);
66
-
67
- checkBounds(&ptr->memory, off, 1);
68
- p = ALLOC(MemoryPointer);
69
- memset(p, 0, sizeof(*p));
70
- p->memory.address = ptr->memory.address + off;;
71
- p->memory.size = ptr->memory.size - off;;
72
- p->parent = self;
73
- p->allocated = false;
74
- p->autorelease = true;
75
- return Data_Wrap_Struct(classMemoryPointer, memptr_mark, memptr_release, p);
76
- }
77
47
 
78
48
  static VALUE
79
49
  memptr_inspect(VALUE self)
80
50
  {
81
51
  MemoryPointer* ptr = (MemoryPointer *) DATA_PTR(self);
82
52
  char tmp[100];
83
- snprintf(tmp, sizeof(tmp), "#<MemoryPointer address=%p>", ptr->memory.address);
53
+ snprintf(tmp, sizeof(tmp), "#<MemoryPointer address=%p size=%lu>", ptr->memory.address, ptr->memory.size);
84
54
  return rb_str_new2(tmp);
85
55
  }
86
56
 
87
- static VALUE
88
- memptr_null_p(VALUE self)
89
- {
90
- MemoryPointer* ptr = (MemoryPointer *) DATA_PTR(self);
91
- return ptr->memory.address == NULL ? Qtrue : Qfalse;
92
- }
93
-
94
- static VALUE
95
- memptr_equals(VALUE self, VALUE other)
96
- {
97
- MemoryPointer* p1 = (MemoryPointer *) DATA_PTR(self);
98
- MemoryPointer* p2;
99
-
100
- if (!rb_obj_is_kind_of(other, classMemoryPointer)) {
101
- rb_raise(rb_eArgError, "Comparing MemoryPointer with non MemoryPointer");
102
- }
103
- p2 = (MemoryPointer *) DATA_PTR(other);
104
- return p1->memory.address == p2->memory.address ? Qtrue : Qfalse;
105
- }
106
-
107
57
  static VALUE
108
58
  memptr_free(VALUE self)
109
59
  {
110
60
  MemoryPointer* ptr = (MemoryPointer *) DATA_PTR(self);
111
61
  if (ptr->allocated) {
112
- free(ptr->memory.address);
113
- ptr->memory.address = NULL;
62
+ if (ptr->address != NULL) {
63
+ free(ptr->address);
64
+ ptr->address = NULL;
65
+ }
114
66
  ptr->allocated = false;
115
67
  }
116
68
  return self;
@@ -124,41 +76,24 @@ memptr_autorelease(VALUE self, VALUE autorelease)
124
76
  return self;
125
77
  }
126
78
 
127
- static VALUE
128
- memptr_address(VALUE self)
129
- {
130
- MemoryPointer* ptr = (MemoryPointer *) DATA_PTR(self);
131
- return ULL2NUM((uintptr_t) ptr->memory.address);
132
- }
133
-
134
79
  static void
135
80
  memptr_release(MemoryPointer* ptr)
136
81
  {
137
- if (ptr->autorelease && ptr->allocated) {
138
- free(ptr->memory.address);
82
+ if (ptr->autorelease && ptr->allocated && ptr->address != NULL) {
83
+ free(ptr->address);
84
+ ptr->address = NULL;
139
85
  }
140
86
  xfree(ptr);
141
87
 
142
88
  }
143
- static void
144
- memptr_mark(MemoryPointer* ptr)
145
- {
146
- if (ptr->parent != Qnil) {
147
- rb_gc_mark(ptr->parent);
148
- }
149
- }
150
89
 
151
90
  void
152
91
  rb_FFI_MemoryPointer_Init()
153
92
  {
154
93
  VALUE moduleFFI = rb_define_module("FFI");
155
- rb_FFI_MemoryPointer_class = classMemoryPointer = rb_define_class_under(moduleFFI, "MemoryPointer", rb_FFI_AbstractMemory_class);
94
+ rb_FFI_MemoryPointer_class = classMemoryPointer = rb_define_class_under(moduleFFI, "MemoryPointer", rb_FFI_Pointer_class);
156
95
  rb_define_singleton_method(classMemoryPointer, "__allocate", memptr_allocate, 3);
157
96
  rb_define_method(classMemoryPointer, "inspect", memptr_inspect, 0);
158
- rb_define_method(classMemoryPointer, "+", memptr_plus, 1);
159
- rb_define_method(classMemoryPointer, "null?", memptr_null_p, 0);
160
97
  rb_define_method(classMemoryPointer, "autorelease=", memptr_autorelease, 1);
161
98
  rb_define_method(classMemoryPointer, "free", memptr_free, 0);
162
- rb_define_method(classMemoryPointer, "address", memptr_address, 0);
163
- rb_define_method(classMemoryPointer, "==", memptr_equals, 1);
164
99
  }
@@ -0,0 +1,90 @@
1
+ #include <sys/types.h>
2
+ #include <stdio.h>
3
+ #include <stdint.h>
4
+ #include <dlfcn.h>
5
+ #include <ruby.h>
6
+
7
+ #include <ffi.h>
8
+
9
+ #include "rbffi.h"
10
+ #include "compat.h"
11
+ #include "Pointer.h"
12
+ #include "NativeLibrary.h"
13
+
14
+ static void library_free(Library* lib);
15
+ static VALUE classLibrary;
16
+
17
+ static VALUE
18
+ library_open(VALUE klass, VALUE libname, VALUE libflags)
19
+ {
20
+ VALUE retval;
21
+ Library* library;
22
+ int flags;
23
+ Check_Type(libflags, T_FIXNUM);
24
+
25
+ flags = libflags != Qnil ? NUM2UINT(libflags) : 0;
26
+ if (flags == 0) {
27
+ flags = RTLD_LAZY;
28
+ }
29
+ retval = Data_Make_Struct(klass, Library, NULL, library_free, library);
30
+ library->handle = dlopen(libname != Qnil ? StringValueCStr(libname) : NULL,
31
+ RTLD_LAZY);
32
+ if (library->handle == NULL) {
33
+ rb_raise(rb_eLoadError, "Could not open library '%s': %s",
34
+ libname != Qnil ? StringValueCStr(libname) : "[current process]",
35
+ dlerror());
36
+ }
37
+ rb_iv_set(retval, "@name", libname != Qnil ? libname : rb_str_new2("[current process]"));
38
+ return retval;
39
+ }
40
+
41
+ static VALUE
42
+ library_dlsym(VALUE self, VALUE name)
43
+ {
44
+ Library* library;
45
+ void* address = NULL;
46
+ Check_Type(name, T_STRING);
47
+
48
+ Data_Get_Struct(self, Library, library);
49
+ address = dlsym(library->handle, StringValueCStr(name));
50
+ return address != NULL ? rb_FFI_Pointer_new(address) : Qnil;
51
+ }
52
+
53
+ static VALUE
54
+ library_dlerror(VALUE self)
55
+ {
56
+ return rb_tainted_str_new2(dlerror());
57
+ }
58
+
59
+ static void
60
+ library_free(Library* library)
61
+ {
62
+ if (library != NULL) {
63
+ // dlclose() on MacOS tends to segfault - avoid it
64
+ #ifndef __APPLE__
65
+ if (library->handle != NULL) {
66
+ dlclose(library->handle);
67
+ }
68
+ #endif
69
+ library->handle = NULL;
70
+ xfree(library);
71
+ }
72
+ }
73
+
74
+ void
75
+ rb_FFI_NativeLibrary_Init()
76
+ {
77
+ VALUE moduleFFI = rb_define_module("FFI");
78
+ classLibrary = rb_define_class_under(moduleFFI, "DynamicLibrary", rb_cObject);
79
+ rb_define_const(moduleFFI, "NativeLibrary", classLibrary); // backwards compat library
80
+ rb_define_singleton_method(classLibrary, "open", library_open, 2);
81
+ rb_define_method(classLibrary, "find_symbol", library_dlsym, 1);
82
+ rb_define_method(classLibrary, "last_error", library_dlerror, 0);
83
+ rb_define_attr(classLibrary, "name", 1, 0);
84
+ #define DEF(x) rb_define_const(classLibrary, "RTLD_" #x, UINT2NUM(RTLD_##x))
85
+ DEF(LAZY);
86
+ DEF(NOW);
87
+ DEF(GLOBAL);
88
+ DEF(LOCAL);
89
+ }
90
+
@@ -0,0 +1,22 @@
1
+
2
+ #ifndef _LIBRARY_H
3
+ #define _LIBRARY_H
4
+
5
+ #ifdef __cplusplus
6
+ extern "C" {
7
+ #endif
8
+
9
+
10
+
11
+ typedef struct Library {
12
+ void* handle;
13
+ } Library;
14
+
15
+ extern void rb_FFI_NativeLibrary_Init();
16
+
17
+ #ifdef __cplusplus
18
+ }
19
+ #endif
20
+
21
+ #endif /* _LIBRARY_H */
22
+
@@ -1,5 +1,6 @@
1
1
  #include <sys/param.h>
2
2
  #include <sys/types.h>
3
+ #include <stdint.h>
3
4
  #include <stdbool.h>
4
5
  #include <ruby.h>
5
6
  #include <ctype.h>
@@ -26,16 +27,34 @@ static VALUE modulePlatform = Qnil;
26
27
  #error "Unknown cpu type"
27
28
  #endif
28
29
 
30
+ static void
31
+ export_primitive_types(VALUE module)
32
+ {
33
+ #define S(name, T) do { \
34
+ typedef struct { char c; T v; } s; \
35
+ rb_define_const(module, #name "_ALIGN", INT2NUM((sizeof(s) - sizeof(T)) * 8)); \
36
+ rb_define_const(module, #name "_SIZE", INT2NUM(sizeof(T)* 8)); \
37
+ } while(0)
38
+ S(INT8, char);
39
+ S(INT16, short);
40
+ S(INT32, int);
41
+ S(INT64, long long);
42
+ S(LONG, long);
43
+ S(FLOAT, float);
44
+ S(DOUBLE, double);
45
+ S(ADDRESS, void*);
46
+ #undef S
47
+ }
48
+
29
49
  void
30
50
  rb_FFI_Platform_Init()
31
51
  {
32
52
  VALUE moduleFFI = rb_define_module("FFI");
33
53
  VALUE platform = rb_define_module_under(moduleFFI, "Platform");
34
- rb_define_const(platform, "LONG_SIZE", INT2FIX(sizeof(long) * 8));
35
- rb_define_const(platform, "ADDRESS_SIZE", INT2FIX(sizeof(void *) * 8));
36
54
  rb_define_const(platform, "BYTE_ORDER", INT2FIX(BYTE_ORDER));
37
55
  rb_define_const(platform, "LITTLE_ENDIAN", INT2FIX(LITTLE_ENDIAN));
38
56
  rb_define_const(platform, "BIG_ENDIAN", INT2FIX(BIG_ENDIAN));
39
57
  rb_define_const(platform, "CPU", rb_str_new2(CPU));
58
+ export_primitive_types(platform);
40
59
  modulePlatform = platform;
41
60
  }
@@ -0,0 +1,107 @@
1
+ #include <stdbool.h>
2
+ #include <stdint.h>
3
+ #include <limits.h>
4
+ #include <ruby.h>
5
+ #include "rbffi.h"
6
+ #include "AbstractMemory.h"
7
+ #include "Pointer.h"
8
+
9
+ typedef struct Pointer {
10
+ AbstractMemory memory;
11
+ VALUE parent;
12
+ } Pointer;
13
+
14
+ VALUE rb_FFI_Pointer_class;
15
+ static VALUE classPointer = Qnil;
16
+ static void ptr_mark(Pointer* ptr);
17
+ static void ptr_free(Pointer* ptr);
18
+
19
+ VALUE
20
+ rb_FFI_Pointer_new(caddr_t addr)
21
+ {
22
+ Pointer* p;
23
+ VALUE retval;
24
+ retval = Data_Make_Struct(classPointer, Pointer, NULL, ptr_free, p);
25
+ p->memory.address = addr;
26
+ p->memory.size = LONG_MAX;
27
+ p->parent = Qnil;
28
+ return retval;
29
+ }
30
+
31
+ static VALUE
32
+ ptr_plus(VALUE self, VALUE offset)
33
+ {
34
+ AbstractMemory* ptr = (AbstractMemory *) DATA_PTR(self);
35
+ Pointer* p;
36
+ VALUE retval;
37
+ long off = NUM2LONG(offset);
38
+
39
+ checkBounds(ptr, off, 1);
40
+ retval = Data_Make_Struct(classPointer, Pointer, ptr_mark, ptr_free, p);
41
+ p->memory.address = ptr->address + off;
42
+ p->memory.size = ptr->size == LONG_MAX ? LONG_MAX : ptr->size - off;
43
+ p->parent = self;
44
+ return retval;
45
+ }
46
+
47
+ static VALUE
48
+ ptr_inspect(VALUE self)
49
+ {
50
+ AbstractMemory* ptr = (AbstractMemory *) DATA_PTR(self);
51
+ char tmp[100];
52
+ snprintf(tmp, sizeof(tmp), "#<Native Pointer address=%p>", ptr->address);
53
+ return rb_str_new2(tmp);
54
+ }
55
+
56
+ static VALUE
57
+ ptr_null_p(VALUE self)
58
+ {
59
+ AbstractMemory* ptr = (AbstractMemory *) DATA_PTR(self);
60
+ return ptr->address == NULL ? Qtrue : Qfalse;
61
+ }
62
+
63
+ static VALUE
64
+ ptr_equals(VALUE self, VALUE other)
65
+ {
66
+ AbstractMemory* p1 = (AbstractMemory *) DATA_PTR(self);
67
+ AbstractMemory* p2;
68
+
69
+ if (!rb_obj_is_kind_of(other, classPointer)) {
70
+ rb_raise(rb_eArgError, "Comparing Pointer with non Pointer");
71
+ }
72
+ p2 = (AbstractMemory *) DATA_PTR(other);
73
+ return p1->address == p2->address ? Qtrue : Qfalse;
74
+ }
75
+
76
+ static VALUE
77
+ ptr_address(VALUE self)
78
+ {
79
+ AbstractMemory* ptr = (AbstractMemory *) DATA_PTR(self);
80
+ return ULL2NUM((uintptr_t) ptr->address);
81
+ }
82
+
83
+ static void
84
+ ptr_mark(Pointer* ptr)
85
+ {
86
+ if (ptr->parent != Qnil) {
87
+ rb_gc_mark(ptr->parent);
88
+ }
89
+ }
90
+
91
+ static void
92
+ ptr_free(Pointer* ptr)
93
+ {
94
+ xfree(ptr);
95
+ }
96
+
97
+ void
98
+ rb_FFI_Pointer_Init()
99
+ {
100
+ VALUE moduleFFI = rb_define_module("FFI");
101
+ rb_FFI_Pointer_class = classPointer = rb_define_class_under(moduleFFI, "Pointer", rb_FFI_AbstractMemory_class);
102
+ rb_define_method(classPointer, "inspect", ptr_inspect, 0);
103
+ rb_define_method(classPointer, "+", ptr_plus, 1);
104
+ rb_define_method(classPointer, "null?", ptr_null_p, 0);
105
+ rb_define_method(classPointer, "address", ptr_address, 0);
106
+ rb_define_method(classPointer, "==", ptr_equals, 1);
107
+ }
@@ -0,0 +1,21 @@
1
+
2
+ #ifndef _POINTER_H
3
+ #define _POINTER_H
4
+
5
+ #ifdef __cplusplus
6
+ extern "C" {
7
+ #endif
8
+
9
+
10
+
11
+ extern void rb_FFI_Pointer_Init(void);
12
+ extern VALUE rb_FFI_Pointer_new(caddr_t addr);
13
+ extern VALUE rb_FFI_Pointer_class;
14
+
15
+
16
+ #ifdef __cplusplus
17
+ }
18
+ #endif
19
+
20
+ #endif /* _POINTER_H */
21
+