ffi 0.6.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +109 -0
- data/LICENSE +10 -21
- data/README.rdoc +1 -0
- data/Rakefile +3 -2
- data/ext/ffi_c/AbstractMemory.c +56 -38
- data/ext/ffi_c/AbstractMemory.h +15 -22
- data/ext/ffi_c/Buffer.c +61 -22
- data/ext/ffi_c/Call.c +55 -543
- data/ext/ffi_c/Call.h +1 -1
- data/ext/ffi_c/DataConverter.c +62 -0
- data/ext/ffi_c/DynamicLibrary.c +21 -1
- data/ext/ffi_c/Function.c +255 -32
- data/ext/ffi_c/MappedType.c +146 -0
- data/ext/ffi_c/MappedType.h +57 -0
- data/ext/ffi_c/MemoryPointer.c +12 -33
- data/ext/ffi_c/Platform.c +2 -0
- data/ext/ffi_c/Pointer.c +66 -28
- data/ext/ffi_c/Struct.c +106 -318
- data/ext/ffi_c/Struct.h +6 -0
- data/ext/ffi_c/StructByReference.c +150 -0
- data/ext/ffi_c/StructByReference.h +50 -0
- data/ext/ffi_c/StructLayout.c +25 -14
- data/ext/ffi_c/Type.c +39 -68
- data/ext/ffi_c/Type.h +12 -22
- data/ext/ffi_c/Types.c +21 -6
- data/ext/ffi_c/Types.h +7 -7
- data/ext/ffi_c/Variadic.c +21 -17
- data/ext/ffi_c/extconf.rb +4 -0
- data/ext/ffi_c/ffi.c +8 -2
- data/ext/ffi_c/libffi/configure +1 -1
- data/ext/ffi_c/libffi.gnu.mk +1 -1
- data/ext/ffi_c/libffi.mk +1 -1
- data/ext/ffi_c/rbffi.h +1 -0
- data/gen/Rakefile +4 -2
- data/lib/ffi/autopointer.rb +23 -22
- data/lib/ffi/enum.rb +36 -21
- data/lib/ffi/errno.rb +20 -0
- data/lib/ffi/ffi.rb +13 -79
- data/lib/ffi/io.rb +12 -20
- data/lib/ffi/library.rb +110 -93
- data/lib/ffi/managedstruct.rb +1 -1
- data/lib/ffi/memorypointer.rb +15 -21
- data/lib/ffi/platform.rb +24 -28
- data/lib/ffi/pointer.rb +14 -21
- data/lib/ffi/struct.rb +100 -51
- data/lib/ffi/struct_layout_builder.rb +158 -0
- data/lib/ffi/types.rb +99 -128
- data/lib/ffi/union.rb +20 -0
- data/lib/ffi/variadic.rb +33 -22
- data/spec/ffi/async_callback_spec.rb +23 -0
- data/spec/ffi/callback_spec.rb +62 -0
- data/spec/ffi/custom_param_type.rb +31 -0
- data/spec/ffi/custom_type_spec.rb +73 -0
- data/spec/ffi/enum_spec.rb +19 -0
- data/spec/ffi/ffi_spec.rb +24 -0
- data/spec/ffi/pointer_spec.rb +15 -0
- data/spec/ffi/rbx/memory_pointer_spec.rb +7 -1
- data/spec/ffi/strptr_spec.rb +36 -0
- data/spec/ffi/struct_packed_spec.rb +46 -0
- data/spec/ffi/struct_spec.rb +39 -7
- data/spec/ffi/typedef_spec.rb +14 -0
- data/tasks/ann.rake +80 -0
- data/tasks/extension.rake +25 -0
- data/tasks/gem.rake +200 -0
- data/tasks/git.rake +41 -0
- data/tasks/notes.rake +27 -0
- data/tasks/post_load.rake +34 -0
- data/tasks/rdoc.rake +50 -0
- data/tasks/rubyforge.rake +55 -0
- data/tasks/setup.rb +301 -0
- data/tasks/spec.rake +54 -0
- data/tasks/svn.rake +47 -0
- data/tasks/test.rake +40 -0
- metadata +64 -11
- data/ext/ffi_c/AutoPointer.c +0 -60
- data/ext/ffi_c/AutoPointer.h +0 -18
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2009, Wayne Meissner
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
*
|
|
5
|
+
* Redistribution and use in source and binary forms, with or without
|
|
6
|
+
* modification, are permitted provided that the following conditions are met:
|
|
7
|
+
*
|
|
8
|
+
* * Redistributions of source code must retain the above copyright notice, this
|
|
9
|
+
* list of conditions and the following disclaimer.
|
|
10
|
+
* * Redistributions in binary form must reproduce the above copyright notice
|
|
11
|
+
* this list of conditions and the following disclaimer in the documentation
|
|
12
|
+
* and/or other materials provided with the distribution.
|
|
13
|
+
* * The name of the author or authors may not be used to endorse or promote
|
|
14
|
+
* products derived from this software without specific prior written permission.
|
|
15
|
+
*
|
|
16
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
17
|
+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
18
|
+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
19
|
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
|
20
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
21
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
22
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
23
|
+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
24
|
+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
25
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
#ifndef RBFFI_STRUCTBYREFERENCE_H
|
|
29
|
+
#define RBFFI_STRUCTBYREFERENCE_H
|
|
30
|
+
|
|
31
|
+
#include <ruby.h>
|
|
32
|
+
|
|
33
|
+
#ifdef __cplusplus
|
|
34
|
+
extern "C" {
|
|
35
|
+
#endif
|
|
36
|
+
|
|
37
|
+
typedef struct StructByReference_ {
|
|
38
|
+
VALUE rbStructClass;
|
|
39
|
+
} StructByReference;
|
|
40
|
+
|
|
41
|
+
void rbffi_StructByReference_Init(VALUE moduleFFI);
|
|
42
|
+
|
|
43
|
+
extern VALUE rbffi_StructByReferenceClass;
|
|
44
|
+
|
|
45
|
+
#ifdef __cplusplus
|
|
46
|
+
}
|
|
47
|
+
#endif
|
|
48
|
+
|
|
49
|
+
#endif /* RBFFI_STRUCTBYREFERENCE_H */
|
|
50
|
+
|
data/ext/ffi_c/StructLayout.c
CHANGED
|
@@ -52,6 +52,8 @@ static void struct_layout_free(StructLayout *);
|
|
|
52
52
|
static void struct_field_mark(StructField* );
|
|
53
53
|
|
|
54
54
|
VALUE rbffi_StructLayoutFieldClass = Qnil;
|
|
55
|
+
VALUE rbffi_StructLayoutNumberFieldClass = Qnil, rbffi_StructLayoutPointerFieldClass = Qnil;
|
|
56
|
+
VALUE rbffi_StructLayoutStringFieldClass = Qnil;
|
|
55
57
|
VALUE rbffi_StructLayoutFunctionFieldClass = Qnil, rbffi_StructLayoutArrayFieldClass = Qnil;
|
|
56
58
|
|
|
57
59
|
VALUE rbffi_StructLayoutClass = Qnil;
|
|
@@ -320,6 +322,7 @@ struct_layout_allocate(VALUE klass)
|
|
|
320
322
|
layout->rbFieldMap = Qnil;
|
|
321
323
|
layout->rbFieldNames = Qnil;
|
|
322
324
|
layout->rbFields = Qnil;
|
|
325
|
+
layout->fieldSymbolTable = st_init_numtable();
|
|
323
326
|
layout->base.ffiType = xcalloc(1, sizeof(*layout->base.ffiType));
|
|
324
327
|
layout->base.ffiType->size = 0;
|
|
325
328
|
layout->base.ffiType->alignment = 0;
|
|
@@ -329,29 +332,29 @@ struct_layout_allocate(VALUE klass)
|
|
|
329
332
|
}
|
|
330
333
|
|
|
331
334
|
static VALUE
|
|
332
|
-
struct_layout_initialize(VALUE self, VALUE
|
|
335
|
+
struct_layout_initialize(VALUE self, VALUE fields, VALUE size, VALUE align)
|
|
333
336
|
{
|
|
334
337
|
StructLayout* layout;
|
|
335
338
|
ffi_type* ltype;
|
|
336
339
|
int i;
|
|
337
340
|
|
|
338
341
|
Data_Get_Struct(self, StructLayout, layout);
|
|
342
|
+
layout->fieldCount = RARRAY_LEN(fields);
|
|
339
343
|
layout->rbFieldMap = rb_hash_new();
|
|
340
|
-
layout->rbFieldNames =
|
|
344
|
+
layout->rbFieldNames = rb_ary_new2(layout->fieldCount);
|
|
341
345
|
layout->size = NUM2INT(size);
|
|
342
346
|
layout->align = NUM2INT(align);
|
|
343
|
-
layout->fieldCount = RARRAY_LEN(field_names);
|
|
344
347
|
layout->fields = xcalloc(layout->fieldCount, sizeof(StructField *));
|
|
345
348
|
layout->ffiTypes = xcalloc(layout->fieldCount + 1, sizeof(ffi_type *));
|
|
346
349
|
layout->rbFields = rb_ary_new2(layout->fieldCount);
|
|
347
350
|
layout->base.ffiType->elements = layout->ffiTypes;
|
|
348
|
-
layout->base.ffiType->size =
|
|
349
|
-
layout->base.ffiType->alignment =
|
|
351
|
+
layout->base.ffiType->size = layout->size;
|
|
352
|
+
layout->base.ffiType->alignment = layout->align;
|
|
350
353
|
|
|
351
354
|
ltype = layout->base.ffiType;
|
|
352
355
|
for (i = 0; i < (int) layout->fieldCount; ++i) {
|
|
353
|
-
VALUE
|
|
354
|
-
VALUE
|
|
356
|
+
VALUE rbField = rb_ary_entry(fields, i);
|
|
357
|
+
VALUE rbName;
|
|
355
358
|
StructField* field;
|
|
356
359
|
ffi_type* ftype;
|
|
357
360
|
|
|
@@ -359,6 +362,7 @@ struct_layout_initialize(VALUE self, VALUE field_names, VALUE fields, VALUE size
|
|
|
359
362
|
if (!rb_obj_is_kind_of(rbField, rbffi_StructLayoutFieldClass)) {
|
|
360
363
|
rb_raise(rb_eTypeError, "wrong type for field %d.", i);
|
|
361
364
|
}
|
|
365
|
+
rbName = rb_funcall2(rbField, rb_intern("name"), 0, NULL);
|
|
362
366
|
|
|
363
367
|
Data_Get_Struct(rbField, StructField, field = layout->fields[i]);
|
|
364
368
|
|
|
@@ -371,20 +375,17 @@ struct_layout_initialize(VALUE self, VALUE field_names, VALUE fields, VALUE size
|
|
|
371
375
|
rb_raise(rb_eTypeError, "type of field %d has zero size", i);
|
|
372
376
|
}
|
|
373
377
|
|
|
374
|
-
rb_hash_aset(layout->rbFieldMap, rbName, rbField);
|
|
375
378
|
layout->ffiTypes[i] = ftype;
|
|
379
|
+
st_insert(layout->fieldSymbolTable, rbName, rbField);
|
|
380
|
+
rb_hash_aset(layout->rbFieldMap, rbName, rbField);
|
|
376
381
|
rb_ary_push(layout->rbFields, rbField);
|
|
377
|
-
|
|
378
|
-
ltype->alignment = MAX(ltype->alignment, ftype->alignment);
|
|
382
|
+
rb_ary_push(layout->rbFieldNames, rbName);
|
|
379
383
|
}
|
|
380
384
|
|
|
381
385
|
if (ltype->size == 0) {
|
|
382
386
|
rb_raise(rb_eRuntimeError, "Struct size is zero");
|
|
383
387
|
}
|
|
384
388
|
|
|
385
|
-
// Include tail padding
|
|
386
|
-
ltype->size = FFI_ALIGN(ltype->size, ltype->alignment);
|
|
387
|
-
|
|
388
389
|
return self;
|
|
389
390
|
}
|
|
390
391
|
|
|
@@ -442,6 +443,7 @@ struct_layout_free(StructLayout *layout)
|
|
|
442
443
|
xfree(layout->ffiTypes);
|
|
443
444
|
xfree(layout->base.ffiType);
|
|
444
445
|
xfree(layout->fields);
|
|
446
|
+
st_free_table(layout->fieldSymbolTable);
|
|
445
447
|
xfree(layout);
|
|
446
448
|
}
|
|
447
449
|
|
|
@@ -455,6 +457,15 @@ rbffi_StructLayout_Init(VALUE moduleFFI)
|
|
|
455
457
|
rbffi_StructLayoutFieldClass = rb_define_class_under(rbffi_StructLayoutClass, "Field", rb_cObject);
|
|
456
458
|
rb_global_variable(&rbffi_StructLayoutFieldClass);
|
|
457
459
|
|
|
460
|
+
rbffi_StructLayoutNumberFieldClass = rb_define_class_under(rbffi_StructLayoutClass, "Number", rbffi_StructLayoutFieldClass);
|
|
461
|
+
rb_global_variable(&rbffi_StructLayoutNumberFieldClass);
|
|
462
|
+
|
|
463
|
+
rbffi_StructLayoutStringFieldClass = rb_define_class_under(rbffi_StructLayoutClass, "String", rbffi_StructLayoutFieldClass);
|
|
464
|
+
rb_global_variable(&rbffi_StructLayoutStringFieldClass);
|
|
465
|
+
|
|
466
|
+
rbffi_StructLayoutPointerFieldClass = rb_define_class_under(rbffi_StructLayoutClass, "Pointer", rbffi_StructLayoutFieldClass);
|
|
467
|
+
rb_global_variable(&rbffi_StructLayoutPointerFieldClass);
|
|
468
|
+
|
|
458
469
|
rbffi_StructLayoutFunctionFieldClass = rb_define_class_under(rbffi_StructLayoutClass, "Function", rbffi_StructLayoutFieldClass);
|
|
459
470
|
rb_global_variable(&rbffi_StructLayoutFunctionFieldClass);
|
|
460
471
|
|
|
@@ -478,7 +489,7 @@ rbffi_StructLayout_Init(VALUE moduleFFI)
|
|
|
478
489
|
rb_define_method(rbffi_StructLayoutArrayFieldClass, "put", array_field_put, 2);
|
|
479
490
|
|
|
480
491
|
rb_define_alloc_func(rbffi_StructLayoutClass, struct_layout_allocate);
|
|
481
|
-
rb_define_method(rbffi_StructLayoutClass, "initialize", struct_layout_initialize,
|
|
492
|
+
rb_define_method(rbffi_StructLayoutClass, "initialize", struct_layout_initialize, 3);
|
|
482
493
|
rb_define_method(rbffi_StructLayoutClass, "[]", struct_layout_aref, 1);
|
|
483
494
|
rb_define_method(rbffi_StructLayoutClass, "fields", struct_layout_fields, 0);
|
|
484
495
|
rb_define_method(rbffi_StructLayoutClass, "members", struct_layout_members, 0);
|
data/ext/ffi_c/Type.c
CHANGED
|
@@ -1,28 +1,19 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* Copyright (c) 2009, Wayne Meissner
|
|
3
|
-
* All rights reserved.
|
|
4
3
|
*
|
|
5
|
-
*
|
|
6
|
-
* modification, are permitted provided that the following conditions are met:
|
|
4
|
+
* This file is part of ruby-ffi.
|
|
7
5
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* this list of conditions and the following disclaimer in the documentation
|
|
12
|
-
* and/or other materials provided with the distribution.
|
|
13
|
-
* * The name of the author or authors may not be used to endorse or promote
|
|
14
|
-
* products derived from this software without specific prior written permission.
|
|
6
|
+
* This code is free software: you can redistribute it and/or modify it under
|
|
7
|
+
* the terms of the GNU Lesser General Public License version 3 only, as
|
|
8
|
+
* published by the Free Software Foundation.
|
|
15
9
|
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
24
|
-
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
25
|
-
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
10
|
+
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
11
|
+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
12
|
+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
|
13
|
+
* version 3 for more details.
|
|
14
|
+
*
|
|
15
|
+
* You should have received a copy of the GNU Lesser General Public License
|
|
16
|
+
* version 3 along with this work. If not, see <http://www.gnu.org/licenses/>.
|
|
26
17
|
*/
|
|
27
18
|
|
|
28
19
|
#include <sys/param.h>
|
|
@@ -42,7 +33,7 @@ typedef struct BuiltinType_ {
|
|
|
42
33
|
|
|
43
34
|
static void builtin_type_free(BuiltinType *);
|
|
44
35
|
|
|
45
|
-
VALUE rbffi_TypeClass = Qnil
|
|
36
|
+
VALUE rbffi_TypeClass = Qnil;
|
|
46
37
|
|
|
47
38
|
static VALUE classBuiltinType = Qnil;
|
|
48
39
|
static VALUE typeMap = Qnil, sizeMap = Qnil;
|
|
@@ -104,41 +95,12 @@ type_alignment(VALUE self)
|
|
|
104
95
|
static VALUE
|
|
105
96
|
type_inspect(VALUE self)
|
|
106
97
|
{
|
|
107
|
-
char buf[256];
|
|
108
98
|
Type *type;
|
|
109
99
|
|
|
110
100
|
Data_Get_Struct(self, Type, type);
|
|
111
|
-
snprintf(buf, sizeof(buf), "#<FFI::Type:%p size=%d alignment=%d>",
|
|
112
|
-
type, (int) type->ffiType->size, (int) type->ffiType->alignment);
|
|
113
|
-
|
|
114
|
-
return rb_str_new2(buf);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
static VALUE
|
|
118
|
-
enum_allocate(VALUE klass)
|
|
119
|
-
{
|
|
120
|
-
Type* type;
|
|
121
|
-
VALUE obj;
|
|
122
|
-
|
|
123
|
-
obj = Data_Make_Struct(klass, Type, NULL, -1, type);
|
|
124
|
-
type->nativeType = NATIVE_ENUM;
|
|
125
|
-
type->ffiType = &ffi_type_sint;
|
|
126
|
-
|
|
127
|
-
return obj;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
int
|
|
131
|
-
rbffi_Type_GetIntValue(VALUE type)
|
|
132
|
-
{
|
|
133
|
-
Type* t;
|
|
134
|
-
|
|
135
|
-
if (!rb_obj_is_kind_of(type, rbffi_TypeClass)) {
|
|
136
|
-
rb_raise(rb_eTypeError, "wrong type. Expected (FFI::Type)");
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
Data_Get_Struct(type, Type, t);
|
|
140
101
|
|
|
141
|
-
return
|
|
102
|
+
return rb_sprintf("#<%s:%p size=%d alignment=%d>",
|
|
103
|
+
rb_obj_classname(self), type, (int) type->ffiType->size, (int) type->ffiType->alignment);
|
|
142
104
|
}
|
|
143
105
|
|
|
144
106
|
static VALUE
|
|
@@ -166,14 +128,11 @@ builtin_type_free(BuiltinType *type)
|
|
|
166
128
|
static VALUE
|
|
167
129
|
builtin_type_inspect(VALUE self)
|
|
168
130
|
{
|
|
169
|
-
char buf[256];
|
|
170
131
|
BuiltinType *type;
|
|
171
132
|
|
|
172
133
|
Data_Get_Struct(self, BuiltinType, type);
|
|
173
|
-
|
|
174
|
-
type->name, (int) type->type.ffiType->size, type->type.ffiType->alignment);
|
|
175
|
-
|
|
176
|
-
return rb_str_new2(buf);
|
|
134
|
+
return rb_sprintf("#<%s:%s size=%d alignment=%d>",
|
|
135
|
+
rb_obj_classname(self), type->name, (int) type->type.ffiType->size, type->type.ffiType->alignment);
|
|
177
136
|
}
|
|
178
137
|
|
|
179
138
|
int
|
|
@@ -231,8 +190,7 @@ rbffi_Type_Find(VALUE name)
|
|
|
231
190
|
VALUE rbType = rbffi_Type_Lookup(name);
|
|
232
191
|
|
|
233
192
|
if (!RTEST(rbType)) {
|
|
234
|
-
|
|
235
|
-
rb_raise(rb_eTypeError, "Invalid type (%s)", RSTRING_PTR(typeName));
|
|
193
|
+
rb_raise(rb_eTypeError, "invalid type, %s", RSTRING_PTR(rb_inspect(name)));
|
|
236
194
|
}
|
|
237
195
|
|
|
238
196
|
return rbType;
|
|
@@ -243,7 +201,6 @@ rbffi_Type_Init(VALUE moduleFFI)
|
|
|
243
201
|
{
|
|
244
202
|
VALUE moduleNativeType;
|
|
245
203
|
VALUE classType = rbffi_TypeClass = rb_define_class_under(moduleFFI, "Type", rb_cObject);
|
|
246
|
-
VALUE classEnum = rbffi_EnumTypeClass = rb_define_class_under(moduleFFI, "Enum", classType);
|
|
247
204
|
|
|
248
205
|
rb_define_const(moduleFFI, "TypeDefs", typeMap = rb_hash_new());
|
|
249
206
|
rb_define_const(moduleFFI, "SizeTypes", sizeMap = rb_hash_new());
|
|
@@ -270,9 +227,7 @@ rbffi_Type_Init(VALUE moduleFFI)
|
|
|
270
227
|
// Make Type::Builtin non-allocatable
|
|
271
228
|
rb_undef_method(CLASS_OF(classBuiltinType), "new");
|
|
272
229
|
rb_define_method(classBuiltinType, "inspect", builtin_type_inspect, 0);
|
|
273
|
-
|
|
274
|
-
rb_define_alloc_func(classEnum, enum_allocate);
|
|
275
|
-
|
|
230
|
+
|
|
276
231
|
rb_global_variable(&rbffi_TypeClass);
|
|
277
232
|
rb_global_variable(&classBuiltinType);
|
|
278
233
|
|
|
@@ -284,29 +239,45 @@ rbffi_Type_Init(VALUE moduleFFI)
|
|
|
284
239
|
rb_define_const(moduleFFI, "TYPE_" #x, t); \
|
|
285
240
|
} while(0)
|
|
286
241
|
|
|
242
|
+
#define A(old_type, new_type) do { \
|
|
243
|
+
VALUE t = rb_const_get(classType, rb_intern(#old_type)); \
|
|
244
|
+
rb_const_set(classType, rb_intern(#new_type), t); \
|
|
245
|
+
} while(0)
|
|
246
|
+
|
|
287
247
|
T(VOID, &ffi_type_void);
|
|
288
248
|
T(INT8, &ffi_type_sint8);
|
|
249
|
+
A(INT8, SCHAR);
|
|
250
|
+
A(INT8, CHAR);
|
|
289
251
|
T(UINT8, &ffi_type_uint8);
|
|
252
|
+
A(UINT8, UCHAR);
|
|
253
|
+
|
|
290
254
|
T(INT16, &ffi_type_sint16);
|
|
255
|
+
A(INT16, SHORT);
|
|
256
|
+
A(INT16, SSHORT);
|
|
291
257
|
T(UINT16, &ffi_type_uint16);
|
|
258
|
+
A(UINT16, USHORT);
|
|
292
259
|
T(INT32, &ffi_type_sint32);
|
|
260
|
+
A(INT32, INT);
|
|
261
|
+
A(INT32, SINT);
|
|
293
262
|
T(UINT32, &ffi_type_uint32);
|
|
263
|
+
A(UINT32, UINT);
|
|
294
264
|
T(INT64, &ffi_type_sint64);
|
|
265
|
+
A(INT64, LONG_LONG);
|
|
266
|
+
A(INT64, SLONG_LONG);
|
|
295
267
|
T(UINT64, &ffi_type_uint64);
|
|
268
|
+
A(UINT64, ULONG_LONG);
|
|
296
269
|
T(LONG, &ffi_type_slong);
|
|
270
|
+
A(LONG, SLONG);
|
|
297
271
|
T(ULONG, &ffi_type_ulong);
|
|
298
272
|
T(FLOAT32, &ffi_type_float);
|
|
273
|
+
A(FLOAT32, FLOAT);
|
|
299
274
|
T(FLOAT64, &ffi_type_double);
|
|
275
|
+
A(FLOAT64, DOUBLE);
|
|
300
276
|
T(POINTER, &ffi_type_pointer);
|
|
301
277
|
T(STRING, &ffi_type_pointer);
|
|
302
|
-
T(RBXSTRING, &ffi_type_pointer);
|
|
303
278
|
T(BUFFER_IN, &ffi_type_pointer);
|
|
304
279
|
T(BUFFER_OUT, &ffi_type_pointer);
|
|
305
280
|
T(BUFFER_INOUT, &ffi_type_pointer);
|
|
306
|
-
T(ENUM, &ffi_type_sint);
|
|
307
281
|
T(BOOL, &ffi_type_uchar);
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
T(CHAR_ARRAY, &ffi_type_void);
|
|
311
282
|
T(VARARGS, &ffi_type_void);
|
|
312
283
|
}
|
data/ext/ffi_c/Type.h
CHANGED
|
@@ -1,28 +1,19 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* Copyright (c) 2009, Wayne Meissner
|
|
3
|
-
* All rights reserved.
|
|
4
3
|
*
|
|
5
|
-
*
|
|
6
|
-
* modification, are permitted provided that the following conditions are met:
|
|
4
|
+
* This file is part of ruby-ffi.
|
|
7
5
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* this list of conditions and the following disclaimer in the documentation
|
|
12
|
-
* and/or other materials provided with the distribution.
|
|
13
|
-
* * The name of the author or authors may not be used to endorse or promote
|
|
14
|
-
* products derived from this software without specific prior written permission.
|
|
6
|
+
* This code is free software: you can redistribute it and/or modify it under
|
|
7
|
+
* the terms of the GNU Lesser General Public License version 3 only, as
|
|
8
|
+
* published by the Free Software Foundation.
|
|
15
9
|
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
24
|
-
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
25
|
-
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
10
|
+
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
11
|
+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
12
|
+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
|
13
|
+
* version 3 for more details.
|
|
14
|
+
*
|
|
15
|
+
* You should have received a copy of the GNU Lesser General Public License
|
|
16
|
+
* version 3 along with this work. If not, see <http://www.gnu.org/licenses/>.
|
|
26
17
|
*/
|
|
27
18
|
|
|
28
19
|
#ifndef RBFFI_TYPE_H
|
|
@@ -44,8 +35,7 @@ struct Type_ {
|
|
|
44
35
|
ffi_type* ffiType;
|
|
45
36
|
};
|
|
46
37
|
|
|
47
|
-
extern VALUE rbffi_TypeClass
|
|
48
|
-
extern int rbffi_Type_GetIntValue(VALUE type);
|
|
38
|
+
extern VALUE rbffi_TypeClass;
|
|
49
39
|
extern VALUE rbffi_Type_Lookup(VALUE type);
|
|
50
40
|
extern VALUE rbffi_Type_Find(VALUE type);
|
|
51
41
|
|
data/ext/ffi_c/Types.c
CHANGED
|
@@ -34,9 +34,10 @@
|
|
|
34
34
|
#include "StructByValue.h"
|
|
35
35
|
#include "Types.h"
|
|
36
36
|
#include "Struct.h"
|
|
37
|
+
#include "MappedType.h"
|
|
37
38
|
#include "MemoryPointer.h"
|
|
38
39
|
|
|
39
|
-
static ID
|
|
40
|
+
static ID id_from_native = 0;
|
|
40
41
|
|
|
41
42
|
|
|
42
43
|
VALUE
|
|
@@ -76,14 +77,15 @@ rbffi_NativeValue_ToRuby(Type* type, VALUE rbType, const void* ptr, VALUE enums)
|
|
|
76
77
|
case NATIVE_POINTER:
|
|
77
78
|
return rbffi_Pointer_NewInstance(*(void **) ptr);
|
|
78
79
|
case NATIVE_BOOL:
|
|
79
|
-
return ((
|
|
80
|
-
case NATIVE_ENUM:
|
|
81
|
-
return rb_funcall(rbType, id_find, 1, INT2NUM((unsigned int) *(ffi_arg *) ptr));
|
|
80
|
+
return ((unsigned char) *(ffi_arg *) ptr) ? Qtrue : Qfalse;
|
|
82
81
|
|
|
83
82
|
case NATIVE_FUNCTION:
|
|
84
83
|
case NATIVE_CALLBACK: {
|
|
85
|
-
return
|
|
84
|
+
return *(void **) ptr != NULL
|
|
85
|
+
? rbffi_Function_NewInstance(rbType, rbffi_Pointer_NewInstance(*(void **) ptr))
|
|
86
|
+
: Qnil;
|
|
86
87
|
}
|
|
88
|
+
|
|
87
89
|
case NATIVE_STRUCT: {
|
|
88
90
|
StructByValue* sbv = (StructByValue *)type;
|
|
89
91
|
AbstractMemory* mem;
|
|
@@ -95,6 +97,19 @@ rbffi_NativeValue_ToRuby(Type* type, VALUE rbType, const void* ptr, VALUE enums)
|
|
|
95
97
|
return rb_class_new_instance(1, &rbMemory, sbv->rbStructClass);
|
|
96
98
|
}
|
|
97
99
|
|
|
100
|
+
case NATIVE_MAPPED: {
|
|
101
|
+
// For mapped types, first convert to the real native type, then upcall to
|
|
102
|
+
// ruby to convert to the expected return type
|
|
103
|
+
MappedType* m;
|
|
104
|
+
VALUE values[2];
|
|
105
|
+
|
|
106
|
+
Data_Get_Struct(rbType, MappedType, m);
|
|
107
|
+
values[0] = rbffi_NativeValue_ToRuby(m->type, m->rbType, ptr, enums);
|
|
108
|
+
values[1] = Qnil;
|
|
109
|
+
|
|
110
|
+
return rb_funcall2(m->rbConverter, id_from_native, 2, values);
|
|
111
|
+
}
|
|
112
|
+
|
|
98
113
|
default:
|
|
99
114
|
rb_raise(rb_eRuntimeError, "Unknown type: %d", type->nativeType);
|
|
100
115
|
return Qnil;
|
|
@@ -104,6 +119,6 @@ rbffi_NativeValue_ToRuby(Type* type, VALUE rbType, const void* ptr, VALUE enums)
|
|
|
104
119
|
void
|
|
105
120
|
rbffi_Types_Init(VALUE moduleFFI)
|
|
106
121
|
{
|
|
107
|
-
|
|
122
|
+
id_from_native = rb_intern("from_native");
|
|
108
123
|
}
|
|
109
124
|
|
data/ext/ffi_c/Types.h
CHANGED
|
@@ -57,20 +57,20 @@ typedef enum {
|
|
|
57
57
|
NATIVE_CHAR_ARRAY,
|
|
58
58
|
NATIVE_BOOL,
|
|
59
59
|
|
|
60
|
-
/**
|
|
61
|
-
* An immutable string. Nul terminated, but only copies in to the native function
|
|
62
|
-
*/
|
|
60
|
+
/** An immutable string. Nul terminated, but only copies in to the native function */
|
|
63
61
|
NATIVE_STRING,
|
|
64
|
-
|
|
65
|
-
NATIVE_RBXSTRING,
|
|
62
|
+
|
|
66
63
|
/** The function takes a variable number of arguments */
|
|
67
64
|
NATIVE_VARARGS,
|
|
68
|
-
|
|
69
|
-
NATIVE_ENUM,
|
|
65
|
+
|
|
70
66
|
/** Struct-by-value param or result */
|
|
71
67
|
NATIVE_STRUCT,
|
|
68
|
+
|
|
72
69
|
/** An array type definition */
|
|
73
70
|
NATIVE_ARRAY,
|
|
71
|
+
|
|
72
|
+
/** Custom native type */
|
|
73
|
+
NATIVE_MAPPED,
|
|
74
74
|
} NativeType;
|
|
75
75
|
|
|
76
76
|
#include <ffi.h>
|
data/ext/ffi_c/Variadic.c
CHANGED
|
@@ -155,7 +155,7 @@ variadic_invoke(VALUE self, VALUE parameterTypes, VALUE parameterValues)
|
|
|
155
155
|
void** ffiValues;
|
|
156
156
|
ffi_type** ffiParamTypes;
|
|
157
157
|
ffi_type* ffiReturnType;
|
|
158
|
-
|
|
158
|
+
Type** paramTypes;
|
|
159
159
|
VALUE* argv;
|
|
160
160
|
int paramCount = 0, i;
|
|
161
161
|
ffi_status ffiStatus;
|
|
@@ -165,7 +165,7 @@ variadic_invoke(VALUE self, VALUE parameterTypes, VALUE parameterValues)
|
|
|
165
165
|
|
|
166
166
|
Data_Get_Struct(self, VariadicInvoker, invoker);
|
|
167
167
|
paramCount = RARRAY_LEN(parameterTypes);
|
|
168
|
-
paramTypes = ALLOCA_N(
|
|
168
|
+
paramTypes = ALLOCA_N(Type *, paramCount);
|
|
169
169
|
ffiParamTypes = ALLOCA_N(ffi_type *, paramCount);
|
|
170
170
|
params = ALLOCA_N(FFIStorage, paramCount);
|
|
171
171
|
ffiValues = ALLOCA_N(void*, paramCount);
|
|
@@ -173,36 +173,40 @@ variadic_invoke(VALUE self, VALUE parameterTypes, VALUE parameterValues)
|
|
|
173
173
|
retval = alloca(MAX(invoker->returnType->ffiType->size, FFI_SIZEOF_ARG));
|
|
174
174
|
|
|
175
175
|
for (i = 0; i < paramCount; ++i) {
|
|
176
|
-
VALUE
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
176
|
+
VALUE rbType = rb_ary_entry(parameterTypes, i);
|
|
177
|
+
|
|
178
|
+
if (!rb_obj_is_kind_of(rbType, rbffi_TypeClass)) {
|
|
179
|
+
rb_raise(rb_eTypeError, "wrong type. Expected (FFI::Type)");
|
|
180
|
+
}
|
|
181
|
+
Data_Get_Struct(rbType, Type, paramTypes[i]);
|
|
180
182
|
|
|
181
|
-
switch (
|
|
183
|
+
switch (paramTypes[i]->nativeType) {
|
|
182
184
|
case NATIVE_INT8:
|
|
183
185
|
case NATIVE_INT16:
|
|
184
186
|
case NATIVE_INT32:
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
ffiParamTypes[i] = &ffi_type_sint;
|
|
187
|
+
rbType = rb_const_get(rbffi_TypeClass, rb_intern("INT32"));
|
|
188
|
+
Data_Get_Struct(rbType, Type, paramTypes[i]);
|
|
188
189
|
break;
|
|
189
190
|
case NATIVE_UINT8:
|
|
190
191
|
case NATIVE_UINT16:
|
|
191
192
|
case NATIVE_UINT32:
|
|
192
|
-
|
|
193
|
-
|
|
193
|
+
rbType = rb_const_get(rbffi_TypeClass, rb_intern("UINT32"));
|
|
194
|
+
Data_Get_Struct(rbType, Type, paramTypes[i]);
|
|
194
195
|
break;
|
|
196
|
+
|
|
195
197
|
case NATIVE_FLOAT32:
|
|
196
|
-
|
|
197
|
-
|
|
198
|
+
rbType = rb_const_get(rbffi_TypeClass, rb_intern("DOUBLE"));
|
|
199
|
+
Data_Get_Struct(rbType, Type, paramTypes[i]);
|
|
198
200
|
break;
|
|
201
|
+
|
|
199
202
|
default:
|
|
200
|
-
ffiParamTypes[i] = type->ffiType;
|
|
201
203
|
break;
|
|
202
204
|
}
|
|
203
|
-
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
ffiParamTypes[i] = paramTypes[i]->ffiType;
|
|
204
208
|
if (ffiParamTypes[i] == NULL) {
|
|
205
|
-
rb_raise(rb_eArgError, "Invalid parameter type #%x",
|
|
209
|
+
rb_raise(rb_eArgError, "Invalid parameter type #%x", paramTypes[i]);
|
|
206
210
|
}
|
|
207
211
|
argv[i] = rb_ary_entry(parameterValues, i);
|
|
208
212
|
}
|
data/ext/ffi_c/extconf.rb
CHANGED
|
@@ -15,9 +15,13 @@ unless Config::CONFIG['host_os'] =~ /mswin32|mingw32/
|
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
have_func('rb_thread_blocking_region')
|
|
18
|
+
have_func('ruby_thread_has_gvl_p')
|
|
19
|
+
have_func('ruby_native_thread_p')
|
|
20
|
+
have_func('rb_thread_call_with_gvl')
|
|
18
21
|
|
|
19
22
|
$defs << "-DHAVE_EXTCONF_H" if $defs.empty? # needed so create_header works
|
|
20
23
|
$defs << "-DUSE_INTERNAL_LIBFFI" unless libffi_ok
|
|
24
|
+
$defs << "-DRUBY_1_9" if RUBY_VERSION >= "1.9.0"
|
|
21
25
|
|
|
22
26
|
create_header
|
|
23
27
|
|
data/ext/ffi_c/ffi.c
CHANGED
|
@@ -35,9 +35,9 @@
|
|
|
35
35
|
#include "AbstractMemory.h"
|
|
36
36
|
#include "Pointer.h"
|
|
37
37
|
#include "MemoryPointer.h"
|
|
38
|
-
#include "AutoPointer.h"
|
|
39
38
|
#include "Struct.h"
|
|
40
39
|
#include "StructByValue.h"
|
|
40
|
+
#include "StructByReference.h"
|
|
41
41
|
#include "DynamicLibrary.h"
|
|
42
42
|
#include "Platform.h"
|
|
43
43
|
#include "Types.h"
|
|
@@ -47,6 +47,7 @@
|
|
|
47
47
|
#include "MethodHandle.h"
|
|
48
48
|
#include "Call.h"
|
|
49
49
|
#include "ArrayType.h"
|
|
50
|
+
#include "MappedType.h"
|
|
50
51
|
|
|
51
52
|
void Init_ffi_c(void);
|
|
52
53
|
|
|
@@ -59,8 +60,12 @@ Init_ffi_c(void) {
|
|
|
59
60
|
rbffi_FFIModule = moduleFFI = rb_define_module("FFI");
|
|
60
61
|
rb_global_variable(&moduleFFI);
|
|
61
62
|
|
|
63
|
+
|
|
62
64
|
// FFI::Type needs to be initialized before most other classes
|
|
63
65
|
rbffi_Type_Init(moduleFFI);
|
|
66
|
+
|
|
67
|
+
rbffi_DataConverter_Init(moduleFFI);
|
|
68
|
+
|
|
64
69
|
rbffi_ArrayType_Init(moduleFFI);
|
|
65
70
|
rbffi_LastError_Init(moduleFFI);
|
|
66
71
|
rbffi_Call_Init(moduleFFI);
|
|
@@ -69,14 +74,15 @@ Init_ffi_c(void) {
|
|
|
69
74
|
rbffi_Platform_Init(moduleFFI);
|
|
70
75
|
rbffi_AbstractMemory_Init(moduleFFI);
|
|
71
76
|
rbffi_Pointer_Init(moduleFFI);
|
|
72
|
-
rbffi_AutoPointer_Init(moduleFFI);
|
|
73
77
|
rbffi_Function_Init(moduleFFI);
|
|
74
78
|
rbffi_MemoryPointer_Init(moduleFFI);
|
|
75
79
|
rbffi_Buffer_Init(moduleFFI);
|
|
76
80
|
rbffi_StructByValue_Init(moduleFFI);
|
|
81
|
+
rbffi_StructByReference_Init(moduleFFI);
|
|
77
82
|
rbffi_Struct_Init(moduleFFI);
|
|
78
83
|
rbffi_DynamicLibrary_Init(moduleFFI);
|
|
79
84
|
rbffi_Variadic_Init(moduleFFI);
|
|
80
85
|
rbffi_Types_Init(moduleFFI);
|
|
86
|
+
rbffi_MappedType_Init(moduleFFI);
|
|
81
87
|
}
|
|
82
88
|
|
data/ext/ffi_c/libffi/configure
CHANGED
|
@@ -9021,7 +9021,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
|
|
|
9021
9021
|
old_archive_from_new_cmds='true'
|
|
9022
9022
|
# FIXME: Should let the user specify the lib program.
|
|
9023
9023
|
old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs'
|
|
9024
|
-
fix_srcfile_path='`cygpath -w "$srcfile"`'
|
|
9024
|
+
# fix_srcfile_path='`cygpath -w "$srcfile"`'
|
|
9025
9025
|
enable_shared_with_static_runtimes=yes
|
|
9026
9026
|
;;
|
|
9027
9027
|
|
data/ext/ffi_c/libffi.gnu.mk
CHANGED
|
@@ -14,7 +14,7 @@ LIBFFI_BUILD_DIR = $(BUILD_DIR)/libffi
|
|
|
14
14
|
ifeq ($(srcdir),.)
|
|
15
15
|
LIBFFI_SRC_DIR := $(shell pwd)/libffi
|
|
16
16
|
else
|
|
17
|
-
LIBFFI_SRC_DIR := $(srcdir)/libffi
|
|
17
|
+
LIBFFI_SRC_DIR := $(abspath $(srcdir)/libffi)
|
|
18
18
|
endif
|
|
19
19
|
|
|
20
20
|
LIBFFI = $(LIBFFI_BUILD_DIR)/.libs/libffi_convenience.a
|
data/ext/ffi_c/libffi.mk
CHANGED
|
@@ -7,7 +7,7 @@ $(LIBFFI):
|
|
|
7
7
|
@if [ ! -f $(LIBFFI_BUILD_DIR)/Makefile ]; then \
|
|
8
8
|
echo "Configuring libffi"; \
|
|
9
9
|
cd $(LIBFFI_BUILD_DIR) && \
|
|
10
|
-
/usr/bin/env
|
|
10
|
+
/usr/bin/env CFLAGS="$(LIBFFI_CFLAGS)" \
|
|
11
11
|
/bin/sh $(LIBFFI_CONFIGURE) $(LIBFFI_HOST) > /dev/null; \
|
|
12
12
|
fi
|
|
13
13
|
cd $(LIBFFI_BUILD_DIR) && $(MAKE)
|