fiddle 1.0.0.beta2 → 1.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +72 -3
- data/Rakefile +4 -5
- data/bin/downloader.rb +331 -0
- data/bin/extlibs.rb +262 -0
- data/ext/fiddle/closure.c +5 -4
- data/ext/fiddle/conversions.c +205 -16
- data/ext/fiddle/conversions.h +14 -4
- data/ext/fiddle/depend +85 -0
- data/ext/fiddle/extconf.rb +60 -29
- data/ext/fiddle/extlibs +10 -2
- data/ext/fiddle/fiddle.c +133 -34
- data/ext/fiddle/fiddle.h +96 -32
- data/ext/fiddle/function.c +261 -93
- data/ext/fiddle/handle.c +10 -12
- data/ext/fiddle/memory_view.c +254 -0
- data/ext/fiddle/pinned.c +123 -0
- data/ext/fiddle/pointer.c +147 -24
- data/ext/fiddle/win32/fficonfig.h +0 -0
- data/ext/fiddle/win32/libffi-config.rb +1 -1
- data/ext/fiddle/win32/libffi.mk.tmpl +0 -0
- data/fiddle.gemspec +50 -5
- data/lib/fiddle.rb +3 -1
- data/lib/fiddle/cparser.rb +93 -25
- data/lib/fiddle/function.rb +5 -0
- data/lib/fiddle/import.rb +11 -9
- data/lib/fiddle/pack.rb +14 -7
- data/lib/fiddle/struct.rb +267 -43
- data/lib/fiddle/value.rb +18 -9
- data/lib/fiddle/version.rb +3 -0
- metadata +18 -15
- data/.gitignore +0 -13
- data/.travis.yml +0 -5
- data/Gemfile +0 -4
- data/bin/console +0 -14
- data/bin/setup +0 -8
data/ext/fiddle/handle.c
CHANGED
@@ -1,8 +1,6 @@
|
|
1
1
|
#include <ruby.h>
|
2
2
|
#include <fiddle.h>
|
3
3
|
|
4
|
-
#define SafeStringValueCStr(v) (rb_check_safe_obj(rb_string_value(&v)), StringValueCStr(v))
|
5
|
-
|
6
4
|
VALUE rb_cHandle;
|
7
5
|
|
8
6
|
struct dl_handle {
|
@@ -76,14 +74,14 @@ rb_fiddle_handle_close(VALUE self)
|
|
76
74
|
/* Check dlclose for successful return value */
|
77
75
|
if(ret) {
|
78
76
|
#if defined(HAVE_DLERROR)
|
79
|
-
rb_raise(
|
77
|
+
rb_raise(rb_eFiddleDLError, "%s", dlerror());
|
80
78
|
#else
|
81
|
-
rb_raise(
|
79
|
+
rb_raise(rb_eFiddleDLError, "could not close handle");
|
82
80
|
#endif
|
83
81
|
}
|
84
82
|
return INT2NUM(ret);
|
85
83
|
}
|
86
|
-
rb_raise(
|
84
|
+
rb_raise(rb_eFiddleDLError, "dlclose() called too many times");
|
87
85
|
|
88
86
|
UNREACHABLE;
|
89
87
|
}
|
@@ -145,11 +143,11 @@ rb_fiddle_handle_initialize(int argc, VALUE argv[], VALUE self)
|
|
145
143
|
cflag = RTLD_LAZY | RTLD_GLOBAL;
|
146
144
|
break;
|
147
145
|
case 1:
|
148
|
-
clib = NIL_P(lib) ? NULL :
|
146
|
+
clib = NIL_P(lib) ? NULL : StringValueCStr(lib);
|
149
147
|
cflag = RTLD_LAZY | RTLD_GLOBAL;
|
150
148
|
break;
|
151
149
|
case 2:
|
152
|
-
clib = NIL_P(lib) ? NULL :
|
150
|
+
clib = NIL_P(lib) ? NULL : StringValueCStr(lib);
|
153
151
|
cflag = NUM2INT(flag);
|
154
152
|
break;
|
155
153
|
default:
|
@@ -179,12 +177,12 @@ rb_fiddle_handle_initialize(int argc, VALUE argv[], VALUE self)
|
|
179
177
|
ptr = dlopen(clib, cflag);
|
180
178
|
#if defined(HAVE_DLERROR)
|
181
179
|
if( !ptr && (err = dlerror()) ){
|
182
|
-
rb_raise(
|
180
|
+
rb_raise(rb_eFiddleDLError, "%s", err);
|
183
181
|
}
|
184
182
|
#else
|
185
183
|
if( !ptr ){
|
186
184
|
err = dlerror();
|
187
|
-
rb_raise(
|
185
|
+
rb_raise(rb_eFiddleDLError, "%s", err);
|
188
186
|
}
|
189
187
|
#endif
|
190
188
|
TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle);
|
@@ -280,7 +278,7 @@ rb_fiddle_handle_sym(VALUE self, VALUE sym)
|
|
280
278
|
|
281
279
|
TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle);
|
282
280
|
if( ! fiddle_handle->open ){
|
283
|
-
rb_raise(
|
281
|
+
rb_raise(rb_eFiddleDLError, "closed handle");
|
284
282
|
}
|
285
283
|
|
286
284
|
return fiddle_handle_sym(fiddle_handle->ptr, sym);
|
@@ -319,7 +317,7 @@ fiddle_handle_sym(void *handle, VALUE symbol)
|
|
319
317
|
# define CHECK_DLERROR
|
320
318
|
#endif
|
321
319
|
void (*func)();
|
322
|
-
const char *name =
|
320
|
+
const char *name = StringValueCStr(symbol);
|
323
321
|
|
324
322
|
#ifdef HAVE_DLERROR
|
325
323
|
dlerror();
|
@@ -368,7 +366,7 @@ fiddle_handle_sym(void *handle, VALUE symbol)
|
|
368
366
|
}
|
369
367
|
#endif
|
370
368
|
if( !func ){
|
371
|
-
rb_raise(
|
369
|
+
rb_raise(rb_eFiddleDLError, "unknown symbol \"%"PRIsVALUE"\"", symbol);
|
372
370
|
}
|
373
371
|
|
374
372
|
return PTR2NUM(func);
|
@@ -0,0 +1,254 @@
|
|
1
|
+
#include <stdbool.h>
|
2
|
+
#include <ruby/ruby.h>
|
3
|
+
|
4
|
+
#ifdef HAVE_RUBY_MEMORY_VIEW_H
|
5
|
+
# include <ruby/memory_view.h>
|
6
|
+
#endif
|
7
|
+
|
8
|
+
#if SIZEOF_INTPTR_T == SIZEOF_LONG_LONG
|
9
|
+
# define INTPTR2NUM LL2NUM
|
10
|
+
# define UINTPTR2NUM ULL2NUM
|
11
|
+
#elif SIZEOF_INTPTR_T == SIZEOF_LONG
|
12
|
+
# define INTPTR2NUM LONG2NUM
|
13
|
+
# define UINTPTR2NUM ULONG2NUM
|
14
|
+
#else
|
15
|
+
# define INTPTR2NUM INT2NUM
|
16
|
+
# define UINTPTR2NUM UINT2NUM
|
17
|
+
#endif
|
18
|
+
|
19
|
+
#include <fiddle.h>
|
20
|
+
|
21
|
+
#ifdef FIDDLE_MEMORY_VIEW
|
22
|
+
VALUE rb_cMemoryView = Qnil;
|
23
|
+
|
24
|
+
struct memview_data {
|
25
|
+
rb_memory_view_t view;
|
26
|
+
rb_memory_view_item_component_t *members;
|
27
|
+
size_t n_members;
|
28
|
+
};
|
29
|
+
|
30
|
+
static void
|
31
|
+
fiddle_memview_mark(void *ptr)
|
32
|
+
{
|
33
|
+
const struct memview_data *data = ptr;
|
34
|
+
rb_gc_mark(data->view.obj);
|
35
|
+
}
|
36
|
+
|
37
|
+
static void
|
38
|
+
fiddle_memview_free(void *ptr)
|
39
|
+
{
|
40
|
+
struct memview_data *data = ptr;
|
41
|
+
rb_memory_view_release(&data->view);
|
42
|
+
if (data->members)
|
43
|
+
xfree(data->members);
|
44
|
+
xfree(ptr);
|
45
|
+
}
|
46
|
+
|
47
|
+
static size_t
|
48
|
+
fiddle_memview_memsize(const void *ptr)
|
49
|
+
{
|
50
|
+
const struct memview_data *data = ptr;
|
51
|
+
return sizeof(*data) + sizeof(rb_memory_view_item_component_t)*data->n_members + (size_t)data->view.len;
|
52
|
+
}
|
53
|
+
|
54
|
+
static const rb_data_type_t fiddle_memview_data_type = {
|
55
|
+
"fiddle/memory_view",
|
56
|
+
{fiddle_memview_mark, fiddle_memview_free, fiddle_memview_memsize,},
|
57
|
+
};
|
58
|
+
|
59
|
+
static VALUE
|
60
|
+
rb_fiddle_memview_s_allocate(VALUE klass)
|
61
|
+
{
|
62
|
+
struct memview_data *data;
|
63
|
+
VALUE obj = TypedData_Make_Struct(klass, struct memview_data, &fiddle_memview_data_type, data);
|
64
|
+
data->view.obj = Qnil;
|
65
|
+
data->members = NULL;
|
66
|
+
data->n_members = 0;
|
67
|
+
return obj;
|
68
|
+
}
|
69
|
+
|
70
|
+
static VALUE
|
71
|
+
rb_fiddle_memview_initialize(VALUE obj, VALUE target)
|
72
|
+
{
|
73
|
+
struct memview_data *data;
|
74
|
+
TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data);
|
75
|
+
|
76
|
+
if (!rb_memory_view_get(target, &data->view, 0)) {
|
77
|
+
rb_raise(rb_eArgError, "Unable to get a memory view from %+"PRIsVALUE, target);
|
78
|
+
}
|
79
|
+
|
80
|
+
return Qnil;
|
81
|
+
}
|
82
|
+
|
83
|
+
static VALUE
|
84
|
+
rb_fiddle_memview_get_obj(VALUE obj)
|
85
|
+
{
|
86
|
+
struct memview_data *data;
|
87
|
+
TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data);
|
88
|
+
|
89
|
+
return data->view.obj;
|
90
|
+
}
|
91
|
+
|
92
|
+
static VALUE
|
93
|
+
rb_fiddle_memview_get_length(VALUE obj)
|
94
|
+
{
|
95
|
+
struct memview_data *data;
|
96
|
+
TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data);
|
97
|
+
|
98
|
+
if (NIL_P(data->view.obj)) return Qnil;
|
99
|
+
return SSIZET2NUM(data->view.len);
|
100
|
+
}
|
101
|
+
|
102
|
+
static VALUE
|
103
|
+
rb_fiddle_memview_get_readonly(VALUE obj)
|
104
|
+
{
|
105
|
+
struct memview_data *data;
|
106
|
+
TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data);
|
107
|
+
|
108
|
+
if (NIL_P(data->view.obj)) return Qnil;
|
109
|
+
return data->view.readonly ? Qtrue : Qfalse;
|
110
|
+
}
|
111
|
+
|
112
|
+
static VALUE
|
113
|
+
rb_fiddle_memview_get_format(VALUE obj)
|
114
|
+
{
|
115
|
+
struct memview_data *data;
|
116
|
+
TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data);
|
117
|
+
|
118
|
+
if (NIL_P(data->view.obj)) return Qnil;
|
119
|
+
return data->view.format == NULL ? Qnil : rb_str_new_cstr(data->view.format);
|
120
|
+
}
|
121
|
+
|
122
|
+
static VALUE
|
123
|
+
rb_fiddle_memview_get_item_size(VALUE obj)
|
124
|
+
{
|
125
|
+
struct memview_data *data;
|
126
|
+
TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data);
|
127
|
+
|
128
|
+
if (NIL_P(data->view.obj)) return Qnil;
|
129
|
+
return SSIZET2NUM(data->view.item_size);
|
130
|
+
}
|
131
|
+
|
132
|
+
static VALUE
|
133
|
+
rb_fiddle_memview_get_ndim(VALUE obj)
|
134
|
+
{
|
135
|
+
struct memview_data *data;
|
136
|
+
TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data);
|
137
|
+
|
138
|
+
if (NIL_P(data->view.obj)) return Qnil;
|
139
|
+
return SSIZET2NUM(data->view.ndim);
|
140
|
+
}
|
141
|
+
|
142
|
+
static VALUE
|
143
|
+
rb_fiddle_memview_get_shape(VALUE obj)
|
144
|
+
{
|
145
|
+
struct memview_data *data;
|
146
|
+
TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data);
|
147
|
+
|
148
|
+
if (NIL_P(data->view.obj)) return Qnil;
|
149
|
+
if (data->view.shape == NULL) return Qnil;
|
150
|
+
|
151
|
+
const ssize_t ndim = data->view.ndim;
|
152
|
+
VALUE shape = rb_ary_new_capa(ndim);
|
153
|
+
ssize_t i;
|
154
|
+
for (i = 0; i < ndim; ++i) {
|
155
|
+
rb_ary_push(shape, SSIZET2NUM(data->view.shape[i]));
|
156
|
+
}
|
157
|
+
return shape;
|
158
|
+
}
|
159
|
+
|
160
|
+
static VALUE
|
161
|
+
rb_fiddle_memview_get_strides(VALUE obj)
|
162
|
+
{
|
163
|
+
struct memview_data *data;
|
164
|
+
TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data);
|
165
|
+
|
166
|
+
if (NIL_P(data->view.obj)) return Qnil;
|
167
|
+
if (data->view.strides == NULL) return Qnil;
|
168
|
+
|
169
|
+
const ssize_t ndim = data->view.ndim;
|
170
|
+
VALUE strides = rb_ary_new_capa(ndim);
|
171
|
+
ssize_t i;
|
172
|
+
for (i = 0; i < ndim; ++i) {
|
173
|
+
rb_ary_push(strides, SSIZET2NUM(data->view.strides[i]));
|
174
|
+
}
|
175
|
+
return strides;
|
176
|
+
}
|
177
|
+
|
178
|
+
static VALUE
|
179
|
+
rb_fiddle_memview_get_sub_offsets(VALUE obj)
|
180
|
+
{
|
181
|
+
struct memview_data *data;
|
182
|
+
TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data);
|
183
|
+
|
184
|
+
if (NIL_P(data->view.obj)) return Qnil;
|
185
|
+
if (data->view.sub_offsets == NULL) return Qnil;
|
186
|
+
|
187
|
+
const ssize_t ndim = data->view.ndim;
|
188
|
+
VALUE sub_offsets = rb_ary_new_capa(ndim);
|
189
|
+
ssize_t i;
|
190
|
+
for (i = 0; i < ndim; ++i) {
|
191
|
+
rb_ary_push(sub_offsets, SSIZET2NUM(data->view.sub_offsets[i]));
|
192
|
+
}
|
193
|
+
return sub_offsets;
|
194
|
+
}
|
195
|
+
|
196
|
+
static VALUE
|
197
|
+
rb_fiddle_memview_aref(int argc, VALUE *argv, VALUE obj)
|
198
|
+
{
|
199
|
+
struct memview_data *data;
|
200
|
+
TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data);
|
201
|
+
|
202
|
+
if (NIL_P(data->view.obj)) return Qnil;
|
203
|
+
|
204
|
+
const ssize_t ndim = data->view.ndim;
|
205
|
+
if (argc != ndim) {
|
206
|
+
rb_raise(rb_eIndexError, "wrong number of index (%d for %"PRIdSIZE")", argc, ndim);
|
207
|
+
}
|
208
|
+
|
209
|
+
VALUE indices_v = 0;
|
210
|
+
ssize_t *indices = ALLOCV_N(ssize_t, indices_v, ndim);
|
211
|
+
|
212
|
+
ssize_t i;
|
213
|
+
for (i = 0; i < ndim; ++i) {
|
214
|
+
ssize_t x = NUM2SSIZET(argv[i]);
|
215
|
+
indices[i] = x;
|
216
|
+
}
|
217
|
+
|
218
|
+
uint8_t *ptr = rb_memory_view_get_item_pointer(&data->view, indices);
|
219
|
+
ALLOCV_END(indices_v);
|
220
|
+
|
221
|
+
if (data->view.format == NULL) {
|
222
|
+
return INT2FIX(*ptr);
|
223
|
+
}
|
224
|
+
|
225
|
+
if (!data->members) {
|
226
|
+
const char *err;
|
227
|
+
if (rb_memory_view_parse_item_format(data->view.format, &data->members, &data->n_members, &err) < 0) {
|
228
|
+
rb_raise(rb_eRuntimeError, "Unable to recognize item format at %"PRIdSIZE" in \"%s\"",
|
229
|
+
err - data->view.format, data->view.format);
|
230
|
+
}
|
231
|
+
}
|
232
|
+
|
233
|
+
return rb_memory_view_extract_item_members(ptr, data->members, data->n_members);
|
234
|
+
}
|
235
|
+
|
236
|
+
void
|
237
|
+
Init_fiddle_memory_view(void)
|
238
|
+
{
|
239
|
+
rb_cMemoryView = rb_define_class_under(mFiddle, "MemoryView", rb_cObject);
|
240
|
+
rb_define_alloc_func(rb_cMemoryView, rb_fiddle_memview_s_allocate);
|
241
|
+
rb_define_method(rb_cMemoryView, "initialize", rb_fiddle_memview_initialize, 1);
|
242
|
+
rb_define_method(rb_cMemoryView, "obj", rb_fiddle_memview_get_obj, 0);
|
243
|
+
rb_define_method(rb_cMemoryView, "length", rb_fiddle_memview_get_length, 0);
|
244
|
+
rb_define_method(rb_cMemoryView, "readonly?", rb_fiddle_memview_get_readonly, 0);
|
245
|
+
rb_define_method(rb_cMemoryView, "format", rb_fiddle_memview_get_format, 0);
|
246
|
+
rb_define_method(rb_cMemoryView, "item_size", rb_fiddle_memview_get_item_size, 0);
|
247
|
+
rb_define_method(rb_cMemoryView, "ndim", rb_fiddle_memview_get_ndim, 0);
|
248
|
+
rb_define_method(rb_cMemoryView, "shape", rb_fiddle_memview_get_shape, 0);
|
249
|
+
rb_define_method(rb_cMemoryView, "strides", rb_fiddle_memview_get_strides, 0);
|
250
|
+
rb_define_method(rb_cMemoryView, "sub_offsets", rb_fiddle_memview_get_sub_offsets, 0);
|
251
|
+
rb_define_method(rb_cMemoryView, "[]", rb_fiddle_memview_aref, -1);
|
252
|
+
}
|
253
|
+
|
254
|
+
#endif /* FIDDLE_MEMORY_VIEW */
|
data/ext/fiddle/pinned.c
ADDED
@@ -0,0 +1,123 @@
|
|
1
|
+
#include <fiddle.h>
|
2
|
+
|
3
|
+
VALUE rb_cPinned;
|
4
|
+
VALUE rb_eFiddleClearedReferenceError;
|
5
|
+
|
6
|
+
struct pinned_data {
|
7
|
+
VALUE ptr;
|
8
|
+
};
|
9
|
+
|
10
|
+
static void
|
11
|
+
pinned_mark(void *ptr)
|
12
|
+
{
|
13
|
+
struct pinned_data *data = (struct pinned_data*)ptr;
|
14
|
+
/* Ensure reference is pinned */
|
15
|
+
if (data->ptr) {
|
16
|
+
rb_gc_mark(data->ptr);
|
17
|
+
}
|
18
|
+
}
|
19
|
+
|
20
|
+
static size_t
|
21
|
+
pinned_memsize(const void *ptr)
|
22
|
+
{
|
23
|
+
return sizeof(struct pinned_data);
|
24
|
+
}
|
25
|
+
|
26
|
+
static const rb_data_type_t pinned_data_type = {
|
27
|
+
"fiddle/pinned",
|
28
|
+
{pinned_mark, xfree, pinned_memsize, },
|
29
|
+
0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED
|
30
|
+
};
|
31
|
+
|
32
|
+
static VALUE
|
33
|
+
allocate(VALUE klass)
|
34
|
+
{
|
35
|
+
struct pinned_data *data;
|
36
|
+
VALUE obj = TypedData_Make_Struct(klass, struct pinned_data, &pinned_data_type, data);
|
37
|
+
data->ptr = 0;
|
38
|
+
return obj;
|
39
|
+
}
|
40
|
+
|
41
|
+
/*
|
42
|
+
* call-seq:
|
43
|
+
* Fiddle::Pinned.new(object) => pinned_object
|
44
|
+
*
|
45
|
+
* Create a new pinned object reference. The Fiddle::Pinned instance will
|
46
|
+
* prevent the GC from moving +object+.
|
47
|
+
*/
|
48
|
+
static VALUE
|
49
|
+
initialize(VALUE self, VALUE ref)
|
50
|
+
{
|
51
|
+
struct pinned_data *data;
|
52
|
+
TypedData_Get_Struct(self, struct pinned_data, &pinned_data_type, data);
|
53
|
+
RB_OBJ_WRITE(self, &data->ptr, ref);
|
54
|
+
return self;
|
55
|
+
}
|
56
|
+
|
57
|
+
/*
|
58
|
+
* call-seq: ref
|
59
|
+
*
|
60
|
+
* Return the object that this pinned instance references.
|
61
|
+
*/
|
62
|
+
static VALUE
|
63
|
+
ref(VALUE self)
|
64
|
+
{
|
65
|
+
struct pinned_data *data;
|
66
|
+
TypedData_Get_Struct(self, struct pinned_data, &pinned_data_type, data);
|
67
|
+
if (data->ptr) {
|
68
|
+
return data->ptr;
|
69
|
+
} else {
|
70
|
+
rb_raise(rb_eFiddleClearedReferenceError, "`ref` called on a cleared object");
|
71
|
+
}
|
72
|
+
}
|
73
|
+
|
74
|
+
/*
|
75
|
+
* call-seq: clear
|
76
|
+
*
|
77
|
+
* Clear the reference to the object this is pinning.
|
78
|
+
*/
|
79
|
+
static VALUE
|
80
|
+
clear(VALUE self)
|
81
|
+
{
|
82
|
+
struct pinned_data *data;
|
83
|
+
TypedData_Get_Struct(self, struct pinned_data, &pinned_data_type, data);
|
84
|
+
data->ptr = 0;
|
85
|
+
return self;
|
86
|
+
}
|
87
|
+
|
88
|
+
/*
|
89
|
+
* call-seq: cleared?
|
90
|
+
*
|
91
|
+
* Returns true if the reference has been cleared, otherwise returns false.
|
92
|
+
*/
|
93
|
+
static VALUE
|
94
|
+
cleared_p(VALUE self)
|
95
|
+
{
|
96
|
+
struct pinned_data *data;
|
97
|
+
TypedData_Get_Struct(self, struct pinned_data, &pinned_data_type, data);
|
98
|
+
if (data->ptr) {
|
99
|
+
return Qfalse;
|
100
|
+
} else {
|
101
|
+
return Qtrue;
|
102
|
+
}
|
103
|
+
}
|
104
|
+
|
105
|
+
extern VALUE rb_eFiddleError;
|
106
|
+
|
107
|
+
void
|
108
|
+
Init_fiddle_pinned(void)
|
109
|
+
{
|
110
|
+
rb_cPinned = rb_define_class_under(mFiddle, "Pinned", rb_cObject);
|
111
|
+
rb_define_alloc_func(rb_cPinned, allocate);
|
112
|
+
rb_define_method(rb_cPinned, "initialize", initialize, 1);
|
113
|
+
rb_define_method(rb_cPinned, "ref", ref, 0);
|
114
|
+
rb_define_method(rb_cPinned, "clear", clear, 0);
|
115
|
+
rb_define_method(rb_cPinned, "cleared?", cleared_p, 0);
|
116
|
+
|
117
|
+
/*
|
118
|
+
* Document-class: Fiddle::ClearedReferenceError
|
119
|
+
*
|
120
|
+
* Cleared reference exception
|
121
|
+
*/
|
122
|
+
rb_eFiddleClearedReferenceError = rb_define_class_under(mFiddle, "ClearedReferenceError", rb_eFiddleError);
|
123
|
+
}
|