ffi 0.6.4 → 1.0.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/History.txt +7 -0
- data/LICENSE +10 -21
- data/README.rdoc +70 -0
- data/Rakefile +56 -84
- 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 +52 -540
- 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 +252 -30
- data/ext/ffi_c/MappedType.c +146 -0
- data/{libtest/FunctionTest.c → ext/ffi_c/MappedType.h} +32 -25
- 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 +19 -306
- data/ext/ffi_c/Struct.h +6 -0
- data/ext/ffi_c/StructByReference.c +150 -0
- data/{libtest/LastErrorTest.c → ext/ffi_c/StructByReference.h} +30 -21
- data/ext/ffi_c/StructLayout.c +26 -16
- data/ext/ffi_c/Type.c +39 -68
- data/ext/ffi_c/Type.h +12 -22
- data/ext/ffi_c/Types.c +20 -5
- 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/rbffi.h +1 -0
- 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 -80
- data/lib/ffi/io.rb +12 -20
- data/lib/ffi/library.rb +109 -92
- data/lib/ffi/managedstruct.rb +1 -1
- data/lib/ffi/memorypointer.rb +15 -21
- data/lib/ffi/platform.rb +27 -33
- data/lib/ffi/pointer.rb +14 -21
- data/lib/ffi/struct.rb +98 -49
- 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 +19 -5
- 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 +139 -131
- data/README.md +0 -109
- data/ext/ffi_c/AutoPointer.c +0 -60
- data/ext/ffi_c/AutoPointer.h +0 -18
- data/ext/ffi_c/Ffi_c.iml +0 -12
- data/ffi.gemspec +0 -18
- data/gen/log +0 -1
- data/lib/Lib.iml +0 -21
- data/libtest/Benchmark.c +0 -73
- data/libtest/BoolTest.c +0 -52
- data/libtest/BufferTest.c +0 -52
- data/libtest/ClosureTest.c +0 -173
- data/libtest/EnumTest.c +0 -55
- data/libtest/GNUmakefile +0 -141
- data/libtest/GlobalVariable.c +0 -56
- data/libtest/NumberTest.c +0 -145
- data/libtest/PointerTest.c +0 -84
- data/libtest/ReferenceTest.c +0 -44
- data/libtest/StringTest.c +0 -55
- data/libtest/StructTest.c +0 -247
- data/libtest/UnionTest.c +0 -64
- data/libtest/VariadicTest.c +0 -57
- data/spec/ffi/Ffi.iml +0 -12
data/History.txt
CHANGED
data/LICENSE
CHANGED
@@ -1,25 +1,14 @@
|
|
1
|
-
Copyright (c) 2008
|
1
|
+
Copyright (c) 2008-2010 Ruby-FFI contributors
|
2
2
|
All rights reserved.
|
3
3
|
|
4
|
-
|
5
|
-
|
4
|
+
This code is free software: you can redistribute it and/or modify it under
|
5
|
+
the terms of the GNU Lesser General Public License version 3 only, as
|
6
|
+
published by the Free Software Foundation.
|
6
7
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
and/or other materials provided with the distribution.
|
12
|
-
* Neither the name of the JRuby Project nor the names of its contributors
|
13
|
-
may be used to endorse or promote products derived from this software
|
14
|
-
without specific prior written permission.
|
8
|
+
This code is distributed in the hope that it will be useful, but WITHOUT
|
9
|
+
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
10
|
+
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
11
|
+
version 3 for more details.
|
15
12
|
|
16
|
-
|
17
|
-
|
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.
|
13
|
+
You should have received a copy of the GNU Lesser General Public License
|
14
|
+
version 3 along with this work. If not, see <http://www.gnu.org/licenses/>.
|
data/README.rdoc
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
ruby-ffi
|
2
|
+
by Wayne Meissner
|
3
|
+
http://wiki.github.com/ffi/ffi
|
4
|
+
|
5
|
+
== DESCRIPTION:
|
6
|
+
|
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://wiki.github.com/ffi/ffi/why-use-ffi].
|
12
|
+
|
13
|
+
== FEATURES/PROBLEMS:
|
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
|
+
|
21
|
+
== SYNOPSIS:
|
22
|
+
|
23
|
+
require 'ffi'
|
24
|
+
|
25
|
+
module MyLib
|
26
|
+
extend FFI::Library
|
27
|
+
ffi_lib 'c'
|
28
|
+
attach_function :puts, [ :string ], :int
|
29
|
+
end
|
30
|
+
|
31
|
+
MyLib.puts 'Hello boys using libc!'
|
32
|
+
|
33
|
+
For less minimalistic and more sane examples you may look at:
|
34
|
+
|
35
|
+
* the samples/ folder
|
36
|
+
* the examples on the wiki[http://wiki.github.com/ffi/ffi]
|
37
|
+
* the projects using FFI listed on this page[http://wiki.github.com/ffi/ffi/projects-using-ffi]
|
38
|
+
|
39
|
+
== REQUIREMENTS:
|
40
|
+
|
41
|
+
* You need a sane building environment in order to compile the extension.
|
42
|
+
|
43
|
+
== DOWNLOAD/INSTALL:
|
44
|
+
|
45
|
+
From rubyforge:
|
46
|
+
|
47
|
+
[sudo] gem install ffi
|
48
|
+
|
49
|
+
or from the git repository on github:
|
50
|
+
|
51
|
+
git clone git://github.com/ffi/ffi.git
|
52
|
+
cd ffi
|
53
|
+
rake gem:install
|
54
|
+
|
55
|
+
== CREDITS:
|
56
|
+
|
57
|
+
Special thanks to:
|
58
|
+
|
59
|
+
* Yehuda Katz
|
60
|
+
* Luc Heinrich
|
61
|
+
* Andrea Fazzi
|
62
|
+
* Mike Dalessio
|
63
|
+
* Hongli Lai
|
64
|
+
* Evan Phoenix
|
65
|
+
* Aman Gupta
|
66
|
+
* Beoran
|
67
|
+
|
68
|
+
== LICENSE:
|
69
|
+
|
70
|
+
See LICENSE file.
|
data/Rakefile
CHANGED
@@ -1,31 +1,32 @@
|
|
1
1
|
require 'rubygems'
|
2
|
-
require 'rubygems/package_task'
|
3
2
|
require 'rbconfig'
|
4
3
|
|
5
4
|
USE_RAKE_COMPILER = (RUBY_PLATFORM =~ /java/) ? false : true
|
6
5
|
if USE_RAKE_COMPILER
|
7
6
|
gem 'rake-compiler', '>=0.6.0'
|
8
7
|
require 'rake/extensiontask'
|
8
|
+
ENV['RUBY_CC_VERSION'] = '1.8.6:1.9.1'
|
9
9
|
end
|
10
10
|
|
11
11
|
require 'date'
|
12
12
|
require 'fileutils'
|
13
13
|
require 'rbconfig'
|
14
14
|
|
15
|
+
load 'tasks/setup.rb'
|
15
16
|
|
16
|
-
LIBEXT = case
|
17
|
+
LIBEXT = case Config::CONFIG['host_os'].downcase
|
17
18
|
when /darwin/
|
18
19
|
"dylib"
|
19
20
|
when /mswin|mingw/
|
20
21
|
"dll"
|
21
22
|
else
|
22
|
-
|
23
|
+
Config::CONFIG['DLEXT']
|
23
24
|
end
|
24
25
|
|
25
|
-
CPU = case
|
26
|
+
CPU = case Config::CONFIG['host_cpu'].downcase
|
26
27
|
when /i[3456]86/
|
27
28
|
# Darwin always reports i686, even when running in 64bit mode
|
28
|
-
if
|
29
|
+
if Config::CONFIG['host_os'] =~ /darwin/ && 0xfee1deadbeef.is_a?(Fixnum)
|
29
30
|
"x86_64"
|
30
31
|
else
|
31
32
|
"i386"
|
@@ -40,14 +41,11 @@ CPU = case RbConfig::CONFIG['host_cpu'].downcase
|
|
40
41
|
when /ppc|powerpc/
|
41
42
|
"powerpc"
|
42
43
|
|
43
|
-
when /^arm/
|
44
|
-
"arm"
|
45
|
-
|
46
44
|
else
|
47
|
-
|
45
|
+
Config::CONFIG['host_cpu']
|
48
46
|
end
|
49
47
|
|
50
|
-
OS = case
|
48
|
+
OS = case Config::CONFIG['host_os'].downcase
|
51
49
|
when /linux/
|
52
50
|
"linux"
|
53
51
|
when /darwin/
|
@@ -61,48 +59,78 @@ OS = case RbConfig::CONFIG['host_os'].downcase
|
|
61
59
|
when /mswin|mingw/
|
62
60
|
"win32"
|
63
61
|
else
|
64
|
-
|
62
|
+
Config::CONFIG['host_os'].downcase
|
65
63
|
end
|
66
64
|
|
67
|
-
CC
|
65
|
+
CC=ENV['CC'] || Config::CONFIG['CC'] || "gcc"
|
68
66
|
|
69
|
-
GMAKE =
|
67
|
+
GMAKE = Config::CONFIG['host_os'].downcase =~ /bsd|solaris/ ? "gmake" : "make"
|
70
68
|
|
71
69
|
LIBTEST = "build/libtest.#{LIBEXT}"
|
72
70
|
BUILD_DIR = "build"
|
73
|
-
BUILD_EXT_DIR = File.join(BUILD_DIR, "#{
|
71
|
+
BUILD_EXT_DIR = File.join(BUILD_DIR, "#{Config::CONFIG['arch']}", 'ffi_c', RUBY_VERSION)
|
74
72
|
|
75
|
-
|
76
|
-
|
77
|
-
|
73
|
+
# Project general information
|
74
|
+
PROJ.name = 'ffi'
|
75
|
+
PROJ.authors = 'Wayne Meissner'
|
76
|
+
PROJ.email = 'wmeissner@gmail.com'
|
77
|
+
PROJ.url = 'http://wiki.github.com/ffi/ffi'
|
78
|
+
PROJ.version = '1.0.0'
|
79
|
+
PROJ.rubyforge.name = 'ffi'
|
80
|
+
PROJ.readme_file = 'README.rdoc'
|
78
81
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
82
|
+
# Annoucement
|
83
|
+
PROJ.ann.paragraphs << 'FEATURES' << 'SYNOPSIS' << 'REQUIREMENTS' << 'DOWNLOAD/INSTALL' << 'CREDITS' << 'LICENSE'
|
84
|
+
|
85
|
+
PROJ.ann.email[:from] = 'andrea.fazzi@alcacoop.it'
|
86
|
+
PROJ.ann.email[:to] = ['ruby-ffi@googlegroups.com']
|
87
|
+
PROJ.ann.email[:server] = 'smtp.gmail.com'
|
88
|
+
|
89
|
+
# Gem specifications
|
90
|
+
PROJ.gem.need_tar = false
|
91
|
+
PROJ.gem.files = %w(History.txt LICENSE README.rdoc Rakefile) + Dir.glob("{ext,gen,lib,spec,tasks}/**/*")
|
92
|
+
PROJ.gem.platform = Gem::Platform::RUBY
|
93
|
+
|
94
|
+
# Override Mr. Bones autogenerated extensions and force ours in
|
95
|
+
PROJ.gem.extras['extensions'] = %w(ext/ffi_c/extconf.rb gen/Rakefile)
|
96
|
+
|
97
|
+
# RDoc
|
98
|
+
PROJ.rdoc.exclude << '^ext\/'
|
99
|
+
PROJ.rdoc.opts << '-x' << 'ext'
|
100
|
+
|
101
|
+
# Ruby
|
102
|
+
PROJ.ruby_opts = []
|
103
|
+
PROJ.ruby_opts << '-I' << BUILD_EXT_DIR unless RUBY_PLATFORM == "java"
|
104
|
+
|
105
|
+
# RSpec
|
106
|
+
PROJ.spec.files.exclude /rbx/
|
107
|
+
PROJ.spec.opts << '--color' << '-fs'
|
108
|
+
|
109
|
+
# Dependencies
|
110
|
+
|
111
|
+
depend_on 'rake', '>=0.8.7'
|
84
112
|
|
85
113
|
TEST_DEPS = [ LIBTEST ]
|
86
114
|
if RUBY_PLATFORM == "java"
|
87
115
|
desc "Run all specs"
|
88
116
|
task :specs => TEST_DEPS do
|
89
|
-
sh %{#{Gem.ruby} -
|
117
|
+
sh %{#{Gem.ruby} -S spec #{Dir["spec/ffi/*_spec.rb"].join(" ")} -fs --color}
|
90
118
|
end
|
91
119
|
desc "Run rubinius specs"
|
92
120
|
task :rbxspecs => TEST_DEPS do
|
93
|
-
sh %{#{Gem.ruby} -
|
121
|
+
sh %{#{Gem.ruby} -S spec #{Dir["spec/ffi/rbx/*_spec.rb"].join(" ")} -fs --color}
|
94
122
|
end
|
95
123
|
else
|
96
124
|
TEST_DEPS.unshift :compile
|
97
125
|
desc "Run all specs"
|
98
126
|
task :specs => TEST_DEPS do
|
99
127
|
ENV["MRI_FFI"] = "1"
|
100
|
-
sh %{#{Gem.ruby} -
|
128
|
+
sh %{#{Gem.ruby} -Ilib -I#{BUILD_EXT_DIR} -S spec #{Dir["spec/ffi/*_spec.rb"].join(" ")} -fs --color}
|
101
129
|
end
|
102
130
|
desc "Run rubinius specs"
|
103
131
|
task :rbxspecs => TEST_DEPS do
|
104
132
|
ENV["MRI_FFI"] = "1"
|
105
|
-
sh %{#{Gem.ruby} -
|
133
|
+
sh %{#{Gem.ruby} -Ilib -I#{BUILD_EXT_DIR} -S spec #{Dir["spec/ffi/rbx/*_spec.rb"].join(" ")} -fs --color}
|
106
134
|
end
|
107
135
|
end
|
108
136
|
|
@@ -112,16 +140,11 @@ task :package => 'gem:package'
|
|
112
140
|
desc "Install the gem locally"
|
113
141
|
task :install => 'gem:install'
|
114
142
|
|
115
|
-
namespace :gem do
|
116
|
-
task :install => :gem do
|
117
|
-
ruby %{ -S gem install pkg/ffi-#{gem_spec.version}.gem }
|
118
|
-
end
|
119
|
-
end
|
120
143
|
|
121
144
|
desc "Clean all built files"
|
122
145
|
task :distclean => :clobber do
|
123
146
|
FileUtils.rm_rf('build')
|
124
|
-
FileUtils.rm_rf(Dir["lib/**/ffi_c.#{
|
147
|
+
FileUtils.rm_rf(Dir["lib/**/ffi_c.#{Config::CONFIG['DLEXT']}"])
|
125
148
|
FileUtils.rm_rf('lib/1.8')
|
126
149
|
FileUtils.rm_rf('lib/1.9')
|
127
150
|
FileUtils.rm_rf('lib/ffi/types.conf')
|
@@ -131,7 +154,7 @@ end
|
|
131
154
|
|
132
155
|
|
133
156
|
desc "Build the native test lib"
|
134
|
-
|
157
|
+
task "build/libtest.#{LIBEXT}" do
|
135
158
|
sh %{#{GMAKE} -f libtest/GNUmakefile CPU=#{CPU} OS=#{OS} }
|
136
159
|
end
|
137
160
|
|
@@ -164,54 +187,3 @@ task 'spec:specdoc' => TEST_DEPS
|
|
164
187
|
|
165
188
|
task :default => :specs
|
166
189
|
|
167
|
-
task 'gem:win32' do
|
168
|
-
sh("rake cross native gem RUBY_CC_VERSION='1.8.7:1.9.3'") || raise("win32 build failed!")
|
169
|
-
end
|
170
|
-
|
171
|
-
|
172
|
-
namespace 'java' do
|
173
|
-
|
174
|
-
java_gem_spec = Gem::Specification.new do |s|
|
175
|
-
s.name = gem_spec.name
|
176
|
-
s.version = gem_spec.version
|
177
|
-
s.author = gem_spec.author
|
178
|
-
s.email = gem_spec.email
|
179
|
-
s.homepage = gem_spec.homepage
|
180
|
-
s.summary = gem_spec.summary
|
181
|
-
s.description = gem_spec.description
|
182
|
-
s.files = %w(History.txt LICENSE COPYING COPYING.LESSER README.md Rakefile)
|
183
|
-
s.has_rdoc = false
|
184
|
-
s.license = gem_spec.license
|
185
|
-
s.platform = 'java'
|
186
|
-
end
|
187
|
-
|
188
|
-
Gem::PackageTask.new(java_gem_spec) do |pkg|
|
189
|
-
pkg.need_zip = true
|
190
|
-
pkg.need_tar = true
|
191
|
-
pkg.package_dir = 'pkg'
|
192
|
-
end
|
193
|
-
end
|
194
|
-
|
195
|
-
task 'gem:java' => 'java:gem'
|
196
|
-
|
197
|
-
|
198
|
-
if USE_RAKE_COMPILER
|
199
|
-
Rake::ExtensionTask.new('ffi_c', gem_spec) do |ext|
|
200
|
-
ext.name = 'ffi_c' # indicate the name of the extension.
|
201
|
-
# ext.lib_dir = BUILD_DIR # put binaries into this folder.
|
202
|
-
ext.tmp_dir = BUILD_DIR # temporary folder used during compilation.
|
203
|
-
ext.cross_compile = true # enable cross compilation (requires cross compile toolchain)
|
204
|
-
ext.cross_platform = 'i386-mingw32' # forces the Windows platform instead of the default one
|
205
|
-
end
|
206
|
-
end
|
207
|
-
|
208
|
-
begin
|
209
|
-
require 'yard'
|
210
|
-
|
211
|
-
namespace :doc do
|
212
|
-
YARD::Rake::YardocTask.new do |yard|
|
213
|
-
end
|
214
|
-
end
|
215
|
-
rescue LoadError
|
216
|
-
warn "[warn] YARD unavailable"
|
217
|
-
end
|
data/ext/ffi_c/AbstractMemory.c
CHANGED
@@ -3,33 +3,26 @@
|
|
3
3
|
*
|
4
4
|
* All rights reserved.
|
5
5
|
*
|
6
|
-
*
|
7
|
-
* modification, are permitted provided that the following conditions are met:
|
6
|
+
* This file is part of ruby-ffi.
|
8
7
|
*
|
9
|
-
*
|
10
|
-
*
|
11
|
-
*
|
12
|
-
* this list of conditions and the following disclaimer in the documentation
|
13
|
-
* and/or other materials provided with the distribution.
|
14
|
-
* * The name of the author or authors may not be used to endorse or promote
|
15
|
-
* products derived from this software without specific prior written permission.
|
8
|
+
* This code is free software: you can redistribute it and/or modify it under
|
9
|
+
* the terms of the GNU Lesser General Public License version 3 only, as
|
10
|
+
* published by the Free Software Foundation.
|
16
11
|
*
|
17
|
-
*
|
18
|
-
*
|
19
|
-
*
|
20
|
-
*
|
21
|
-
*
|
22
|
-
*
|
23
|
-
*
|
24
|
-
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
25
|
-
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
26
|
-
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
12
|
+
* This code is distributed in the hope that it will be useful, but WITHOUT
|
13
|
+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
14
|
+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
15
|
+
* version 3 for more details.
|
16
|
+
*
|
17
|
+
* You should have received a copy of the GNU Lesser General Public License
|
18
|
+
* version 3 along with this work. If not, see <http://www.gnu.org/licenses/>.
|
27
19
|
*/
|
28
20
|
|
29
21
|
#include <sys/types.h>
|
30
22
|
#include <sys/param.h>
|
31
23
|
#include <stdint.h>
|
32
24
|
#include <stdbool.h>
|
25
|
+
#include <limits.h>
|
33
26
|
#include <ruby.h>
|
34
27
|
#include "rbffi.h"
|
35
28
|
#include "compat.h"
|
@@ -49,17 +42,18 @@ memory_allocate(VALUE klass)
|
|
49
42
|
AbstractMemory* memory;
|
50
43
|
VALUE obj;
|
51
44
|
obj = Data_Make_Struct(klass, AbstractMemory, NULL, -1, memory);
|
52
|
-
memory->
|
45
|
+
memory->flags = MEM_RD | MEM_WR;
|
53
46
|
|
54
47
|
return obj;
|
55
48
|
}
|
49
|
+
#define VAL(x, swap) (unlikely(((memory->flags & MEM_SWAP) != 0)) ? swap((x)) : (x))
|
56
50
|
|
57
|
-
#define NUM_OP(name, type, toNative, fromNative) \
|
51
|
+
#define NUM_OP(name, type, toNative, fromNative, swap) \
|
58
52
|
static void memory_op_put_##name(AbstractMemory* memory, long off, VALUE value); \
|
59
53
|
static void \
|
60
54
|
memory_op_put_##name(AbstractMemory* memory, long off, VALUE value) \
|
61
55
|
{ \
|
62
|
-
type tmp = (type) toNative(value); \
|
56
|
+
type tmp = (type) VAL(toNative(value), swap); \
|
63
57
|
checkWrite(memory); \
|
64
58
|
checkBounds(memory, off, sizeof(type)); \
|
65
59
|
memcpy(memory->address + off, &tmp, sizeof(tmp)); \
|
@@ -81,7 +75,7 @@ memory_op_get_##name(AbstractMemory* memory, long off) \
|
|
81
75
|
checkRead(memory); \
|
82
76
|
checkBounds(memory, off, sizeof(type)); \
|
83
77
|
memcpy(&tmp, memory->address + off, sizeof(tmp)); \
|
84
|
-
return fromNative(tmp); \
|
78
|
+
return fromNative(VAL(tmp, swap)); \
|
85
79
|
} \
|
86
80
|
static VALUE memory_get_##name(VALUE self, VALUE offset); \
|
87
81
|
static VALUE \
|
@@ -104,7 +98,7 @@ memory_put_array_of_##name(VALUE self, VALUE offset, VALUE ary) \
|
|
104
98
|
checkWrite(memory); \
|
105
99
|
checkBounds(memory, off, count * sizeof(type)); \
|
106
100
|
for (i = 0; i < count; i++) { \
|
107
|
-
type tmp = (type) toNative(RARRAY_PTR(ary)[i]); \
|
101
|
+
type tmp = (type) VAL(toNative(RARRAY_PTR(ary)[i]), swap); \
|
108
102
|
memcpy(memory->address + off + (i * sizeof(type)), &tmp, sizeof(tmp)); \
|
109
103
|
} \
|
110
104
|
return self; \
|
@@ -123,23 +117,47 @@ memory_get_array_of_##name(VALUE self, VALUE offset, VALUE length) \
|
|
123
117
|
for (i = 0; i < count; ++i) { \
|
124
118
|
type tmp; \
|
125
119
|
memcpy(&tmp, memory->address + off + (i * sizeof(type)), sizeof(tmp)); \
|
126
|
-
rb_ary_push(retVal, fromNative(tmp)); \
|
120
|
+
rb_ary_push(retVal, fromNative(VAL(tmp, swap))); \
|
127
121
|
} \
|
128
122
|
return retVal; \
|
129
123
|
}
|
130
124
|
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
125
|
+
#define NOSWAP(x) (x)
|
126
|
+
#define bswap16(x) (((x) >> 8) & 0xff) | (((x) << 8) & 0xff00);
|
127
|
+
static inline int16_t
|
128
|
+
SWAPS16(int16_t x)
|
129
|
+
{
|
130
|
+
return bswap16(x);
|
131
|
+
}
|
132
|
+
|
133
|
+
static inline uint16_t
|
134
|
+
SWAPU16(uint16_t x)
|
135
|
+
{
|
136
|
+
return bswap16(x);
|
137
|
+
}
|
138
|
+
|
139
|
+
#define SWAP16(x) (x)
|
140
|
+
#define SWAP32(x) __builtin_bswap32(x)
|
141
|
+
#define SWAP64(x) __builtin_bswap64(x)
|
142
|
+
|
143
|
+
#if LONG_MAX > INT_MAX
|
144
|
+
# define SWAPLONG SWAP64
|
145
|
+
#else
|
146
|
+
# define SWAPLONG SWAP32
|
147
|
+
#endif
|
148
|
+
|
149
|
+
NUM_OP(int8, int8_t, NUM2INT, INT2NUM, NOSWAP);
|
150
|
+
NUM_OP(uint8, uint8_t, NUM2UINT, UINT2NUM, NOSWAP);
|
151
|
+
NUM_OP(int16, int16_t, NUM2INT, INT2NUM, SWAP16);
|
152
|
+
NUM_OP(uint16, uint16_t, NUM2UINT, UINT2NUM, SWAP16);
|
153
|
+
NUM_OP(int32, int32_t, NUM2INT, INT2NUM, SWAP32);
|
154
|
+
NUM_OP(uint32, uint32_t, NUM2UINT, UINT2NUM, SWAP32);
|
155
|
+
NUM_OP(int64, int64_t, NUM2LL, LL2NUM, SWAP64);
|
156
|
+
NUM_OP(uint64, uint64_t, NUM2ULL, ULL2NUM, SWAP64);
|
157
|
+
NUM_OP(long, long, NUM2LONG, LONG2NUM, SWAPLONG);
|
158
|
+
NUM_OP(ulong, unsigned long, NUM2ULONG, ULONG2NUM, SWAPLONG);
|
159
|
+
NUM_OP(float32, float, NUM2DBL, rb_float_new, NOSWAP);
|
160
|
+
NUM_OP(float64, double, NUM2DBL, rb_float_new, NOSWAP);
|
143
161
|
|
144
162
|
static inline void*
|
145
163
|
get_pointer_value(VALUE value)
|
@@ -161,7 +179,7 @@ get_pointer_value(VALUE value)
|
|
161
179
|
}
|
162
180
|
}
|
163
181
|
|
164
|
-
NUM_OP(pointer, void *, get_pointer_value, rbffi_Pointer_NewInstance);
|
182
|
+
NUM_OP(pointer, void *, get_pointer_value, rbffi_Pointer_NewInstance, NOSWAP);
|
165
183
|
|
166
184
|
static VALUE
|
167
185
|
memory_clear(VALUE self)
|