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.
- data/Rakefile +52 -29
- data/ext/AbstractMemory.c +72 -28
- data/ext/AutoPointer.c +54 -0
- data/ext/AutoPointer.h +18 -0
- data/ext/Buffer.c +21 -17
- data/ext/Callback.c +81 -43
- data/ext/Callback.h +1 -1
- data/ext/Invoker.c +465 -108
- data/ext/MemoryPointer.c +25 -90
- data/ext/NativeLibrary.c +90 -0
- data/ext/NativeLibrary.h +22 -0
- data/ext/Platform.c +21 -2
- data/ext/Pointer.c +107 -0
- data/ext/Pointer.h +21 -0
- data/ext/Types.c +16 -5
- data/ext/Types.h +3 -1
- data/ext/compat.h +14 -0
- data/ext/extconf.rb +13 -1
- data/ext/ffi.c +11 -1
- data/ext/ffi.mk +3 -3
- data/ext/libffi.darwin.mk +19 -8
- data/gen/Rakefile +12 -0
- data/lib/ffi/autopointer.rb +61 -0
- data/lib/ffi/errno.rb +8 -0
- data/lib/ffi/ffi.rb +38 -201
- data/lib/ffi/io.rb +7 -0
- data/lib/ffi/library.rb +116 -0
- data/lib/ffi/managedstruct.rb +55 -0
- data/lib/ffi/memorypointer.rb +3 -96
- data/lib/ffi/platform.rb +8 -5
- data/lib/ffi/pointer.rb +105 -0
- data/lib/ffi/struct.rb +97 -42
- data/lib/ffi/tools/const_generator.rb +177 -0
- data/lib/ffi/tools/generator.rb +58 -0
- data/lib/ffi/tools/generator_task.rb +35 -0
- data/lib/ffi/tools/struct_generator.rb +194 -0
- data/lib/ffi/tools/types_generator.rb +123 -0
- data/lib/ffi/types.rb +150 -0
- data/lib/ffi/variadic.rb +30 -0
- data/nbproject/Makefile-Default.mk +6 -3
- data/nbproject/Makefile-impl.mk +5 -5
- data/nbproject/Package-Default.bash +72 -0
- data/nbproject/configurations.xml +139 -25
- data/nbproject/private/configurations.xml +1 -1
- data/nbproject/project.xml +4 -0
- data/samples/gettimeofday.rb +6 -2
- data/samples/inotify.rb +59 -0
- data/samples/pty.rb +75 -0
- data/specs/buffer_spec.rb +64 -9
- data/specs/callback_spec.rb +308 -4
- data/specs/errno_spec.rb +13 -0
- data/specs/library_spec.rb +55 -0
- data/specs/managed_struct_spec.rb +40 -0
- data/specs/number_spec.rb +183 -0
- data/specs/pointer_spec.rb +126 -0
- data/specs/rbx/memory_pointer_spec.rb +7 -7
- data/specs/spec_helper.rb +7 -0
- data/specs/string_spec.rb +34 -0
- data/specs/struct_spec.rb +223 -0
- data/specs/typedef_spec.rb +48 -0
- data/specs/variadic_spec.rb +84 -0
- metadata +270 -237
data/ext/MemoryPointer.c
CHANGED
@@ -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
|
-
|
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
|
-
|
42
|
-
|
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 =
|
45
|
-
|
46
|
-
p->
|
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
|
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
|
-
|
113
|
-
|
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->
|
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",
|
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
|
}
|
data/ext/NativeLibrary.c
ADDED
@@ -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
|
+
|
data/ext/NativeLibrary.h
ADDED
@@ -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
|
+
|
data/ext/Platform.c
CHANGED
@@ -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
|
}
|
data/ext/Pointer.c
ADDED
@@ -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
|
+
}
|
data/ext/Pointer.h
ADDED
@@ -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
|
+
|