ffi 0.4.0 → 0.5.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.rdoc +15 -15
- data/Rakefile +57 -8
- data/ext/ffi_c/AbstractMemory.c +101 -24
- data/ext/ffi_c/AbstractMemory.h +98 -6
- data/ext/ffi_c/ArrayType.c +129 -0
- data/ext/ffi_c/ArrayType.h +58 -0
- data/ext/ffi_c/AutoPointer.c +1 -0
- data/ext/ffi_c/Buffer.c +59 -43
- data/ext/ffi_c/Call.c +853 -0
- data/ext/ffi_c/Call.h +86 -0
- data/ext/ffi_c/ClosurePool.c +302 -0
- data/ext/ffi_c/ClosurePool.h +29 -0
- data/ext/ffi_c/DynamicLibrary.c +3 -0
- data/ext/ffi_c/Function.c +478 -0
- data/ext/ffi_c/Function.h +80 -0
- data/ext/ffi_c/FunctionInfo.c +221 -0
- data/ext/ffi_c/LastError.c +30 -6
- data/ext/ffi_c/MemoryPointer.c +50 -28
- data/ext/ffi_c/MethodHandle.c +346 -0
- data/ext/ffi_c/MethodHandle.h +53 -0
- data/ext/ffi_c/Pointer.c +73 -13
- data/ext/ffi_c/Pointer.h +31 -7
- data/ext/ffi_c/Struct.c +517 -224
- data/ext/ffi_c/Struct.h +60 -6
- data/ext/ffi_c/StructByValue.c +140 -0
- data/ext/ffi_c/StructByValue.h +53 -0
- data/ext/ffi_c/StructLayout.c +450 -0
- data/ext/ffi_c/Type.c +121 -22
- data/ext/ffi_c/Type.h +37 -8
- data/ext/ffi_c/Types.c +46 -61
- data/ext/ffi_c/Types.h +38 -7
- data/ext/ffi_c/Variadic.c +260 -0
- data/ext/ffi_c/compat.h +53 -3
- data/ext/ffi_c/extconf.rb +6 -7
- data/ext/ffi_c/ffi.c +45 -39
- data/ext/ffi_c/libffi.darwin.mk +2 -2
- data/ext/ffi_c/rbffi.h +3 -0
- data/lib/ffi/ffi.rb +7 -4
- data/lib/ffi/library.rb +34 -59
- data/lib/ffi/platform.rb +14 -4
- data/lib/ffi/struct.rb +110 -281
- data/lib/ffi/union.rb +4 -9
- data/lib/ffi/variadic.rb +1 -6
- data/spec/ffi/buffer_spec.rb +6 -0
- data/spec/ffi/callback_spec.rb +34 -3
- data/spec/ffi/function_spec.rb +73 -0
- data/spec/ffi/library_spec.rb +56 -52
- data/spec/ffi/pointer_spec.rb +3 -3
- data/spec/ffi/struct_callback_spec.rb +26 -3
- data/spec/ffi/struct_spec.rb +56 -3
- metadata +42 -11
- data/ext/ffi_c/Callback.c +0 -374
- data/ext/ffi_c/Callback.h +0 -47
- data/ext/ffi_c/Invoker.c +0 -962
- data/ext/ffi_c/NullPointer.c +0 -143
data/ext/ffi_c/Struct.h
CHANGED
@@ -1,26 +1,80 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
/*
|
2
|
+
* Copyright (c) 2008, 2009, Wayne Meissner
|
3
|
+
* Copyright (c) 2009, Luc Heinrich <luc@honk-honk.com>
|
4
|
+
*
|
5
|
+
* All rights reserved.
|
6
|
+
*
|
7
|
+
* Redistribution and use in source and binary forms, with or without
|
8
|
+
* modification, are permitted provided that the following conditions are met:
|
9
|
+
*
|
10
|
+
* * Redistributions of source code must retain the above copyright notice, this
|
11
|
+
* list of conditions and the following disclaimer.
|
12
|
+
* * Redistributions in binary form must reproduce the above copyright notice
|
13
|
+
* this list of conditions and the following disclaimer in the documentation
|
14
|
+
* and/or other materials provided with the distribution.
|
15
|
+
* * The name of the author or authors may not be used to endorse or promote
|
16
|
+
* products derived from this software without specific prior written permission.
|
17
|
+
*
|
18
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
19
|
+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
20
|
+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
21
|
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
22
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
23
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
24
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
25
|
+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
26
|
+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
27
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
28
|
+
*/
|
29
|
+
|
30
|
+
#ifndef RBFFI_STRUCT_H
|
31
|
+
#define RBFFI_STRUCT_H
|
3
32
|
|
4
33
|
#include "AbstractMemory.h"
|
34
|
+
#include "Type.h"
|
5
35
|
|
6
36
|
#ifdef __cplusplus
|
7
37
|
extern "C" {
|
8
38
|
#endif
|
9
39
|
|
10
40
|
extern void rbffi_Struct_Init(VALUE ffiModule);
|
41
|
+
extern void rbffi_StructLayout_Init(VALUE ffiModule);
|
42
|
+
|
43
|
+
typedef struct StructField_ {
|
44
|
+
Type* type;
|
45
|
+
unsigned int offset;
|
46
|
+
|
47
|
+
VALUE rbType;
|
48
|
+
VALUE rbName;
|
49
|
+
} StructField;
|
50
|
+
|
51
|
+
typedef struct StructLayout_ {
|
52
|
+
Type base;
|
53
|
+
StructField** fields;
|
54
|
+
unsigned int fieldCount;
|
55
|
+
int size;
|
56
|
+
int align;
|
57
|
+
ffi_type** ffiTypes;
|
58
|
+
VALUE rbFieldNames;
|
59
|
+
VALUE rbFieldMap;
|
60
|
+
VALUE rbFields;
|
61
|
+
} StructLayout;
|
11
62
|
|
12
|
-
struct StructLayout;
|
13
63
|
typedef struct Struct {
|
14
|
-
|
64
|
+
StructLayout* layout;
|
15
65
|
AbstractMemory* pointer;
|
16
66
|
VALUE rbLayout;
|
17
67
|
VALUE rbPointer;
|
18
68
|
} Struct;
|
19
69
|
|
20
|
-
extern VALUE rbffi_StructClass;
|
70
|
+
extern VALUE rbffi_StructClass, rbffi_StructLayoutClass;
|
71
|
+
extern VALUE rbffi_StructLayoutFieldClass, rbffi_StructLayoutFunctionFieldClass;
|
72
|
+
extern VALUE rbffi_StructLayoutArrayFieldClass, rbffi_StructLayoutStructFieldClass;
|
73
|
+
extern VALUE rbffi_StructInlineArrayClass;
|
74
|
+
|
21
75
|
#ifdef __cplusplus
|
22
76
|
}
|
23
77
|
#endif
|
24
78
|
|
25
|
-
#endif /*
|
79
|
+
#endif /* RBFFI_STRUCT_H */
|
26
80
|
|
@@ -0,0 +1,140 @@
|
|
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
|
+
#include <sys/param.h>
|
29
|
+
#include <sys/types.h>
|
30
|
+
#include <stdio.h>
|
31
|
+
#include <stdint.h>
|
32
|
+
#include <stdbool.h>
|
33
|
+
#include <errno.h>
|
34
|
+
#include <ruby.h>
|
35
|
+
|
36
|
+
#include <ffi.h>
|
37
|
+
#include "rbffi.h"
|
38
|
+
#include "compat.h"
|
39
|
+
|
40
|
+
#include "Type.h"
|
41
|
+
#include "StructByValue.h"
|
42
|
+
#include "Struct.h"
|
43
|
+
|
44
|
+
#define FFI_ALIGN(v, a) (((((size_t) (v))-1) | ((a)-1))+1)
|
45
|
+
|
46
|
+
static VALUE sbv_allocate(VALUE);
|
47
|
+
static VALUE sbv_initialize(VALUE, VALUE);
|
48
|
+
static void sbv_mark(StructByValue *);
|
49
|
+
static void sbv_free(StructByValue *);
|
50
|
+
|
51
|
+
VALUE rbffi_StructByValueClass = Qnil;
|
52
|
+
|
53
|
+
static VALUE
|
54
|
+
sbv_allocate(VALUE klass)
|
55
|
+
{
|
56
|
+
StructByValue* sbv;
|
57
|
+
|
58
|
+
VALUE obj = Data_Make_Struct(klass, StructByValue, sbv_mark, sbv_free, sbv);
|
59
|
+
|
60
|
+
sbv->rbStructClass = Qnil;
|
61
|
+
sbv->rbStructLayout = Qnil;
|
62
|
+
sbv->base.nativeType = NATIVE_STRUCT;
|
63
|
+
|
64
|
+
sbv->base.ffiType = xcalloc(1, sizeof(*sbv->base.ffiType));
|
65
|
+
sbv->base.ffiType->size = 0;
|
66
|
+
sbv->base.ffiType->alignment = 1;
|
67
|
+
sbv->base.ffiType->type = FFI_TYPE_STRUCT;
|
68
|
+
|
69
|
+
return obj;
|
70
|
+
}
|
71
|
+
|
72
|
+
static VALUE
|
73
|
+
sbv_initialize(VALUE self, VALUE rbStructClass)
|
74
|
+
{
|
75
|
+
StructByValue* sbv = NULL;
|
76
|
+
StructLayout* layout = NULL;
|
77
|
+
VALUE rbLayout = Qnil;
|
78
|
+
|
79
|
+
rbLayout = rb_cvar_get(rbStructClass, rb_intern("@layout"));
|
80
|
+
if (!rb_obj_is_instance_of(rbLayout, rbffi_StructLayoutClass)) {
|
81
|
+
rb_raise(rb_eTypeError, "wrong type in @layout cvar (expected FFI::StructLayout)");
|
82
|
+
}
|
83
|
+
|
84
|
+
Data_Get_Struct(rbLayout, StructLayout, layout);
|
85
|
+
Data_Get_Struct(self, StructByValue, sbv);
|
86
|
+
sbv->rbStructClass = rbStructClass;
|
87
|
+
sbv->rbStructLayout = rbLayout;
|
88
|
+
|
89
|
+
// We can just use everything from the ffi_type directly
|
90
|
+
*sbv->base.ffiType = *layout->base.ffiType;
|
91
|
+
|
92
|
+
return self;
|
93
|
+
}
|
94
|
+
|
95
|
+
static void
|
96
|
+
sbv_mark(StructByValue *sbv)
|
97
|
+
{
|
98
|
+
rb_gc_mark(sbv->rbStructClass);
|
99
|
+
rb_gc_mark(sbv->rbStructLayout);
|
100
|
+
}
|
101
|
+
|
102
|
+
static void
|
103
|
+
sbv_free(StructByValue *sbv)
|
104
|
+
{
|
105
|
+
xfree(sbv->base.ffiType);
|
106
|
+
xfree(sbv);
|
107
|
+
}
|
108
|
+
|
109
|
+
|
110
|
+
static VALUE
|
111
|
+
sbv_layout(VALUE self)
|
112
|
+
{
|
113
|
+
StructByValue* sbv;
|
114
|
+
|
115
|
+
Data_Get_Struct(self, StructByValue, sbv);
|
116
|
+
return sbv->rbStructLayout;
|
117
|
+
}
|
118
|
+
|
119
|
+
static VALUE
|
120
|
+
sbv_struct_class(VALUE self)
|
121
|
+
{
|
122
|
+
StructByValue* sbv;
|
123
|
+
|
124
|
+
Data_Get_Struct(self, StructByValue, sbv);
|
125
|
+
|
126
|
+
return sbv->rbStructClass;
|
127
|
+
}
|
128
|
+
|
129
|
+
void
|
130
|
+
rbffi_StructByValue_Init(VALUE moduleFFI)
|
131
|
+
{
|
132
|
+
rbffi_StructByValueClass = rb_define_class_under(moduleFFI, "StructByValue", rbffi_TypeClass);
|
133
|
+
rb_global_variable(&rbffi_StructByValueClass);
|
134
|
+
rb_define_const(rbffi_TypeClass, "Struct", rbffi_StructByValueClass);
|
135
|
+
|
136
|
+
rb_define_alloc_func(rbffi_StructByValueClass, sbv_allocate);
|
137
|
+
rb_define_method(rbffi_StructByValueClass, "initialize", sbv_initialize, 1);
|
138
|
+
rb_define_method(rbffi_StructByValueClass, "layout", sbv_layout, 0);
|
139
|
+
rb_define_method(rbffi_StructByValueClass, "struct_class", sbv_struct_class, 0);
|
140
|
+
}
|
@@ -0,0 +1,53 @@
|
|
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_STRUCTBYVALUE_H
|
29
|
+
#define RBFFI_STRUCTBYVALUE_H
|
30
|
+
|
31
|
+
#include <ruby.h>
|
32
|
+
#include "Type.h"
|
33
|
+
|
34
|
+
#ifdef __cplusplus
|
35
|
+
extern "C" {
|
36
|
+
#endif
|
37
|
+
|
38
|
+
typedef struct StructByValue_ {
|
39
|
+
Type base;
|
40
|
+
VALUE rbStructClass;
|
41
|
+
VALUE rbStructLayout;
|
42
|
+
} StructByValue;
|
43
|
+
|
44
|
+
void rbffi_StructByValue_Init(VALUE moduleFFI);
|
45
|
+
|
46
|
+
extern VALUE rbffi_StructByValueClass;
|
47
|
+
|
48
|
+
#ifdef __cplusplus
|
49
|
+
}
|
50
|
+
#endif
|
51
|
+
|
52
|
+
#endif /* RBFFI_STRUCTBYVALUE_H */
|
53
|
+
|
@@ -0,0 +1,450 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright (c) 2008, 2009, Wayne Meissner
|
3
|
+
* Copyright (c) 2009, Luc Heinrich <luc@honk-honk.com>
|
4
|
+
*
|
5
|
+
* All rights reserved.
|
6
|
+
*
|
7
|
+
* Redistribution and use in source and binary forms, with or without
|
8
|
+
* modification, are permitted provided that the following conditions are met:
|
9
|
+
*
|
10
|
+
* * Redistributions of source code must retain the above copyright notice, this
|
11
|
+
* list of conditions and the following disclaimer.
|
12
|
+
* * Redistributions in binary form must reproduce the above copyright notice
|
13
|
+
* this list of conditions and the following disclaimer in the documentation
|
14
|
+
* and/or other materials provided with the distribution.
|
15
|
+
* * The name of the author or authors may not be used to endorse or promote
|
16
|
+
* products derived from this software without specific prior written permission.
|
17
|
+
*
|
18
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
19
|
+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
20
|
+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
21
|
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
22
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
23
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
24
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
25
|
+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
26
|
+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
27
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
28
|
+
*/
|
29
|
+
|
30
|
+
#include <sys/types.h>
|
31
|
+
|
32
|
+
#include "Function.h"
|
33
|
+
#include <sys/param.h>
|
34
|
+
#include <stdint.h>
|
35
|
+
#include <stdbool.h>
|
36
|
+
#include <ruby.h>
|
37
|
+
#include "rbffi.h"
|
38
|
+
#include "compat.h"
|
39
|
+
#include "AbstractMemory.h"
|
40
|
+
#include "Pointer.h"
|
41
|
+
#include "MemoryPointer.h"
|
42
|
+
#include "Function.h"
|
43
|
+
#include "Types.h"
|
44
|
+
#include "Struct.h"
|
45
|
+
#include "StructByValue.h"
|
46
|
+
#include "ArrayType.h"
|
47
|
+
|
48
|
+
#define FFI_ALIGN(v, a) (((((size_t) (v))-1) | ((a)-1))+1)
|
49
|
+
|
50
|
+
static void struct_layout_mark(StructLayout *);
|
51
|
+
static void struct_layout_free(StructLayout *);
|
52
|
+
static void struct_field_mark(StructField* );
|
53
|
+
|
54
|
+
VALUE rbffi_StructLayoutFieldClass = Qnil;
|
55
|
+
VALUE rbffi_StructLayoutFunctionFieldClass = Qnil, rbffi_StructLayoutArrayFieldClass = Qnil;
|
56
|
+
VALUE rbffi_StructLayoutStructFieldClass = Qnil;
|
57
|
+
|
58
|
+
VALUE rbffi_StructLayoutClass = Qnil;
|
59
|
+
|
60
|
+
|
61
|
+
static VALUE
|
62
|
+
struct_field_allocate(VALUE klass)
|
63
|
+
{
|
64
|
+
StructField* field;
|
65
|
+
VALUE obj;
|
66
|
+
|
67
|
+
obj = Data_Make_Struct(klass, StructField, struct_field_mark, -1, field);
|
68
|
+
field->rbType = Qnil;
|
69
|
+
field->rbName = Qnil;
|
70
|
+
|
71
|
+
return obj;
|
72
|
+
}
|
73
|
+
|
74
|
+
static void
|
75
|
+
struct_field_mark(StructField* f)
|
76
|
+
{
|
77
|
+
rb_gc_mark(f->rbType);
|
78
|
+
rb_gc_mark(f->rbName);
|
79
|
+
}
|
80
|
+
|
81
|
+
static VALUE
|
82
|
+
struct_field_initialize(int argc, VALUE* argv, VALUE self)
|
83
|
+
{
|
84
|
+
VALUE rbOffset = Qnil, rbName = Qnil, rbType = Qnil;
|
85
|
+
StructField* field;
|
86
|
+
int nargs;
|
87
|
+
|
88
|
+
Data_Get_Struct(self, StructField, field);
|
89
|
+
|
90
|
+
nargs = rb_scan_args(argc, argv, "3", &rbName, &rbOffset, &rbType);
|
91
|
+
|
92
|
+
if (TYPE(rbName) != T_SYMBOL && TYPE(rbName) != T_STRING) {
|
93
|
+
rb_raise(rb_eTypeError, "wrong argument type %s (expected Symbol/String)",
|
94
|
+
rb_obj_classname(rbName));
|
95
|
+
}
|
96
|
+
|
97
|
+
Check_Type(rbOffset, T_FIXNUM);
|
98
|
+
|
99
|
+
if (!rb_obj_is_kind_of(rbType, rbffi_TypeClass)) {
|
100
|
+
rb_raise(rb_eTypeError, "wrong argument type %s (expected FFI::Type)",
|
101
|
+
rb_obj_classname(rbType));
|
102
|
+
}
|
103
|
+
|
104
|
+
field->offset = NUM2UINT(rbOffset);
|
105
|
+
field->rbName = (TYPE(rbName) == T_SYMBOL) ? rbName : rb_str_intern(rbName);
|
106
|
+
field->rbType = rbType;
|
107
|
+
Data_Get_Struct(field->rbType, Type, field->type);
|
108
|
+
|
109
|
+
return self;
|
110
|
+
}
|
111
|
+
|
112
|
+
static VALUE
|
113
|
+
struct_field_offset(VALUE self)
|
114
|
+
{
|
115
|
+
StructField* field;
|
116
|
+
Data_Get_Struct(self, StructField, field);
|
117
|
+
return UINT2NUM(field->offset);
|
118
|
+
}
|
119
|
+
|
120
|
+
static VALUE
|
121
|
+
struct_field_size(VALUE self)
|
122
|
+
{
|
123
|
+
StructField* field;
|
124
|
+
Data_Get_Struct(self, StructField, field);
|
125
|
+
return UINT2NUM(field->type->ffiType->size);
|
126
|
+
}
|
127
|
+
|
128
|
+
static VALUE
|
129
|
+
struct_field_alignment(VALUE self)
|
130
|
+
{
|
131
|
+
StructField* field;
|
132
|
+
Data_Get_Struct(self, StructField, field);
|
133
|
+
return UINT2NUM(field->type->ffiType->alignment);
|
134
|
+
}
|
135
|
+
|
136
|
+
static VALUE
|
137
|
+
struct_field_ffi_type(VALUE self)
|
138
|
+
{
|
139
|
+
StructField* field;
|
140
|
+
Data_Get_Struct(self, StructField, field);
|
141
|
+
return field->rbType;
|
142
|
+
}
|
143
|
+
|
144
|
+
static VALUE
|
145
|
+
struct_field_name(VALUE self)
|
146
|
+
{
|
147
|
+
StructField* field;
|
148
|
+
Data_Get_Struct(self, StructField, field);
|
149
|
+
return field->rbName;
|
150
|
+
}
|
151
|
+
|
152
|
+
static VALUE
|
153
|
+
struct_field_get(VALUE self, VALUE pointer)
|
154
|
+
{
|
155
|
+
StructField* f;
|
156
|
+
MemoryOp* op;
|
157
|
+
AbstractMemory* memory = MEMORY(pointer);
|
158
|
+
|
159
|
+
Data_Get_Struct(self, StructField, f);
|
160
|
+
op = memory_get_op(memory, f->type);
|
161
|
+
if (op == NULL) {
|
162
|
+
rb_raise(rb_eArgError, "get not supported for %s", rb_obj_classname(self));
|
163
|
+
return Qnil;
|
164
|
+
}
|
165
|
+
|
166
|
+
return (*op->get)(memory, f->offset);
|
167
|
+
}
|
168
|
+
|
169
|
+
static VALUE
|
170
|
+
struct_field_put(VALUE self, VALUE pointer, VALUE value)
|
171
|
+
{
|
172
|
+
StructField* f;
|
173
|
+
MemoryOp* op;
|
174
|
+
AbstractMemory* memory = MEMORY(pointer);
|
175
|
+
|
176
|
+
Data_Get_Struct(self, StructField, f);
|
177
|
+
op = memory_get_op(memory, f->type);
|
178
|
+
if (op == NULL) {
|
179
|
+
rb_raise(rb_eArgError, "put not supported for %s", rb_obj_classname(self));
|
180
|
+
return self;
|
181
|
+
}
|
182
|
+
|
183
|
+
(*op->put)(memory, f->offset, value);
|
184
|
+
|
185
|
+
return self;
|
186
|
+
}
|
187
|
+
|
188
|
+
static VALUE
|
189
|
+
function_field_get(VALUE self, VALUE pointer)
|
190
|
+
{
|
191
|
+
StructField* f;
|
192
|
+
MemoryOp* op;
|
193
|
+
AbstractMemory* memory = MEMORY(pointer);
|
194
|
+
|
195
|
+
Data_Get_Struct(self, StructField, f);
|
196
|
+
op = memory->ops->pointer;
|
197
|
+
if (op == NULL) {
|
198
|
+
rb_raise(rb_eArgError, "get not supported for %s", rb_obj_classname(self));
|
199
|
+
return Qnil;
|
200
|
+
}
|
201
|
+
|
202
|
+
return rbffi_Function_NewInstance(f->rbType, (*op->get)(memory, f->offset));
|
203
|
+
}
|
204
|
+
|
205
|
+
static VALUE
|
206
|
+
function_field_put(VALUE self, VALUE pointer, VALUE proc)
|
207
|
+
{
|
208
|
+
StructField* f;
|
209
|
+
MemoryOp* op;
|
210
|
+
AbstractMemory* memory = MEMORY(pointer);
|
211
|
+
VALUE value = Qnil;
|
212
|
+
|
213
|
+
Data_Get_Struct(self, StructField, f);
|
214
|
+
op = memory->ops->pointer;
|
215
|
+
if (op == NULL) {
|
216
|
+
rb_raise(rb_eArgError, "put not supported for %s", rb_obj_classname(self));
|
217
|
+
return self;
|
218
|
+
}
|
219
|
+
|
220
|
+
if (NIL_P(proc) || rb_obj_is_kind_of(proc, rbffi_FunctionClass)) {
|
221
|
+
value = proc;
|
222
|
+
} else if (rb_obj_is_kind_of(proc, rb_cProc) || rb_respond_to(proc, rb_intern("call"))) {
|
223
|
+
value = rbffi_Function_ForProc(f->rbType, proc);
|
224
|
+
} else {
|
225
|
+
rb_raise(rb_eTypeError, "wrong type (expected Proc or Function)");
|
226
|
+
}
|
227
|
+
|
228
|
+
(*op->put)(memory, f->offset, value);
|
229
|
+
|
230
|
+
return self;
|
231
|
+
}
|
232
|
+
|
233
|
+
static VALUE
|
234
|
+
array_field_get(VALUE self, VALUE pointer)
|
235
|
+
{
|
236
|
+
StructField* f;
|
237
|
+
ArrayType* array;
|
238
|
+
MemoryOp* op;
|
239
|
+
AbstractMemory* memory = MEMORY(pointer);
|
240
|
+
VALUE argv[2];
|
241
|
+
|
242
|
+
Data_Get_Struct(self, StructField, f);
|
243
|
+
Data_Get_Struct(f->rbType, ArrayType, array);
|
244
|
+
|
245
|
+
op = memory_get_op(memory, array->componentType);
|
246
|
+
if (op == NULL) {
|
247
|
+
rb_raise(rb_eArgError, "get not supported for %s", rb_obj_classname(array->rbComponentType));
|
248
|
+
return Qnil;
|
249
|
+
}
|
250
|
+
|
251
|
+
argv[0] = pointer;
|
252
|
+
argv[1] = self;
|
253
|
+
|
254
|
+
return rb_class_new_instance(2, argv, rbffi_StructInlineArrayClass);
|
255
|
+
}
|
256
|
+
|
257
|
+
static VALUE
|
258
|
+
inline_struct_field_get(VALUE self, VALUE pointer)
|
259
|
+
{
|
260
|
+
StructField* f;
|
261
|
+
StructByValue* sbv;
|
262
|
+
VALUE rbPointer = Qnil, rbOffset = Qnil;
|
263
|
+
|
264
|
+
Data_Get_Struct(self, StructField, f);
|
265
|
+
Data_Get_Struct(f->rbType, StructByValue, sbv);
|
266
|
+
|
267
|
+
rbOffset = UINT2NUM(f->offset);
|
268
|
+
rbPointer = rb_funcall2(pointer, rb_intern("+"), 1, &rbOffset);
|
269
|
+
|
270
|
+
return rb_class_new_instance(1, &rbPointer, sbv->rbStructClass);
|
271
|
+
}
|
272
|
+
|
273
|
+
static VALUE
|
274
|
+
struct_layout_allocate(VALUE klass)
|
275
|
+
{
|
276
|
+
StructLayout* layout;
|
277
|
+
VALUE obj;
|
278
|
+
|
279
|
+
obj = Data_Make_Struct(klass, StructLayout, struct_layout_mark, struct_layout_free, layout);
|
280
|
+
layout->rbFieldMap = Qnil;
|
281
|
+
layout->rbFieldNames = Qnil;
|
282
|
+
layout->rbFields = Qnil;
|
283
|
+
layout->base.ffiType = xcalloc(1, sizeof(*layout->base.ffiType));
|
284
|
+
layout->base.ffiType->size = 0;
|
285
|
+
layout->base.ffiType->alignment = 0;
|
286
|
+
layout->base.ffiType->type = FFI_TYPE_STRUCT;
|
287
|
+
|
288
|
+
return obj;
|
289
|
+
}
|
290
|
+
|
291
|
+
static VALUE
|
292
|
+
struct_layout_initialize(VALUE self, VALUE field_names, VALUE fields, VALUE size, VALUE align)
|
293
|
+
{
|
294
|
+
StructLayout* layout;
|
295
|
+
ffi_type* ltype;
|
296
|
+
int i;
|
297
|
+
|
298
|
+
Data_Get_Struct(self, StructLayout, layout);
|
299
|
+
layout->rbFieldMap = rb_hash_new();
|
300
|
+
layout->rbFieldNames = rb_ary_dup(field_names);
|
301
|
+
layout->size = NUM2INT(size);
|
302
|
+
layout->align = NUM2INT(align);
|
303
|
+
layout->fieldCount = RARRAY_LEN(field_names);
|
304
|
+
layout->fields = xcalloc(layout->fieldCount, sizeof(StructField *));
|
305
|
+
layout->ffiTypes = xcalloc(layout->fieldCount + 1, sizeof(ffi_type *));
|
306
|
+
layout->rbFields = rb_ary_new2(layout->fieldCount);
|
307
|
+
layout->base.ffiType->elements = layout->ffiTypes;
|
308
|
+
layout->base.ffiType->size = 0;
|
309
|
+
layout->base.ffiType->alignment = 1;
|
310
|
+
|
311
|
+
ltype = layout->base.ffiType;
|
312
|
+
for (i = 0; i < layout->fieldCount; ++i) {
|
313
|
+
VALUE rbName = rb_ary_entry(field_names, i);
|
314
|
+
VALUE rbField = rb_hash_aref(fields, rbName);
|
315
|
+
StructField* field;
|
316
|
+
ffi_type* ftype;
|
317
|
+
|
318
|
+
|
319
|
+
if (!rb_obj_is_kind_of(rbField, rbffi_StructLayoutFieldClass)) {
|
320
|
+
rb_raise(rb_eTypeError, "wrong type for field %d.", i);
|
321
|
+
}
|
322
|
+
|
323
|
+
Data_Get_Struct(rbField, StructField, field = layout->fields[i]);
|
324
|
+
|
325
|
+
if (field->type == NULL || field->type->ffiType == NULL) {
|
326
|
+
rb_raise(rb_eRuntimeError, "type of field %d not supported", i);
|
327
|
+
}
|
328
|
+
|
329
|
+
ftype = field->type->ffiType;
|
330
|
+
if (ftype->size == 0) {
|
331
|
+
rb_raise(rb_eTypeError, "type of field %d has zero size", i);
|
332
|
+
}
|
333
|
+
|
334
|
+
rb_hash_aset(layout->rbFieldMap, rbName, rbField);
|
335
|
+
layout->ffiTypes[i] = ftype;
|
336
|
+
rb_ary_push(layout->rbFields, rbField);
|
337
|
+
ltype->size = MAX(ltype->size, field->offset + ftype->size);
|
338
|
+
ltype->alignment = MAX(ltype->alignment, ftype->alignment);
|
339
|
+
}
|
340
|
+
|
341
|
+
if (ltype->size == 0) {
|
342
|
+
rb_raise(rb_eRuntimeError, "Struct size is zero");
|
343
|
+
}
|
344
|
+
|
345
|
+
// Include tail padding
|
346
|
+
ltype->size = FFI_ALIGN(ltype->size, ltype->alignment);
|
347
|
+
|
348
|
+
return self;
|
349
|
+
}
|
350
|
+
|
351
|
+
static VALUE
|
352
|
+
struct_layout_aref(VALUE self, VALUE field)
|
353
|
+
{
|
354
|
+
StructLayout* layout;
|
355
|
+
|
356
|
+
Data_Get_Struct(self, StructLayout, layout);
|
357
|
+
|
358
|
+
return rb_hash_aref(layout->rbFieldMap, field);
|
359
|
+
}
|
360
|
+
|
361
|
+
static VALUE
|
362
|
+
struct_layout_fields(VALUE self)
|
363
|
+
{
|
364
|
+
StructLayout* layout;
|
365
|
+
|
366
|
+
Data_Get_Struct(self, StructLayout, layout);
|
367
|
+
|
368
|
+
return rb_ary_dup(layout->rbFields);
|
369
|
+
}
|
370
|
+
|
371
|
+
static VALUE
|
372
|
+
struct_layout_members(VALUE self)
|
373
|
+
{
|
374
|
+
StructLayout* layout;
|
375
|
+
|
376
|
+
Data_Get_Struct(self, StructLayout, layout);
|
377
|
+
|
378
|
+
return rb_ary_dup(layout->rbFieldNames);
|
379
|
+
}
|
380
|
+
|
381
|
+
static VALUE
|
382
|
+
struct_layout_to_a(VALUE self)
|
383
|
+
{
|
384
|
+
StructLayout* layout;
|
385
|
+
|
386
|
+
Data_Get_Struct(self, StructLayout, layout);
|
387
|
+
|
388
|
+
return rb_ary_dup(layout->rbFields);
|
389
|
+
}
|
390
|
+
|
391
|
+
static void
|
392
|
+
struct_layout_mark(StructLayout *layout)
|
393
|
+
{
|
394
|
+
rb_gc_mark(layout->rbFieldMap);
|
395
|
+
rb_gc_mark(layout->rbFieldNames);
|
396
|
+
rb_gc_mark(layout->rbFields);
|
397
|
+
}
|
398
|
+
|
399
|
+
static void
|
400
|
+
struct_layout_free(StructLayout *layout)
|
401
|
+
{
|
402
|
+
xfree(layout->ffiTypes);
|
403
|
+
xfree(layout->base.ffiType);
|
404
|
+
xfree(layout->fields);
|
405
|
+
xfree(layout);
|
406
|
+
}
|
407
|
+
|
408
|
+
void
|
409
|
+
rbffi_StructLayout_Init(VALUE moduleFFI)
|
410
|
+
{
|
411
|
+
rbffi_StructLayoutClass = rb_define_class_under(moduleFFI, "StructLayout", rbffi_TypeClass);
|
412
|
+
rb_global_variable(&rbffi_StructLayoutClass);
|
413
|
+
|
414
|
+
rbffi_StructLayoutFieldClass = rb_define_class_under(rbffi_StructLayoutClass, "Field", rb_cObject);
|
415
|
+
rb_global_variable(&rbffi_StructLayoutFieldClass);
|
416
|
+
|
417
|
+
rbffi_StructLayoutFunctionFieldClass = rb_define_class_under(rbffi_StructLayoutClass, "Function", rbffi_StructLayoutFieldClass);
|
418
|
+
rb_global_variable(&rbffi_StructLayoutFunctionFieldClass);
|
419
|
+
|
420
|
+
rbffi_StructLayoutStructFieldClass = rb_define_class_under(rbffi_StructLayoutClass, "StructByValue", rbffi_StructLayoutFieldClass);
|
421
|
+
rb_global_variable(&rbffi_StructLayoutStructFieldClass);
|
422
|
+
|
423
|
+
rbffi_StructLayoutArrayFieldClass = rb_define_class_under(rbffi_StructLayoutClass, "Array", rbffi_StructLayoutFieldClass);
|
424
|
+
rb_global_variable(&rbffi_StructLayoutArrayFieldClass);
|
425
|
+
|
426
|
+
rb_define_alloc_func(rbffi_StructLayoutFieldClass, struct_field_allocate);
|
427
|
+
rb_define_method(rbffi_StructLayoutFieldClass, "initialize", struct_field_initialize, -1);
|
428
|
+
rb_define_method(rbffi_StructLayoutFieldClass, "offset", struct_field_offset, 0);
|
429
|
+
rb_define_method(rbffi_StructLayoutFieldClass, "size", struct_field_size, 0);
|
430
|
+
rb_define_method(rbffi_StructLayoutFieldClass, "alignment", struct_field_alignment, 0);
|
431
|
+
rb_define_method(rbffi_StructLayoutFieldClass, "name", struct_field_name, 0);
|
432
|
+
rb_define_method(rbffi_StructLayoutFieldClass, "ffi_type", struct_field_ffi_type, 0);
|
433
|
+
rb_define_method(rbffi_StructLayoutFieldClass, "put", struct_field_put, 2);
|
434
|
+
rb_define_method(rbffi_StructLayoutFieldClass, "get", struct_field_get, 1);
|
435
|
+
|
436
|
+
rb_define_method(rbffi_StructLayoutFunctionFieldClass, "put", function_field_put, 2);
|
437
|
+
rb_define_method(rbffi_StructLayoutFunctionFieldClass, "get", function_field_get, 1);
|
438
|
+
|
439
|
+
rb_define_method(rbffi_StructLayoutArrayFieldClass, "get", array_field_get, 1);
|
440
|
+
rb_define_method(rbffi_StructLayoutStructFieldClass, "get", inline_struct_field_get, 1);
|
441
|
+
|
442
|
+
|
443
|
+
rb_define_alloc_func(rbffi_StructLayoutClass, struct_layout_allocate);
|
444
|
+
rb_define_method(rbffi_StructLayoutClass, "initialize", struct_layout_initialize, 4);
|
445
|
+
rb_define_method(rbffi_StructLayoutClass, "[]", struct_layout_aref, 1);
|
446
|
+
rb_define_method(rbffi_StructLayoutClass, "fields", struct_layout_fields, 0);
|
447
|
+
rb_define_method(rbffi_StructLayoutClass, "members", struct_layout_members, 0);
|
448
|
+
rb_define_method(rbffi_StructLayoutClass, "to_a", struct_layout_to_a, 0);
|
449
|
+
|
450
|
+
}
|