ffi 1.2.1 → 1.3.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/README.md +10 -5
- data/ext/ffi_c/ArrayType.c +6 -2
- data/ext/ffi_c/Buffer.c +3 -1
- data/ext/ffi_c/Call.c +12 -21
- data/ext/ffi_c/FunctionInfo.c +27 -2
- data/ext/ffi_c/MappedType.c +1 -2
- data/ext/ffi_c/MemoryPointer.c +35 -4
- data/ext/ffi_c/Pointer.c +5 -4
- data/ext/ffi_c/Struct.c +125 -8
- data/ext/ffi_c/StructByReference.c +33 -0
- data/ext/ffi_c/StructByValue.c +2 -2
- data/ext/ffi_c/StructLayout.c +135 -1
- data/ext/ffi_c/Type.c +1 -0
- data/ext/ffi_c/extconf.rb +1 -1
- data/ffi.gemspec +1 -1
- data/lib/ffi.rb +2 -1
- data/lib/ffi/library.rb +2 -0
- data/lib/ffi/managedstruct.rb +37 -37
- data/lib/ffi/struct.rb +74 -1
- data/lib/ffi/struct_layout_builder.rb +50 -1
- data/lib/ffi/tools/generator.rb +2 -0
- data/lib/ffi/tools/generator_task.rb +1 -0
- data/lib/ffi/tools/types_generator.rb +2 -0
- data/libtest/Benchmark.c +1 -15
- data/libtest/BoolTest.c +2 -16
- data/libtest/BufferTest.c +3 -17
- data/libtest/ClosureTest.c +1 -15
- data/libtest/EnumTest.c +1 -15
- data/libtest/FunctionTest.c +2 -16
- data/libtest/GlobalVariable.c +2 -16
- data/libtest/LastErrorTest.c +2 -16
- data/libtest/NumberTest.c +1 -15
- data/libtest/PointerTest.c +1 -15
- data/libtest/ReferenceTest.c +1 -15
- data/libtest/StringTest.c +1 -15
- data/libtest/StructTest.c +1 -15
- data/libtest/UnionTest.c +1 -15
- data/libtest/VariadicTest.c +2 -16
- data/spec/ffi/async_callback_spec.rb +3 -14
- data/spec/ffi/bool_spec.rb +7 -18
- data/spec/ffi/buffer_spec.rb +26 -37
- data/spec/ffi/callback_spec.rb +96 -107
- data/spec/ffi/custom_param_type.rb +2 -13
- data/spec/ffi/custom_type_spec.rb +1 -12
- data/spec/ffi/dup_spec.rb +7 -18
- data/spec/ffi/enum_spec.rb +128 -139
- data/spec/ffi/errno_spec.rb +2 -13
- data/spec/ffi/ffi_spec.rb +4 -15
- data/spec/ffi/function_spec.rb +6 -17
- data/spec/ffi/library_spec.rb +26 -26
- data/spec/ffi/long_double.rb +1 -12
- data/spec/ffi/managed_struct_spec.rb +3 -18
- data/spec/ffi/number_spec.rb +32 -43
- data/spec/ffi/pointer_spec.rb +7 -22
- data/spec/ffi/rbx/memory_pointer_spec.rb +17 -17
- data/spec/ffi/rbx/struct_spec.rb +2 -2
- data/spec/ffi/spec_helper.rb +10 -12
- data/spec/ffi/string_spec.rb +9 -20
- data/spec/ffi/strptr_spec.rb +2 -13
- data/spec/ffi/struct_callback_spec.rb +3 -14
- data/spec/ffi/struct_initialize_spec.rb +3 -14
- data/spec/ffi/struct_packed_spec.rb +7 -18
- data/spec/ffi/struct_spec.rb +93 -104
- data/spec/ffi/typedef_spec.rb +5 -16
- data/spec/ffi/union_spec.rb +4 -15
- data/spec/ffi/variadic_spec.rb +7 -18
- metadata +73 -58
data/README.md
CHANGED
@@ -22,9 +22,9 @@ using Ruby-FFI [here](http://wiki.github.com/ffi/ffi/why-use-ffi).
|
|
22
22
|
require 'ffi'
|
23
23
|
|
24
24
|
module MyLib
|
25
|
-
extend FFI::Library
|
26
|
-
ffi_lib 'c'
|
27
|
-
attach_function :puts, [ :string ], :int
|
25
|
+
extend FFI::Library
|
26
|
+
ffi_lib 'c'
|
27
|
+
attach_function :puts, [ :string ], :int
|
28
28
|
end
|
29
29
|
|
30
30
|
MyLib.puts 'Hello, World using libc!'
|
@@ -38,7 +38,10 @@ For less minimalistic and more sane examples you may look at:
|
|
38
38
|
|
39
39
|
## Requirements
|
40
40
|
|
41
|
-
|
41
|
+
You need a sane building environment in order to compile the extension.
|
42
|
+
At a minimum, you will need:
|
43
|
+
* A C compiler (e.g. Xcode on OSX, gcc on everything else)
|
44
|
+
* libffi development library - this is commonly in the libffi-dev or libffi-devel
|
42
45
|
|
43
46
|
## Installation
|
44
47
|
|
@@ -54,7 +57,9 @@ or from the git repository on github:
|
|
54
57
|
|
55
58
|
## License
|
56
59
|
|
57
|
-
|
60
|
+
The ffi library is covered by the LGPL3 license, also see the LICENSE file.
|
61
|
+
The specs are shared with Rubyspec and are licensed by the same license
|
62
|
+
as Rubyspec, see the LICENSE.SPECS file.
|
58
63
|
|
59
64
|
## Credits
|
60
65
|
|
data/ext/ffi_c/ArrayType.c
CHANGED
@@ -126,12 +126,16 @@ array_type_element_type(VALUE self)
|
|
126
126
|
void
|
127
127
|
rbffi_ArrayType_Init(VALUE moduleFFI)
|
128
128
|
{
|
129
|
+
VALUE ffi_Type;
|
130
|
+
|
131
|
+
ffi_Type = rbffi_TypeClass;
|
132
|
+
|
129
133
|
/*
|
130
134
|
* Document-class: FFI::ArrayType < FFI::Type
|
131
135
|
*
|
132
136
|
* This is a typed array. The type is a {NativeType native type}.
|
133
137
|
*/
|
134
|
-
rbffi_ArrayTypeClass = rb_define_class_under(moduleFFI, "ArrayType",
|
138
|
+
rbffi_ArrayTypeClass = rb_define_class_under(moduleFFI, "ArrayType", ffi_Type);
|
135
139
|
/*
|
136
140
|
* Document-variable: FFI::ArrayType
|
137
141
|
*/
|
@@ -139,7 +143,7 @@ rbffi_ArrayType_Init(VALUE moduleFFI)
|
|
139
143
|
/*
|
140
144
|
* Document-constant: FFI::Type::Array
|
141
145
|
*/
|
142
|
-
rb_define_const(
|
146
|
+
rb_define_const(ffi_Type, "Array", rbffi_ArrayTypeClass);
|
143
147
|
|
144
148
|
rb_define_alloc_func(rbffi_ArrayTypeClass, array_type_s_allocate);
|
145
149
|
rb_define_method(rbffi_ArrayTypeClass, "initialize", array_type_initialize, 2);
|
data/ext/ffi_c/Buffer.c
CHANGED
@@ -310,12 +310,14 @@ buffer_mark(Buffer* ptr)
|
|
310
310
|
void
|
311
311
|
rbffi_Buffer_Init(VALUE moduleFFI)
|
312
312
|
{
|
313
|
+
VALUE ffi_AbstractMemory = rbffi_AbstractMemoryClass;
|
314
|
+
|
313
315
|
/*
|
314
316
|
* Document-class: FFI::Buffer < FFI::AbstractMemory
|
315
317
|
*
|
316
318
|
* A Buffer is a function argument type. It should be use with functions playing with C arrays.
|
317
319
|
*/
|
318
|
-
BufferClass = rb_define_class_under(moduleFFI, "Buffer",
|
320
|
+
BufferClass = rb_define_class_under(moduleFFI, "Buffer", ffi_AbstractMemory);
|
319
321
|
|
320
322
|
/*
|
321
323
|
* Document-variable: FFI::Buffer
|
data/ext/ffi_c/Call.c
CHANGED
@@ -79,7 +79,6 @@ typedef int bool;
|
|
79
79
|
|
80
80
|
static void* callback_param(VALUE proc, VALUE cbinfo);
|
81
81
|
static inline void* getPointer(VALUE value, int type);
|
82
|
-
static inline char* getString(VALUE value, int type);
|
83
82
|
|
84
83
|
static ID id_to_ptr, id_map_symbol, id_to_native;
|
85
84
|
|
@@ -221,7 +220,18 @@ rbffi_SetupCallParams(int argc, VALUE* argv, int paramCount, Type** paramTypes,
|
|
221
220
|
|
222
221
|
|
223
222
|
case NATIVE_STRING:
|
224
|
-
|
223
|
+
if (type == T_NIL) {
|
224
|
+
param->ptr = NULL;
|
225
|
+
|
226
|
+
} else {
|
227
|
+
if (rb_safe_level() >= 1 && OBJ_TAINTED(argv[argidx])) {
|
228
|
+
rb_raise(rb_eSecurityError, "Unsafe string parameter");
|
229
|
+
}
|
230
|
+
|
231
|
+
param->ptr = StringValueCStr(argv[argidx]);
|
232
|
+
++argidx;
|
233
|
+
}
|
234
|
+
|
225
235
|
ADJ(param, ADDRESS);
|
226
236
|
break;
|
227
237
|
|
@@ -397,25 +407,6 @@ getPointer(VALUE value, int type)
|
|
397
407
|
return NULL;
|
398
408
|
}
|
399
409
|
|
400
|
-
static inline char*
|
401
|
-
getString(VALUE value, int type)
|
402
|
-
{
|
403
|
-
if (type == T_STRING) {
|
404
|
-
|
405
|
-
if (rb_safe_level() >= 1 && OBJ_TAINTED(value)) {
|
406
|
-
rb_raise(rb_eSecurityError, "Unsafe string parameter");
|
407
|
-
}
|
408
|
-
|
409
|
-
return StringValueCStr(value);
|
410
|
-
|
411
|
-
} else if (type == T_NIL) {
|
412
|
-
return NULL;
|
413
|
-
}
|
414
|
-
|
415
|
-
rb_raise(rb_eArgError, "Invalid String value");
|
416
|
-
}
|
417
|
-
|
418
|
-
|
419
410
|
Invoker
|
420
411
|
rbffi_GetInvoker(FunctionType *fnInfo)
|
421
412
|
{
|
data/ext/ffi_c/FunctionInfo.c
CHANGED
@@ -91,6 +91,17 @@ fntype_free(FunctionType* fnInfo)
|
|
91
91
|
xfree(fnInfo);
|
92
92
|
}
|
93
93
|
|
94
|
+
/*
|
95
|
+
* call-seq: initialize(return_type, param_types, options={})
|
96
|
+
* @param [Type, Symbol] return_type return type for the function
|
97
|
+
* @param [Array<Type, Symbol>] param_types array of parameters types
|
98
|
+
* @param [Hash] options
|
99
|
+
* @option options [Boolean] :blocking set to true if the C function is a blocking call
|
100
|
+
* @option options [Symbol] :convention calling convention see {FFI::Library#calling_convention}
|
101
|
+
* @option options [FFI::Enums] :enums
|
102
|
+
* @return [self]
|
103
|
+
* A new FunctionType instance.
|
104
|
+
*/
|
94
105
|
static VALUE
|
95
106
|
fntype_initialize(int argc, VALUE* argv, VALUE self)
|
96
107
|
{
|
@@ -186,6 +197,11 @@ fntype_initialize(int argc, VALUE* argv, VALUE self)
|
|
186
197
|
return self;
|
187
198
|
}
|
188
199
|
|
200
|
+
/*
|
201
|
+
* call-seq: result_type
|
202
|
+
* @return [Type]
|
203
|
+
* Get the return type of the function type
|
204
|
+
*/
|
189
205
|
static VALUE
|
190
206
|
fntype_result_type(VALUE self)
|
191
207
|
{
|
@@ -196,6 +212,11 @@ fntype_result_type(VALUE self)
|
|
196
212
|
return ft->rbReturnType;
|
197
213
|
}
|
198
214
|
|
215
|
+
/*
|
216
|
+
* call-seq: param_types
|
217
|
+
* @return [Array<Type>]
|
218
|
+
* Get parameters types.
|
219
|
+
*/
|
199
220
|
static VALUE
|
200
221
|
fntype_param_types(VALUE self)
|
201
222
|
{
|
@@ -209,10 +230,14 @@ fntype_param_types(VALUE self)
|
|
209
230
|
void
|
210
231
|
rbffi_FunctionInfo_Init(VALUE moduleFFI)
|
211
232
|
{
|
233
|
+
VALUE ffi_Type;
|
234
|
+
|
235
|
+
ffi_Type = rbffi_TypeClass;
|
236
|
+
|
212
237
|
/*
|
213
238
|
* Document-class: FFI::FunctionType < FFI::Type
|
214
239
|
*/
|
215
|
-
rbffi_FunctionTypeClass = rb_define_class_under(moduleFFI, "FunctionType",
|
240
|
+
rbffi_FunctionTypeClass = rb_define_class_under(moduleFFI, "FunctionType",ffi_Type);
|
216
241
|
rb_global_variable(&rbffi_FunctionTypeClass);
|
217
242
|
/*
|
218
243
|
* Document-const: FFI::CallbackInfo = FFI::FunctionType
|
@@ -225,7 +250,7 @@ rbffi_FunctionInfo_Init(VALUE moduleFFI)
|
|
225
250
|
/*
|
226
251
|
* Document-const: FFI::Type::Function = FFI::FunctionType
|
227
252
|
*/
|
228
|
-
rb_define_const(
|
253
|
+
rb_define_const(ffi_Type, "Function", rbffi_FunctionTypeClass);
|
229
254
|
|
230
255
|
rb_define_alloc_func(rbffi_FunctionTypeClass, fntype_allocate);
|
231
256
|
rb_define_method(rbffi_FunctionTypeClass, "initialize", fntype_initialize, -1);
|
data/ext/ffi_c/MappedType.c
CHANGED
@@ -138,9 +138,8 @@ mapped_from_native(int argc, VALUE* argv, VALUE self)
|
|
138
138
|
void
|
139
139
|
rbffi_MappedType_Init(VALUE moduleFFI)
|
140
140
|
{
|
141
|
-
|
142
141
|
/*
|
143
|
-
* Document-class: FFI::Type::Mapped
|
142
|
+
* Document-class: FFI::Type::Mapped < FFI::Type
|
144
143
|
*/
|
145
144
|
rbffi_MappedTypeClass = rb_define_class_under(rbffi_TypeClass, "Mapped", rbffi_TypeClass);
|
146
145
|
|
data/ext/ffi_c/MemoryPointer.c
CHANGED
@@ -63,6 +63,14 @@ memptr_allocate(VALUE klass)
|
|
63
63
|
return obj;
|
64
64
|
}
|
65
65
|
|
66
|
+
/*
|
67
|
+
* call-seq: initialize(size, count=1, clear=true)
|
68
|
+
* @param [Fixnum, Bignum, Symbol, FFI::Type] size size of a memory cell (in bytes, or type whom size will be used)
|
69
|
+
* @param [Numeric] count number of cells in memory
|
70
|
+
* @param [Boolean] clear set memory to all-zero if +true+
|
71
|
+
* @return [self]
|
72
|
+
* A new instance of FFI::MeoryPointer.
|
73
|
+
*/
|
66
74
|
static VALUE
|
67
75
|
memptr_initialize(int argc, VALUE* argv, VALUE self)
|
68
76
|
{
|
@@ -71,7 +79,7 @@ memptr_initialize(int argc, VALUE* argv, VALUE self)
|
|
71
79
|
|
72
80
|
memptr_malloc(self, rbffi_type_size(size), nargs > 1 ? NUM2LONG(count) : 1,
|
73
81
|
RTEST(clear) || clear == Qnil);
|
74
|
-
|
82
|
+
|
75
83
|
if (rb_block_given_p()) {
|
76
84
|
return rb_ensure(rb_yield, self, memptr_free, self);
|
77
85
|
}
|
@@ -100,7 +108,7 @@ memptr_malloc(VALUE self, long size, long count, bool clear)
|
|
100
108
|
/* ensure the memory is aligned on at least a 8 byte boundary */
|
101
109
|
p->memory.address = (char *) (((uintptr_t) p->storage + 0x7) & (uintptr_t) ~0x7UL);;
|
102
110
|
p->allocated = true;
|
103
|
-
|
111
|
+
|
104
112
|
if (clear && p->memory.size > 0) {
|
105
113
|
memset(p->memory.address, 0, p->memory.size);
|
106
114
|
}
|
@@ -136,6 +144,12 @@ memptr_release(Pointer* ptr)
|
|
136
144
|
xfree(ptr);
|
137
145
|
}
|
138
146
|
|
147
|
+
/*
|
148
|
+
* call-seq: from_string(s)
|
149
|
+
* @param [String] s string
|
150
|
+
* @return [MemoryPointer]
|
151
|
+
* Create a {MemoryPointer} with +s+ inside.
|
152
|
+
*/
|
139
153
|
static VALUE
|
140
154
|
memptr_s_from_string(VALUE klass, VALUE to_str)
|
141
155
|
{
|
@@ -143,14 +157,31 @@ memptr_s_from_string(VALUE klass, VALUE to_str)
|
|
143
157
|
VALUE args[] = { INT2FIX(1), LONG2NUM(RSTRING_LEN(s) + 1), Qfalse };
|
144
158
|
VALUE obj = rb_class_new_instance(3, args, klass);
|
145
159
|
rb_funcall(obj, rb_intern("put_string"), 2, INT2FIX(0), s);
|
146
|
-
|
160
|
+
|
147
161
|
return obj;
|
148
162
|
}
|
149
163
|
|
150
164
|
void
|
151
165
|
rbffi_MemoryPointer_Init(VALUE moduleFFI)
|
152
166
|
{
|
153
|
-
|
167
|
+
VALUE ffi_Pointer;
|
168
|
+
|
169
|
+
ffi_Pointer = rbffi_PointerClass;
|
170
|
+
|
171
|
+
/*
|
172
|
+
* Document-class: FFI::MemoryPointer < FFI::Pointer
|
173
|
+
* A MemoryPointer is a specific {Pointer}. It points to a memory composed of cells. All cells have the
|
174
|
+
* same size.
|
175
|
+
*
|
176
|
+
* @example Create a new MemoryPointer
|
177
|
+
* mp = FFI::MemoryPointer.new(:long, 16) # Create a pointer on a memory of 16 long ints.
|
178
|
+
* @example Create a new MemoryPointer from a String
|
179
|
+
* mp1 = FFI::MemoryPointer.from_string("this is a string")
|
180
|
+
* # same as:
|
181
|
+
* mp2 = FFI::MemoryPointer.new(:char,16)
|
182
|
+
* mp2.put_string("this is a string")
|
183
|
+
*/
|
184
|
+
rbffi_MemoryPointerClass = rb_define_class_under(moduleFFI, "MemoryPointer", ffi_Pointer);
|
154
185
|
rb_global_variable(&rbffi_MemoryPointerClass);
|
155
186
|
|
156
187
|
rb_define_alloc_func(rbffi_MemoryPointerClass, memptr_allocate);
|
data/ext/ffi_c/Pointer.c
CHANGED
@@ -322,9 +322,9 @@ ptr_address(VALUE self)
|
|
322
322
|
|
323
323
|
/*
|
324
324
|
* Get or set +self+'s endianness
|
325
|
-
* @overload
|
325
|
+
* @overload order
|
326
326
|
* @return [:big, :little] endianness of +self+
|
327
|
-
* @overload
|
327
|
+
* @overload order(order)
|
328
328
|
* @param [Symbol] order endianness to set (+:little+, +:big+ or +:network+). +:big+ and +:network+
|
329
329
|
* are synonymous.
|
330
330
|
* @return [self]
|
@@ -449,8 +449,9 @@ void
|
|
449
449
|
rbffi_Pointer_Init(VALUE moduleFFI)
|
450
450
|
{
|
451
451
|
VALUE rbNullAddress = ULL2NUM(0);
|
452
|
+
VALUE ffi_AbstractMemory = rbffi_AbstractMemoryClass;
|
452
453
|
|
453
|
-
/*
|
454
|
+
/*
|
454
455
|
* Document-class: FFI::Pointer < FFI::AbstractMemory
|
455
456
|
* Pointer class is used to manage C pointers with ease. A {Pointer} object is defined by his
|
456
457
|
* {#address} (as a C pointer). It permits additions with an integer for pointer arithmetic.
|
@@ -459,7 +460,7 @@ rbffi_Pointer_Init(VALUE moduleFFI)
|
|
459
460
|
* A pointer object may autorelease his contents when freed (by default). This behaviour may be
|
460
461
|
* changed with {#autorelease=} method.
|
461
462
|
*/
|
462
|
-
rbffi_PointerClass = rb_define_class_under(moduleFFI, "Pointer",
|
463
|
+
rbffi_PointerClass = rb_define_class_under(moduleFFI, "Pointer", ffi_AbstractMemory);
|
463
464
|
/*
|
464
465
|
* Document-variable: Pointer
|
465
466
|
*/
|
data/ext/ffi_c/Struct.c
CHANGED
@@ -90,6 +90,13 @@ struct_allocate(VALUE klass)
|
|
90
90
|
return obj;
|
91
91
|
}
|
92
92
|
|
93
|
+
/*
|
94
|
+
* call-seq: initialize
|
95
|
+
* @overload initialize(pointer, *args)
|
96
|
+
* @param [AbstractMemory] pointer
|
97
|
+
* @param [Array] args
|
98
|
+
* @return [self]
|
99
|
+
*/
|
93
100
|
static VALUE
|
94
101
|
struct_initialize(int argc, VALUE* argv, VALUE self)
|
95
102
|
{
|
@@ -124,6 +131,11 @@ struct_initialize(int argc, VALUE* argv, VALUE self)
|
|
124
131
|
return self;
|
125
132
|
}
|
126
133
|
|
134
|
+
/*
|
135
|
+
* call-seq: initialize_copy(other)
|
136
|
+
* @return [nil]
|
137
|
+
* DO NOT CALL THIS METHOD
|
138
|
+
*/
|
127
139
|
static VALUE
|
128
140
|
struct_initialize_copy(VALUE self, VALUE other)
|
129
141
|
{
|
@@ -165,11 +177,11 @@ static VALUE
|
|
165
177
|
struct_class_layout(VALUE klass)
|
166
178
|
{
|
167
179
|
VALUE layout;
|
168
|
-
if (!
|
180
|
+
if (!rb_ivar_defined(klass, id_layout_ivar)) {
|
169
181
|
rb_raise(rb_eRuntimeError, "no Struct layout configured for %s", rb_class2name(klass));
|
170
182
|
}
|
171
183
|
|
172
|
-
layout =
|
184
|
+
layout = rb_ivar_get(klass, id_layout_ivar);
|
173
185
|
if (!rb_obj_is_kind_of(layout, rbffi_StructLayoutClass)) {
|
174
186
|
rb_raise(rb_eRuntimeError, "invalid Struct layout for %s", rb_class2name(klass));
|
175
187
|
}
|
@@ -279,6 +291,11 @@ struct_field(Struct* s, VALUE fieldName)
|
|
279
291
|
return rbField;
|
280
292
|
}
|
281
293
|
|
294
|
+
/*
|
295
|
+
* call-seq: struct[field_name]
|
296
|
+
* @param field_name field to access
|
297
|
+
* Acces to a Struct field.
|
298
|
+
*/
|
282
299
|
static VALUE
|
283
300
|
struct_aref(VALUE self, VALUE fieldName)
|
284
301
|
{
|
@@ -304,6 +321,13 @@ struct_aref(VALUE self, VALUE fieldName)
|
|
304
321
|
}
|
305
322
|
}
|
306
323
|
|
324
|
+
/*
|
325
|
+
* call-seq: []=(field_name, value)
|
326
|
+
* @param field_name field to access
|
327
|
+
* @param value value to set to +field_name+
|
328
|
+
* @return [value]
|
329
|
+
* Set a field in Struct.
|
330
|
+
*/
|
307
331
|
static VALUE
|
308
332
|
struct_aset(VALUE self, VALUE fieldName, VALUE value)
|
309
333
|
{
|
@@ -338,6 +362,12 @@ struct_aset(VALUE self, VALUE fieldName, VALUE value)
|
|
338
362
|
return value;
|
339
363
|
}
|
340
364
|
|
365
|
+
/*
|
366
|
+
* call-seq: pointer= pointer
|
367
|
+
* @param [AbstractMemory] pointer
|
368
|
+
* @return [self]
|
369
|
+
* Make Struct point to +pointer+.
|
370
|
+
*/
|
341
371
|
static VALUE
|
342
372
|
struct_set_pointer(VALUE self, VALUE pointer)
|
343
373
|
{
|
@@ -368,6 +398,11 @@ struct_set_pointer(VALUE self, VALUE pointer)
|
|
368
398
|
return self;
|
369
399
|
}
|
370
400
|
|
401
|
+
/*
|
402
|
+
* call-seq: pointer
|
403
|
+
* @return [AbstractMemory]
|
404
|
+
* Get pointer to Struct contents.
|
405
|
+
*/
|
371
406
|
static VALUE
|
372
407
|
struct_get_pointer(VALUE self)
|
373
408
|
{
|
@@ -378,6 +413,12 @@ struct_get_pointer(VALUE self)
|
|
378
413
|
return s->rbPointer;
|
379
414
|
}
|
380
415
|
|
416
|
+
/*
|
417
|
+
* call-seq: layout= layout
|
418
|
+
* @param [StructLayout] layout
|
419
|
+
* @return [self]
|
420
|
+
* Set the Struct's layout.
|
421
|
+
*/
|
381
422
|
static VALUE
|
382
423
|
struct_set_layout(VALUE self, VALUE layout)
|
383
424
|
{
|
@@ -396,6 +437,11 @@ struct_set_layout(VALUE self, VALUE layout)
|
|
396
437
|
return self;
|
397
438
|
}
|
398
439
|
|
440
|
+
/*
|
441
|
+
* call-seq: layout
|
442
|
+
* @return [StructLayout]
|
443
|
+
* Get the Struct's layout.
|
444
|
+
*/
|
399
445
|
static VALUE
|
400
446
|
struct_get_layout(VALUE self)
|
401
447
|
{
|
@@ -406,7 +452,11 @@ struct_get_layout(VALUE self)
|
|
406
452
|
return s->rbLayout;
|
407
453
|
}
|
408
454
|
|
409
|
-
|
455
|
+
/*
|
456
|
+
* call-seq: null?
|
457
|
+
* @return [Boolean]
|
458
|
+
* Test if Struct's pointer is NULL
|
459
|
+
*/
|
410
460
|
static VALUE
|
411
461
|
struct_null_p(VALUE self)
|
412
462
|
{
|
@@ -417,6 +467,9 @@ struct_null_p(VALUE self)
|
|
417
467
|
return s->pointer->address == NULL ? Qtrue : Qfalse;
|
418
468
|
}
|
419
469
|
|
470
|
+
/*
|
471
|
+
* (see Pointer#order)
|
472
|
+
*/
|
420
473
|
static VALUE
|
421
474
|
struct_order(int argc, VALUE* argv, VALUE self)
|
422
475
|
{
|
@@ -435,7 +488,6 @@ struct_order(int argc, VALUE* argv, VALUE self)
|
|
435
488
|
}
|
436
489
|
}
|
437
490
|
|
438
|
-
|
439
491
|
static VALUE
|
440
492
|
inline_array_allocate(VALUE klass)
|
441
493
|
{
|
@@ -456,6 +508,13 @@ inline_array_mark(InlineArray* array)
|
|
456
508
|
rb_gc_mark(array->rbMemory);
|
457
509
|
}
|
458
510
|
|
511
|
+
/*
|
512
|
+
* Document-method: FFI::Struct::InlineArray#initialize
|
513
|
+
* call-seq: initialize(memory, field)
|
514
|
+
* @param [AbstractMemory] memory
|
515
|
+
* @param [StructField] field
|
516
|
+
* @return [self]
|
517
|
+
*/
|
459
518
|
static VALUE
|
460
519
|
inline_array_initialize(VALUE self, VALUE rbMemory, VALUE rbField)
|
461
520
|
{
|
@@ -480,6 +539,11 @@ inline_array_initialize(VALUE self, VALUE rbMemory, VALUE rbField)
|
|
480
539
|
return self;
|
481
540
|
}
|
482
541
|
|
542
|
+
/*
|
543
|
+
* call-seq: size
|
544
|
+
* @return [Numeric]
|
545
|
+
* Get size
|
546
|
+
*/
|
483
547
|
static VALUE
|
484
548
|
inline_array_size(VALUE self)
|
485
549
|
{
|
@@ -500,6 +564,11 @@ inline_array_offset(InlineArray* array, int index)
|
|
500
564
|
return (int) array->field->offset + (index * (int) array->componentType->ffiType->size);
|
501
565
|
}
|
502
566
|
|
567
|
+
/*
|
568
|
+
* call-seq: [](index)
|
569
|
+
* @param [Numeric] index
|
570
|
+
* @return [Type, Struct]
|
571
|
+
*/
|
503
572
|
static VALUE
|
504
573
|
inline_array_aref(VALUE self, VALUE rbIndex)
|
505
574
|
{
|
@@ -530,6 +599,12 @@ inline_array_aref(VALUE self, VALUE rbIndex)
|
|
530
599
|
}
|
531
600
|
}
|
532
601
|
|
602
|
+
/*
|
603
|
+
* call-seq: []=(index, value)
|
604
|
+
* @param [Numeric] index
|
605
|
+
* @param [Type, Struct]
|
606
|
+
* @return [value]
|
607
|
+
*/
|
533
608
|
static VALUE
|
534
609
|
inline_array_aset(VALUE self, VALUE rbIndex, VALUE rbValue)
|
535
610
|
{
|
@@ -574,6 +649,10 @@ inline_array_aset(VALUE self, VALUE rbIndex, VALUE rbValue)
|
|
574
649
|
return rbValue;
|
575
650
|
}
|
576
651
|
|
652
|
+
/*
|
653
|
+
* call-seq: each
|
654
|
+
* Yield block for each element of +self+.
|
655
|
+
*/
|
577
656
|
static VALUE
|
578
657
|
inline_array_each(VALUE self)
|
579
658
|
{
|
@@ -590,6 +669,11 @@ inline_array_each(VALUE self)
|
|
590
669
|
return self;
|
591
670
|
}
|
592
671
|
|
672
|
+
/*
|
673
|
+
* call-seq: to_a
|
674
|
+
* @return [Array]
|
675
|
+
* Convert +self+ to an array.
|
676
|
+
*/
|
593
677
|
static VALUE
|
594
678
|
inline_array_to_a(VALUE self)
|
595
679
|
{
|
@@ -608,6 +692,12 @@ inline_array_to_a(VALUE self)
|
|
608
692
|
return obj;
|
609
693
|
}
|
610
694
|
|
695
|
+
/*
|
696
|
+
* Document-method: FFI::StructLayout::CharArray#to_s
|
697
|
+
* call-seq: to_s
|
698
|
+
* @return [String]
|
699
|
+
* Convert +self+ to a string.
|
700
|
+
*/
|
611
701
|
static VALUE
|
612
702
|
inline_array_to_s(VALUE self)
|
613
703
|
{
|
@@ -627,7 +717,11 @@ inline_array_to_s(VALUE self)
|
|
627
717
|
return rb_funcall2(array->rbMemory, rb_intern("get_string"), 2, argv);
|
628
718
|
}
|
629
719
|
|
630
|
-
|
720
|
+
/*
|
721
|
+
* call-seq: to_ptr
|
722
|
+
* @return [AbstractMemory]
|
723
|
+
* Get pointer to +self+ content.
|
724
|
+
*/
|
631
725
|
static VALUE
|
632
726
|
inline_array_to_ptr(VALUE self)
|
633
727
|
{
|
@@ -647,14 +741,37 @@ rbffi_Struct_Init(VALUE moduleFFI)
|
|
647
741
|
|
648
742
|
rbffi_StructLayout_Init(moduleFFI);
|
649
743
|
|
650
|
-
|
744
|
+
/*
|
745
|
+
* Document-class: FFI::Struct
|
746
|
+
*
|
747
|
+
* A FFI::Struct means to mirror a C struct.
|
748
|
+
*
|
749
|
+
* A Struct is defined as:
|
750
|
+
* class MyStruct < FFI::Struct
|
751
|
+
* layout :value1, :int,
|
752
|
+
* :value2, :double
|
753
|
+
* end
|
754
|
+
* and is used as:
|
755
|
+
* my_struct = MyStruct.new
|
756
|
+
* my_struct[:value1] = 12
|
757
|
+
*
|
758
|
+
* For more information, see http://github.com/ffi/ffi/wiki/Structs
|
759
|
+
*/
|
760
|
+
rbffi_StructClass = rb_define_class_under(moduleFFI, "Struct", rb_cObject);
|
761
|
+
StructClass = rbffi_StructClass; // put on a line alone to help RDoc
|
651
762
|
rb_global_variable(&rbffi_StructClass);
|
652
763
|
|
764
|
+
/*
|
765
|
+
* Document-class: FFI::Struct::InlineArray
|
766
|
+
*/
|
653
767
|
rbffi_StructInlineArrayClass = rb_define_class_under(rbffi_StructClass, "InlineArray", rb_cObject);
|
654
768
|
rb_global_variable(&rbffi_StructInlineArrayClass);
|
655
769
|
|
656
|
-
|
657
|
-
|
770
|
+
/*
|
771
|
+
* Document-class: FFI::StructLayout::CharArray < FFI::Struct::InlineArray
|
772
|
+
*/
|
773
|
+
rbffi_StructLayoutCharArrayClass = rb_define_class_under(rbffi_StructLayoutClass, "CharArray",
|
774
|
+
rbffi_StructInlineArrayClass);
|
658
775
|
rb_global_variable(&rbffi_StructLayoutCharArrayClass);
|
659
776
|
|
660
777
|
|