ffi 0.3.5 → 0.4.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 +51 -1
- data/Rakefile +34 -26
- data/ext/ffi_c/AbstractMemory.c +73 -70
- data/ext/ffi_c/AbstractMemory.h +8 -4
- data/ext/ffi_c/AutoPointer.c +8 -9
- data/ext/ffi_c/AutoPointer.h +2 -2
- data/ext/ffi_c/Buffer.c +19 -20
- data/ext/ffi_c/Callback.c +85 -33
- data/ext/ffi_c/Callback.h +11 -5
- data/ext/ffi_c/{NativeLibrary.c → DynamicLibrary.c} +83 -16
- data/ext/ffi_c/{NativeLibrary.h → DynamicLibrary.h} +1 -1
- data/ext/ffi_c/Invoker.c +148 -192
- data/ext/ffi_c/LastError.c +135 -0
- data/ext/ffi_c/LastError.h +18 -0
- data/ext/ffi_c/MemoryPointer.c +26 -19
- data/ext/ffi_c/MemoryPointer.h +3 -3
- data/ext/ffi_c/NullPointer.c +49 -47
- data/ext/ffi_c/Platform.c +9 -10
- data/ext/ffi_c/Platform.h +1 -1
- data/ext/ffi_c/Pointer.c +52 -21
- data/ext/ffi_c/Pointer.h +8 -6
- data/ext/ffi_c/Struct.c +70 -61
- data/ext/ffi_c/Struct.h +2 -2
- data/ext/ffi_c/Type.c +230 -0
- data/ext/ffi_c/Type.h +28 -0
- data/ext/ffi_c/Types.c +47 -6
- data/ext/ffi_c/Types.h +8 -2
- data/ext/ffi_c/endian.h +40 -0
- data/ext/ffi_c/extconf.rb +6 -5
- data/ext/ffi_c/ffi.c +20 -43
- data/ext/ffi_c/libffi.bsd.mk +34 -0
- data/ext/ffi_c/libffi.darwin.mk +30 -10
- data/ext/ffi_c/libffi.gnu.mk +29 -0
- data/ext/ffi_c/libffi.mk +4 -2
- data/ext/ffi_c/rbffi.h +6 -8
- data/lib/ffi.rb +10 -1
- data/lib/ffi/autopointer.rb +1 -1
- data/lib/ffi/enum.rb +78 -0
- data/lib/ffi/ffi.rb +5 -6
- data/lib/ffi/io.rb +15 -1
- data/lib/ffi/library.rb +78 -17
- data/lib/ffi/pointer.rb +2 -2
- data/lib/ffi/struct.rb +68 -14
- data/lib/ffi/types.rb +6 -3
- data/lib/ffi/variadic.rb +2 -2
- data/spec/ffi/bool_spec.rb +24 -0
- data/spec/ffi/callback_spec.rb +217 -17
- data/spec/ffi/enum_spec.rb +164 -0
- data/spec/ffi/managed_struct_spec.rb +6 -1
- data/spec/ffi/number_spec.rb +30 -0
- data/spec/ffi/pointer_spec.rb +33 -8
- data/spec/ffi/rbx/memory_pointer_spec.rb +0 -6
- data/spec/ffi/spec_helper.rb +5 -1
- data/spec/ffi/string_spec.rb +65 -4
- data/spec/ffi/struct_callback_spec.rb +41 -0
- data/spec/ffi/struct_initialize_spec.rb +30 -0
- data/spec/ffi/struct_spec.rb +19 -20
- metadata +29 -52
- data/ext/ffi_c/ffi.mk +0 -23
data/README.rdoc
CHANGED
@@ -4,16 +4,66 @@ ruby-ffi
|
|
4
4
|
|
5
5
|
== DESCRIPTION:
|
6
6
|
|
7
|
-
|
7
|
+
Ruby-FFI is a ruby extension for programmatically loading dynamic
|
8
|
+
libraries, binding functions within them, and calling those functions
|
9
|
+
from Ruby code. Moreover, a Ruby-FFI extension works without changes
|
10
|
+
on Ruby and JRuby. Discover why should you write your next extension
|
11
|
+
using Ruby-FFI {here}[http://kenai.com/projects/ruby-ffi/pages/WhyUseFFI].
|
8
12
|
|
9
13
|
== FEATURES/PROBLEMS:
|
10
14
|
|
15
|
+
* It has a very intuitive DSL
|
16
|
+
* It supports all C native types
|
17
|
+
* It supports C structs (also nested), enums and global variables
|
18
|
+
* It supports callbacks
|
19
|
+
* It has smart methods to handle memory management of pointers and structs
|
20
|
+
|
11
21
|
== SYNOPSIS:
|
12
22
|
|
23
|
+
require 'ffi'
|
24
|
+
|
25
|
+
module MyLib
|
26
|
+
extend FFI::Library
|
27
|
+
attach_function :puts, [ :string ], :int
|
28
|
+
end
|
29
|
+
|
30
|
+
MyLib.puts 'Hello boys using libc!'
|
31
|
+
|
32
|
+
For less minimalistic and more sane examples you may look at:
|
33
|
+
|
34
|
+
* the samples/ folder
|
35
|
+
* the examples on the Kenai {wiki}[http://kenai.com/projects/ruby-ffi/pages/Home]
|
36
|
+
* the projects using FFI listed on this {page}[http://kenai.com/projects/ruby-ffi/pages/ProjectsUsingFFI]
|
37
|
+
|
13
38
|
== REQUIREMENTS:
|
14
39
|
|
40
|
+
* You need a sane building environment in order to compile the extension.
|
41
|
+
|
15
42
|
== DOWNLOAD/INSTALL:
|
16
43
|
|
44
|
+
From rubyforge:
|
45
|
+
|
46
|
+
[sudo] gem install ffi
|
47
|
+
|
48
|
+
or from the mercurial repository on Kenai:
|
49
|
+
|
50
|
+
hg clone https://kenai.com/hg/ruby-ffi~mercurial ruby-ffi
|
51
|
+
cd ruby-ffi
|
52
|
+
rake gem:install
|
53
|
+
|
54
|
+
== CREDITS:
|
55
|
+
|
56
|
+
Special thanks to:
|
57
|
+
|
58
|
+
Yehuda Katz
|
59
|
+
Luc Heinrich
|
60
|
+
Andrea Fazzi
|
61
|
+
Mike Dalessio
|
62
|
+
Hongli Lai
|
63
|
+
Evan Phoenix
|
64
|
+
Aman Gupta
|
65
|
+
Beoran
|
66
|
+
|
17
67
|
== LICENSE:
|
18
68
|
|
19
69
|
See LICENSE file.
|
data/Rakefile
CHANGED
@@ -1,9 +1,11 @@
|
|
1
1
|
require 'rubygems'
|
2
|
+
require 'rbconfig'
|
2
3
|
|
3
|
-
USE_RAKE_COMPILER = (
|
4
|
+
USE_RAKE_COMPILER = (RUBY_PLATFORM =~ /java/) ? false : true
|
4
5
|
if USE_RAKE_COMPILER
|
5
|
-
gem 'rake-compiler', '>=0.
|
6
|
+
gem 'rake-compiler', '>=0.6.0'
|
6
7
|
require 'rake/extensiontask'
|
8
|
+
ENV['RUBY_CC_VERSION'] = '1.8.6:1.9.1'
|
7
9
|
end
|
8
10
|
|
9
11
|
require 'date'
|
@@ -24,20 +26,22 @@ end
|
|
24
26
|
LIBEXT = Config::CONFIG['host_os'].downcase =~ /darwin/ ? "dylib" : "so"
|
25
27
|
GMAKE = Config::CONFIG['host_os'].downcase =~ /bsd/ ? "gmake" : "make"
|
26
28
|
LIBTEST = "build/libtest.#{LIBEXT}"
|
27
|
-
BUILD_DIR = "build
|
29
|
+
BUILD_DIR = "build"
|
30
|
+
BUILD_EXT_DIR = File.join(BUILD_DIR, "#{Config::CONFIG['arch']}", 'ffi_c', RUBY_VERSION)
|
28
31
|
|
29
32
|
# Project general information
|
30
33
|
PROJ.name = 'ffi'
|
31
34
|
PROJ.authors = 'Wayne Meissner'
|
32
35
|
PROJ.email = 'wmeissner@gmail.com'
|
33
36
|
PROJ.url = 'http://kenai.com/projects/ruby-ffi'
|
34
|
-
PROJ.version = '0.
|
37
|
+
PROJ.version = '0.4.0'
|
35
38
|
PROJ.rubyforge.name = 'ffi'
|
36
39
|
PROJ.readme_file = 'README.rdoc'
|
37
40
|
|
38
41
|
# Annoucement
|
39
|
-
PROJ.ann.paragraphs
|
40
|
-
|
42
|
+
PROJ.ann.paragraphs << 'FEATURES' << 'SYNOPSIS' << 'REQUIREMENTS' << 'DOWNLOAD/INSTALL' << 'CREDITS' << 'LICENSE'
|
43
|
+
|
44
|
+
PROJ.ann.email[:from] = 'andrea.fazzi@alcacoop.it'
|
41
45
|
PROJ.ann.email[:to] << 'dev@ruby-ffi.kenai.com' << 'users@ruby-ffi.kenai.com'
|
42
46
|
PROJ.ann.email[:server] = 'smtp.gmail.com'
|
43
47
|
|
@@ -55,7 +59,7 @@ PROJ.rdoc.opts << '-x' << 'ext'
|
|
55
59
|
|
56
60
|
# Ruby
|
57
61
|
PROJ.ruby_opts = []
|
58
|
-
PROJ.ruby_opts << '-I' <<
|
62
|
+
PROJ.ruby_opts << '-I' << BUILD_EXT_DIR unless RUBY_PLATFORM == "java"
|
59
63
|
|
60
64
|
#RSpec
|
61
65
|
PROJ.spec.opts << '--color' << '-fs'
|
@@ -75,12 +79,12 @@ else
|
|
75
79
|
desc "Run all specs"
|
76
80
|
task :specs => TEST_DEPS do
|
77
81
|
ENV["MRI_FFI"] = "1"
|
78
|
-
sh %{#{Gem.ruby} -Ilib -I#{
|
82
|
+
sh %{#{Gem.ruby} -Ilib -I#{BUILD_EXT_DIR} -S spec #{Dir["spec/ffi/*_spec.rb"].join(" ")} -fs --color}
|
79
83
|
end
|
80
84
|
desc "Run rubinius specs"
|
81
85
|
task :rbxspecs => TEST_DEPS do
|
82
86
|
ENV["MRI_FFI"] = "1"
|
83
|
-
sh %{#{Gem.ruby} -Ilib -I#{
|
87
|
+
sh %{#{Gem.ruby} -Ilib -I#{BUILD_EXT_DIR} -S spec #{Dir["spec/ffi/rbx/*_spec.rb"].join(" ")} -fs --color}
|
84
88
|
end
|
85
89
|
end
|
86
90
|
|
@@ -90,30 +94,31 @@ task :package => 'gem:package'
|
|
90
94
|
desc "Install the gem locally"
|
91
95
|
task :install => 'gem:install'
|
92
96
|
|
93
|
-
|
94
|
-
file "#{BUILD_DIR}/Makefile" do
|
95
|
-
FileUtils.mkdir_p(BUILD_DIR) unless File.directory?(BUILD_DIR)
|
96
|
-
sh %{cd "#{BUILD_DIR}" && #{Gem.ruby} #{Dir.pwd}/ext/ffi_c/extconf.rb}
|
97
|
-
end
|
98
|
-
desc "Compile the native module"
|
99
|
-
task :compile => "#{BUILD_DIR}/Makefile" do
|
100
|
-
sh %{cd "#{BUILD_DIR}"; make}
|
101
|
-
end
|
102
|
-
end
|
97
|
+
|
103
98
|
desc "Clean all built files"
|
104
|
-
task :
|
105
|
-
FileUtils.rm_rf(
|
106
|
-
FileUtils.rm_rf(
|
107
|
-
FileUtils.
|
99
|
+
task :distclean => :clobber do
|
100
|
+
FileUtils.rm_rf('build')
|
101
|
+
FileUtils.rm_rf(Dir['lib/**/ffi_c.so'])
|
102
|
+
FileUtils.rm_rf('lib/1.8')
|
103
|
+
FileUtils.rm_rf('lib/1.9')
|
104
|
+
FileUtils.rm_rf('conftest.dSYM')
|
105
|
+
FileUtils.rm_rf('pkg')
|
108
106
|
end
|
107
|
+
|
108
|
+
|
109
|
+
desc "Build the native test lib"
|
109
110
|
task "build/libtest.#{LIBEXT}" do
|
110
|
-
sh %{#{GMAKE} -f libtest/GNUmakefile}
|
111
|
+
sh %{#{GMAKE} -f libtest/GNUmakefile CPU=#{Config::CONFIG['host_cpu']}}
|
111
112
|
end
|
113
|
+
|
114
|
+
|
112
115
|
desc "Build test helper lib"
|
113
116
|
task :libtest => "build/libtest.#{LIBEXT}"
|
117
|
+
|
114
118
|
desc "Test the extension"
|
115
|
-
task :test => [ :specs, :rbxspecs ]
|
116
|
-
|
119
|
+
task :test => [ :specs, :rbxspecs ]
|
120
|
+
|
121
|
+
|
117
122
|
namespace :bench do
|
118
123
|
ITER = ENV['ITER'] ? ENV['ITER'].to_i : 100000
|
119
124
|
bench_libs = "-Ilib -I#{BUILD_DIR}" unless RUBY_PLATFORM == "java"
|
@@ -132,3 +137,6 @@ end
|
|
132
137
|
|
133
138
|
task 'spec:run' => TEST_DEPS
|
134
139
|
task 'spec:specdoc' => TEST_DEPS
|
140
|
+
|
141
|
+
task :default => :specs
|
142
|
+
|
data/ext/ffi_c/AbstractMemory.c
CHANGED
@@ -11,9 +11,9 @@
|
|
11
11
|
|
12
12
|
|
13
13
|
static inline char* memory_address(VALUE self);
|
14
|
-
VALUE
|
15
|
-
static
|
16
|
-
static ID
|
14
|
+
VALUE rbffi_AbstractMemoryClass = Qnil;
|
15
|
+
static ID id_to_ptr = 0;
|
16
|
+
static ID id_call = 0;
|
17
17
|
|
18
18
|
static VALUE
|
19
19
|
memory_allocate(VALUE klass)
|
@@ -21,7 +21,7 @@ memory_allocate(VALUE klass)
|
|
21
21
|
AbstractMemory* memory;
|
22
22
|
VALUE obj;
|
23
23
|
obj = Data_Make_Struct(klass, AbstractMemory, NULL, -1, memory);
|
24
|
-
memory->ops = &
|
24
|
+
memory->ops = &rbffi_AbstractMemoryOps;
|
25
25
|
|
26
26
|
return obj;
|
27
27
|
}
|
@@ -107,63 +107,26 @@ NUM_OP(uint64, uint64_t, NUM2ULL, ULL2NUM);
|
|
107
107
|
NUM_OP(float32, float, NUM2DBL, rb_float_new);
|
108
108
|
NUM_OP(float64, double, NUM2DBL, rb_float_new);
|
109
109
|
|
110
|
-
static void
|
111
|
-
|
112
|
-
{
|
110
|
+
static inline void*
|
111
|
+
get_pointer_value(VALUE value)
|
112
|
+
{
|
113
113
|
const int type = TYPE(value);
|
114
|
-
|
115
|
-
|
116
|
-
if (rb_obj_is_kind_of(value, rb_FFI_Pointer_class) && type == T_DATA) {
|
117
|
-
void* tmp = memory_address(value);
|
118
|
-
memcpy(memory->address + off, &tmp, sizeof(tmp));
|
114
|
+
if (type == T_DATA && rb_obj_is_kind_of(value, rbffi_PointerClass)) {
|
115
|
+
return memory_address(value);
|
119
116
|
} else if (type == T_NIL) {
|
120
|
-
|
121
|
-
memcpy(memory->address + off, &tmp, sizeof(tmp));
|
117
|
+
return NULL;
|
122
118
|
} else if (type == T_FIXNUM) {
|
123
|
-
|
124
|
-
memcpy(memory->address + off, &tmp, sizeof(tmp));
|
119
|
+
return (void *) (uintptr_t) FIX2INT(value);
|
125
120
|
} else if (type == T_BIGNUM) {
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
VALUE ptr = rb_funcall2(value, to_ptr, 0, NULL);
|
130
|
-
void* tmp = MEMORY_PTR(ptr);
|
131
|
-
memcpy(memory->address + off, &tmp, sizeof(tmp));
|
121
|
+
return (void *) (uintptr_t) NUM2ULL(value);
|
122
|
+
} else if (rb_respond_to(value, id_to_ptr)) {
|
123
|
+
return MEMORY_PTR(rb_funcall2(value, id_to_ptr, 0, NULL));
|
132
124
|
} else {
|
133
125
|
rb_raise(rb_eArgError, "value is not a pointer");
|
134
126
|
}
|
135
127
|
}
|
136
128
|
|
137
|
-
|
138
|
-
memory_op_get_pointer(AbstractMemory* memory, long off)
|
139
|
-
{
|
140
|
-
void* tmp;
|
141
|
-
|
142
|
-
checkBounds(memory, off, sizeof(tmp));
|
143
|
-
memcpy(&tmp, memory->address + off, sizeof(tmp));
|
144
|
-
return rb_FFI_Pointer_new(tmp);
|
145
|
-
}
|
146
|
-
|
147
|
-
static VALUE
|
148
|
-
memory_put_pointer(VALUE self, VALUE offset, VALUE value)
|
149
|
-
{
|
150
|
-
AbstractMemory* memory;
|
151
|
-
|
152
|
-
Data_Get_Struct(self, AbstractMemory, memory);
|
153
|
-
memory_op_put_pointer(memory, NUM2LONG(offset), value);
|
154
|
-
|
155
|
-
return self;
|
156
|
-
}
|
157
|
-
|
158
|
-
static VALUE
|
159
|
-
memory_get_pointer(VALUE self, VALUE offset)
|
160
|
-
{
|
161
|
-
AbstractMemory* memory;
|
162
|
-
|
163
|
-
Data_Get_Struct(self, AbstractMemory, memory);
|
164
|
-
|
165
|
-
return memory_op_get_pointer(memory, NUM2LONG(offset));
|
166
|
-
}
|
129
|
+
NUM_OP(pointer, void *, get_pointer_value, rbffi_Pointer_NewInstance);
|
167
130
|
|
168
131
|
static VALUE
|
169
132
|
memory_put_callback(VALUE self, VALUE offset, VALUE proc, VALUE cbInfo)
|
@@ -172,8 +135,8 @@ memory_put_callback(VALUE self, VALUE offset, VALUE proc, VALUE cbInfo)
|
|
172
135
|
long off = NUM2LONG(offset);
|
173
136
|
checkBounds(memory, off, sizeof(void *));
|
174
137
|
|
175
|
-
if (rb_obj_is_kind_of(proc, rb_cProc)) {
|
176
|
-
VALUE callback =
|
138
|
+
if (rb_obj_is_kind_of(proc, rb_cProc) || rb_respond_to(proc, id_call)) {
|
139
|
+
VALUE callback = rbffi_NativeCallback_ForProc(proc, cbInfo);
|
177
140
|
void* code = ((NativeCallback *) DATA_PTR(callback))->code;
|
178
141
|
memcpy(memory->address + off, &code, sizeof(code));
|
179
142
|
} else {
|
@@ -214,6 +177,45 @@ memory_get_string(int argc, VALUE* argv, VALUE self)
|
|
214
177
|
(end != NULL ? end - ptr->address - off : len));
|
215
178
|
}
|
216
179
|
|
180
|
+
static VALUE
|
181
|
+
memory_get_array_of_string(int argc, VALUE* argv, VALUE self)
|
182
|
+
{
|
183
|
+
VALUE offset = Qnil, countnum = Qnil, retVal = Qnil;
|
184
|
+
AbstractMemory* ptr;
|
185
|
+
long off;
|
186
|
+
int count;
|
187
|
+
|
188
|
+
rb_scan_args(argc, argv, "11", &offset, &countnum);
|
189
|
+
off = NUM2LONG(offset);
|
190
|
+
count = (countnum == Qnil ? 0 : NUM2INT(countnum));
|
191
|
+
retVal = rb_ary_new2(count);
|
192
|
+
|
193
|
+
Data_Get_Struct(self, AbstractMemory, ptr);
|
194
|
+
|
195
|
+
if (countnum != Qnil) {
|
196
|
+
int i;
|
197
|
+
|
198
|
+
checkBounds(ptr, off, count * sizeof (char*));
|
199
|
+
|
200
|
+
for (i = 0; i < count; ++i) {
|
201
|
+
const char* strptr = *((const char**) (ptr->address + off) + i);
|
202
|
+
rb_ary_push(retVal, (strptr == NULL ? Qnil : rb_tainted_str_new2(strptr)));
|
203
|
+
}
|
204
|
+
|
205
|
+
} else {
|
206
|
+
checkBounds(ptr, off, sizeof (char*));
|
207
|
+
for ( ; off < ptr->size - sizeof (void *); off += sizeof (void *)) {
|
208
|
+
const char* strptr = *(const char**) (ptr->address + off);
|
209
|
+
if (strptr == NULL) {
|
210
|
+
break;
|
211
|
+
}
|
212
|
+
rb_ary_push(retVal, rb_tainted_str_new2(strptr));
|
213
|
+
}
|
214
|
+
}
|
215
|
+
|
216
|
+
return retVal;
|
217
|
+
}
|
218
|
+
|
217
219
|
static VALUE
|
218
220
|
memory_put_string(VALUE self, VALUE offset, VALUE str)
|
219
221
|
{
|
@@ -224,7 +226,7 @@ memory_put_string(VALUE self, VALUE offset, VALUE str)
|
|
224
226
|
off = NUM2LONG(offset);
|
225
227
|
len = RSTRING_LEN(str);
|
226
228
|
|
227
|
-
checkBounds(ptr, off, len);
|
229
|
+
checkBounds(ptr, off, len + 1);
|
228
230
|
if (rb_safe_level() >= 1 && OBJ_TAINTED(str)) {
|
229
231
|
rb_raise(rb_eSecurityError, "Writing unsafe string to memory");
|
230
232
|
}
|
@@ -279,13 +281,14 @@ memory_address(VALUE obj)
|
|
279
281
|
}
|
280
282
|
|
281
283
|
AbstractMemory*
|
282
|
-
|
284
|
+
rbffi_AbstractMemory_Cast(VALUE obj, VALUE klass)
|
283
285
|
{
|
284
286
|
if (rb_obj_is_kind_of(obj, klass)) {
|
285
287
|
AbstractMemory* memory;
|
286
288
|
Data_Get_Struct(obj, AbstractMemory, memory);
|
287
289
|
return memory;
|
288
290
|
}
|
291
|
+
|
289
292
|
rb_raise(rb_eArgError, "Invalid Memory object");
|
290
293
|
return NULL;
|
291
294
|
}
|
@@ -311,9 +314,9 @@ memory_op_put_strptr(AbstractMemory* ptr, long offset, VALUE value)
|
|
311
314
|
|
312
315
|
static MemoryOp memory_op_strptr = { memory_op_get_strptr, memory_op_put_strptr };
|
313
316
|
|
314
|
-
static MemoryOp memory_op_pointer = { memory_op_get_pointer, memory_op_put_pointer };
|
317
|
+
//static MemoryOp memory_op_pointer = { memory_op_get_pointer, memory_op_put_pointer };
|
315
318
|
|
316
|
-
MemoryOps
|
319
|
+
MemoryOps rbffi_AbstractMemoryOps = {
|
317
320
|
.int8 = &memory_op_int8,
|
318
321
|
.uint8 = &memory_op_uint8,
|
319
322
|
.int16 = &memory_op_int16,
|
@@ -329,10 +332,11 @@ MemoryOps rb_FFI_AbstractMemory_ops = {
|
|
329
332
|
};
|
330
333
|
|
331
334
|
void
|
332
|
-
|
335
|
+
rbffi_AbstractMemory_Init(VALUE moduleFFI)
|
333
336
|
{
|
334
|
-
VALUE
|
335
|
-
|
337
|
+
VALUE classMemory = rb_define_class_under(moduleFFI, "AbstractMemory", rb_cObject);
|
338
|
+
rbffi_AbstractMemoryClass = classMemory;
|
339
|
+
rb_global_variable(&rbffi_AbstractMemoryClass);
|
336
340
|
|
337
341
|
rb_define_alloc_func(classMemory, memory_allocate);
|
338
342
|
#undef INT
|
@@ -367,16 +371,11 @@ rb_FFI_AbstractMemory_Init()
|
|
367
371
|
ALIAS(long_long, int64);
|
368
372
|
|
369
373
|
if (sizeof(long) == 4) {
|
370
|
-
|
371
|
-
rb_define_alias(classMemory, "put_ulong", "put_uint32");
|
372
|
-
rb_define_alias(classMemory, "get_long", "get_int32");
|
373
|
-
rb_define_alias(classMemory, "get_ulong", "get_uint32");
|
374
|
+
ALIAS(long, int32);
|
374
375
|
} else {
|
375
|
-
|
376
|
-
rb_define_alias(classMemory, "put_ulong", "put_uint64");
|
377
|
-
rb_define_alias(classMemory, "get_long", "get_int64");
|
378
|
-
rb_define_alias(classMemory, "get_ulong", "get_uint64");
|
376
|
+
ALIAS(long, int64);
|
379
377
|
}
|
378
|
+
|
380
379
|
rb_define_method(classMemory, "put_float32", memory_put_float32, 2);
|
381
380
|
rb_define_method(classMemory, "get_float32", memory_get_float32, 1);
|
382
381
|
rb_define_alias(classMemory, "put_float", "put_float32");
|
@@ -395,15 +394,19 @@ rb_FFI_AbstractMemory_Init()
|
|
395
394
|
rb_define_alias(classMemory, "get_array_of_double", "get_array_of_float64");
|
396
395
|
rb_define_method(classMemory, "put_pointer", memory_put_pointer, 2);
|
397
396
|
rb_define_method(classMemory, "get_pointer", memory_get_pointer, 1);
|
397
|
+
rb_define_method(classMemory, "put_array_of_pointer", memory_put_array_of_pointer, 2);
|
398
|
+
rb_define_method(classMemory, "get_array_of_pointer", memory_get_array_of_pointer, 2);
|
398
399
|
rb_define_method(classMemory, "put_callback", memory_put_callback, 3);
|
399
400
|
rb_define_method(classMemory, "get_string", memory_get_string, -1);
|
400
401
|
rb_define_method(classMemory, "put_string", memory_put_string, 2);
|
401
402
|
rb_define_method(classMemory, "get_bytes", memory_get_bytes, 2);
|
402
403
|
rb_define_method(classMemory, "put_bytes", memory_put_bytes, -1);
|
404
|
+
rb_define_method(classMemory, "get_array_of_string", memory_get_array_of_string, -1);
|
403
405
|
|
404
406
|
rb_define_method(classMemory, "clear", memory_clear, 0);
|
405
407
|
rb_define_method(classMemory, "total", memory_size, 0);
|
406
408
|
|
407
|
-
|
409
|
+
id_to_ptr = rb_intern("to_ptr");
|
410
|
+
id_call = rb_intern("call");
|
408
411
|
}
|
409
412
|
|
data/ext/ffi_c/AbstractMemory.h
CHANGED
@@ -5,6 +5,8 @@
|
|
5
5
|
#include <sys/types.h>
|
6
6
|
#include <stdint.h>
|
7
7
|
|
8
|
+
#include "compat.h"
|
9
|
+
|
8
10
|
#ifdef __cplusplus
|
9
11
|
extern "C" {
|
10
12
|
#endif
|
@@ -47,14 +49,16 @@ checkBounds(AbstractMemory* mem, long off, long len)
|
|
47
49
|
}
|
48
50
|
}
|
49
51
|
|
50
|
-
#define MEMORY(obj)
|
52
|
+
#define MEMORY(obj) rbffi_AbstractMemory_Cast((obj), rbffi_AbstractMemoryClass)
|
51
53
|
#define MEMORY_PTR(obj) MEMORY((obj))->address
|
52
54
|
#define MEMORY_LEN(obj) MEMORY((obj))->size
|
53
55
|
|
54
|
-
extern
|
56
|
+
extern void rbffi_AbstractMemory_Init(VALUE ffiModule);
|
57
|
+
|
58
|
+
extern AbstractMemory* rbffi_AbstractMemory_Cast(VALUE obj, VALUE klass);
|
55
59
|
|
56
|
-
extern VALUE
|
57
|
-
extern MemoryOps
|
60
|
+
extern VALUE rbffi_AbstractMemoryClass;
|
61
|
+
extern MemoryOps rbffi_AbstractMemoryOps;
|
58
62
|
|
59
63
|
#ifdef __cplusplus
|
60
64
|
}
|