ffi 0.6.0 → 0.6.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +102 -0
- data/README.md +109 -0
- data/Rakefile +85 -56
- data/ext/ffi_c/Call.c +3 -3
- data/ext/ffi_c/Ffi_c.iml +12 -0
- data/ext/ffi_c/Function.c +3 -2
- data/ext/ffi_c/Struct.c +88 -13
- data/ext/ffi_c/StructLayout.c +2 -1
- data/ext/ffi_c/Types.c +1 -1
- data/ext/ffi_c/libffi/configure +1 -1
- data/ext/ffi_c/libffi.gnu.mk +1 -1
- data/ext/ffi_c/libffi.mk +1 -1
- data/ffi.gemspec +18 -0
- data/gen/Rakefile +4 -2
- data/gen/log +1 -0
- data/lib/Lib.iml +21 -0
- data/lib/ffi/ffi.rb +1 -0
- data/lib/ffi/library.rb +2 -2
- data/lib/ffi/platform.rb +5 -3
- data/lib/ffi/struct.rb +2 -2
- data/libtest/Benchmark.c +73 -0
- data/libtest/BoolTest.c +52 -0
- data/libtest/BufferTest.c +52 -0
- data/libtest/ClosureTest.c +173 -0
- data/libtest/EnumTest.c +55 -0
- data/libtest/FunctionTest.c +50 -0
- data/libtest/GNUmakefile +141 -0
- data/libtest/GlobalVariable.c +56 -0
- data/libtest/LastErrorTest.c +41 -0
- data/libtest/NumberTest.c +145 -0
- data/libtest/PointerTest.c +84 -0
- data/libtest/ReferenceTest.c +44 -0
- data/libtest/StringTest.c +55 -0
- data/libtest/StructTest.c +247 -0
- data/libtest/UnionTest.c +64 -0
- data/libtest/VariadicTest.c +57 -0
- data/spec/ffi/Ffi.iml +12 -0
- data/spec/ffi/struct_spec.rb +20 -2
- metadata +138 -93
- data/README.rdoc +0 -69
data/History.txt
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
== 0.5.0 / 2009-10-06
|
|
2
|
+
|
|
3
|
+
* Major improvements
|
|
4
|
+
* New Function class
|
|
5
|
+
* Structs can be passed and returned by value
|
|
6
|
+
* Implement a custom trampoline for x86_64, resulting in roughly 30% speedup
|
|
7
|
+
* Improve dispatch of functions which take (0..6) char/short/int/long/pointer arguments by between 50% and 200% on x86_64
|
|
8
|
+
* Callbacks are now approximately 100% faster on x86_64
|
|
9
|
+
* Minor improvements
|
|
10
|
+
* Add support for MacOSX Snow Leopard
|
|
11
|
+
* Improve support for Windows releasing fat binaries on rubyforge
|
|
12
|
+
* Better introspection in structs:
|
|
13
|
+
* Add StructLayout::Field#type, size, offset, alignment and name
|
|
14
|
+
methods
|
|
15
|
+
* Add StructLayout#fields which returns an array of
|
|
16
|
+
StructLayout::Field objects
|
|
17
|
+
* Add automagic deducing of library name from module name.
|
|
18
|
+
Idea and prototype implementation from Matt Hulse
|
|
19
|
+
* Callback fields in structs can now be both read and written
|
|
20
|
+
* Add a bunch of new benchmarks
|
|
21
|
+
* Lots of refactoring
|
|
22
|
+
* Experimental features
|
|
23
|
+
* blocking functions (i.e. native code that blocks the thread) support
|
|
24
|
+
* Bug fixes
|
|
25
|
+
* Fix RUBY-FFI_43 (rake gem dependency)
|
|
26
|
+
|
|
27
|
+
== 0.4.0 / 2009-08-05
|
|
28
|
+
|
|
29
|
+
* Major improvements
|
|
30
|
+
* Add support for boolean types
|
|
31
|
+
* Add support for methods as callbacks
|
|
32
|
+
* Add FFI::IO.read as described in JRUBY-3636
|
|
33
|
+
* Minor improvements
|
|
34
|
+
* Add Pointer::NULL constant
|
|
35
|
+
* Add AbstractMemory#get_array_of_string()
|
|
36
|
+
* Implement Pointer.new(address) and Pointer.new(:type, address)
|
|
37
|
+
* Bug fixes
|
|
38
|
+
* Fix RUBY_FFI-38
|
|
39
|
+
* Fix issues related to 1.9.1 build
|
|
40
|
+
* Fix issues related to OSX build
|
|
41
|
+
* Fix issues related to FreeBSD build
|
|
42
|
+
* Fix issues related to OpenSolaris build
|
|
43
|
+
|
|
44
|
+
== 0.3.5 / 2009-05-08
|
|
45
|
+
|
|
46
|
+
* Bug fixes
|
|
47
|
+
* Fix RUBY_FFI-17
|
|
48
|
+
* Fix RUBY_FFI-21
|
|
49
|
+
|
|
50
|
+
== 0.3.4 / 2009-05-01
|
|
51
|
+
|
|
52
|
+
* Minor improvements
|
|
53
|
+
* Add return statements to functions that call rb_raise(), in case
|
|
54
|
+
rb_raise is not declared noreturn, to avoid gcc warnings.
|
|
55
|
+
|
|
56
|
+
== 0.3.3 / 2009-04-27
|
|
57
|
+
|
|
58
|
+
* Minor improvements
|
|
59
|
+
* Implement RUBY_FFI-16 - Add support for anonymous callbacks
|
|
60
|
+
* Add support for callback parameters in callbacks
|
|
61
|
+
* Add support for function pointer return values
|
|
62
|
+
* Callbacks can now coerce proc objects into function pointers for
|
|
63
|
+
return values.
|
|
64
|
+
* Implement FFI::Type and FFI::Type::Builtin
|
|
65
|
+
* Add support for enumerations
|
|
66
|
+
* Bug fixes
|
|
67
|
+
* Fix RUBY_FFI-19
|
|
68
|
+
* Fix RUBY_FFI-15
|
|
69
|
+
|
|
70
|
+
== 0.3.2 / 2009-05-01
|
|
71
|
+
|
|
72
|
+
* Bug fixes
|
|
73
|
+
* Fix JRUBY-3527 by passing RTLD_GLOBAL instead of RTLD_LOCAL
|
|
74
|
+
|
|
75
|
+
== 0.3.1 / 2009-03-23
|
|
76
|
+
|
|
77
|
+
* Bug fixes
|
|
78
|
+
* Correctly save errno/GetLastError after each call.
|
|
79
|
+
|
|
80
|
+
== 0.3.0 / 2009-03-19
|
|
81
|
+
|
|
82
|
+
* Switch compilation to rake-compiler
|
|
83
|
+
* Makes cross-compilation from linux -> win32 super easy
|
|
84
|
+
* win32 support is available now, but highly experimental
|
|
85
|
+
* Performance improvements
|
|
86
|
+
* struct field access approx 3x faster than 0.2.0
|
|
87
|
+
* function invocation approx 20% faster than 0.2.0
|
|
88
|
+
* A bunch of minor improvements
|
|
89
|
+
* Struct instances can now be passed as :pointer parameters without calling
|
|
90
|
+
Struct#pointer
|
|
91
|
+
* Support for array struct members
|
|
92
|
+
* Structs are now padded correctly to the alignment of the struct's
|
|
93
|
+
largest field
|
|
94
|
+
* Global library variables
|
|
95
|
+
* Callbacks in global library variables
|
|
96
|
+
* Strings passed in as :string arguments are scrubbed to avoid
|
|
97
|
+
poison-null-byte attacks.
|
|
98
|
+
* Union support
|
|
99
|
+
* nil can be passed as a :string argument (passed as NULL)
|
|
100
|
+
* Structs can now be fields inside another struct
|
|
101
|
+
* Lots of internal cleanups and refactorings.
|
|
102
|
+
|
data/README.md
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# ruby-ffi http://wiki.github.com/ffi/ffi [](https://travis-ci.org/ffi/ffi)
|
|
2
|
+
|
|
3
|
+
## Description
|
|
4
|
+
|
|
5
|
+
Ruby-FFI is a ruby extension for programmatically loading dynamic
|
|
6
|
+
libraries, binding functions within them, and calling those functions
|
|
7
|
+
from Ruby code. Moreover, a Ruby-FFI extension works without changes
|
|
8
|
+
on Ruby and JRuby. Discover why should you write your next extension
|
|
9
|
+
using Ruby-FFI [here](http://wiki.github.com/ffi/ffi/why-use-ffi).
|
|
10
|
+
|
|
11
|
+
## Features/problems
|
|
12
|
+
|
|
13
|
+
* Intuitive DSL
|
|
14
|
+
* Supports all C native types
|
|
15
|
+
* C structs (also nested), enums and global variables
|
|
16
|
+
* Callbacks from C to ruby
|
|
17
|
+
* Automatic garbage collection of native memory
|
|
18
|
+
|
|
19
|
+
## Synopsis
|
|
20
|
+
|
|
21
|
+
```ruby
|
|
22
|
+
require 'ffi'
|
|
23
|
+
|
|
24
|
+
module MyLib
|
|
25
|
+
extend FFI::Library
|
|
26
|
+
ffi_lib 'c'
|
|
27
|
+
attach_function :puts, [ :string ], :int
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
MyLib.puts 'Hello, World using libc!'
|
|
31
|
+
```
|
|
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
|
+
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
|
|
45
|
+
|
|
46
|
+
## Installation
|
|
47
|
+
|
|
48
|
+
From rubygems:
|
|
49
|
+
|
|
50
|
+
[sudo] gem install ffi
|
|
51
|
+
|
|
52
|
+
or from the git repository on github:
|
|
53
|
+
|
|
54
|
+
git clone git://github.com/ffi/ffi.git
|
|
55
|
+
cd ffi
|
|
56
|
+
rake gem:install
|
|
57
|
+
|
|
58
|
+
## License
|
|
59
|
+
|
|
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.
|
|
63
|
+
|
|
64
|
+
## Credits
|
|
65
|
+
|
|
66
|
+
The following people have submitted code, bug reports, or otherwide contributed to the success of this project:
|
|
67
|
+
|
|
68
|
+
* Alban Peignier <alban.peignier@free.fr>
|
|
69
|
+
* Aman Gupta <aman@tmm1.net>
|
|
70
|
+
* Andrea Fazzi <andrea.fazzi@alcacoop.it>
|
|
71
|
+
* Andreas Niederl <rico32@gmx.net>
|
|
72
|
+
* Andrew Cholakian <andrew@andrewvc.com>
|
|
73
|
+
* Antonio Terceiro <terceiro@softwarelivre.org>
|
|
74
|
+
* Brian Candler <B.Candler@pobox.com>
|
|
75
|
+
* Brian D. Burns <burns180@gmail.com>
|
|
76
|
+
* Bryan Kearney <bkearney@redhat.com>
|
|
77
|
+
* Charlie Savage <cfis@zerista.com>
|
|
78
|
+
* Chikanaga Tomoyuki <nagachika00@gmail.com>
|
|
79
|
+
* Hongli Lai <hongli@phusion.nl>
|
|
80
|
+
* Ian MacLeod <ian@nevir.net>
|
|
81
|
+
* Jake Douglas <jake@shiftedlabs.com>
|
|
82
|
+
* Jean-Dominique Morani <jdmorani@mac.com>
|
|
83
|
+
* Jeremy Hinegardner <jeremy@hinegardner.org>
|
|
84
|
+
* Jesús García Sáez <blaxter@gmail.com>
|
|
85
|
+
* Joe Khoobyar <joe@ankhcraft.com>
|
|
86
|
+
* Jurij Smakov <jurij@wooyd.org>
|
|
87
|
+
* KISHIMOTO, Makoto <ksmakoto@dd.iij4u.or.jp>
|
|
88
|
+
* Kim Burgestrand <kim@burgestrand.se>
|
|
89
|
+
* Lars Kanis <kanis@comcard.de>
|
|
90
|
+
* Luc Heinrich <luc@honk-honk.com>
|
|
91
|
+
* Luis Lavena <luislavena@gmail.com>
|
|
92
|
+
* Matijs van Zuijlen <matijs@matijs.net>
|
|
93
|
+
* Matthew King <automatthew@gmail.com>
|
|
94
|
+
* Mike Dalessio <mike.dalessio@gmail.com>
|
|
95
|
+
* NARUSE, Yui <naruse@airemix.jp>
|
|
96
|
+
* Park Heesob <phasis@gmail.com>
|
|
97
|
+
* Shin Yee <shinyee@speedgocomputing.com>
|
|
98
|
+
* Stephen Bannasch <stephen.bannasch@gmail.com>
|
|
99
|
+
* Suraj N. Kurapati <sunaku@gmail.com>
|
|
100
|
+
* Sylvain Daubert <sylvain.daubert@laposte.net>
|
|
101
|
+
* Victor Costan
|
|
102
|
+
* beoran@gmail.com
|
|
103
|
+
* ctide <christide@christide.com>
|
|
104
|
+
* emboss <Martin.Bosslet@googlemail.com>
|
|
105
|
+
* hobophobe <unusualtears@gmail.com>
|
|
106
|
+
* meh <meh@paranoici.org>
|
|
107
|
+
* postmodern <postmodern.mod3@gmail.com>
|
|
108
|
+
* wycats@gmail.com <wycats@gmail.com>
|
|
109
|
+
* Wayne Meissner <wmeissner@gmail.com>
|
data/Rakefile
CHANGED
|
@@ -1,32 +1,31 @@
|
|
|
1
1
|
require 'rubygems'
|
|
2
|
+
require 'rubygems/package_task'
|
|
2
3
|
require 'rbconfig'
|
|
3
4
|
|
|
4
5
|
USE_RAKE_COMPILER = (RUBY_PLATFORM =~ /java/) ? false : true
|
|
5
6
|
if USE_RAKE_COMPILER
|
|
6
7
|
gem 'rake-compiler', '>=0.6.0'
|
|
7
8
|
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'
|
|
16
15
|
|
|
17
|
-
LIBEXT = case
|
|
16
|
+
LIBEXT = case RbConfig::CONFIG['host_os'].downcase
|
|
18
17
|
when /darwin/
|
|
19
18
|
"dylib"
|
|
20
19
|
when /mswin|mingw/
|
|
21
20
|
"dll"
|
|
22
21
|
else
|
|
23
|
-
|
|
22
|
+
RbConfig::CONFIG['DLEXT']
|
|
24
23
|
end
|
|
25
24
|
|
|
26
|
-
CPU = case
|
|
25
|
+
CPU = case RbConfig::CONFIG['host_cpu'].downcase
|
|
27
26
|
when /i[3456]86/
|
|
28
27
|
# Darwin always reports i686, even when running in 64bit mode
|
|
29
|
-
if
|
|
28
|
+
if RbConfig::CONFIG['host_os'] =~ /darwin/ && 0xfee1deadbeef.is_a?(Fixnum)
|
|
30
29
|
"x86_64"
|
|
31
30
|
else
|
|
32
31
|
"i386"
|
|
@@ -41,11 +40,14 @@ CPU = case Config::CONFIG['host_cpu'].downcase
|
|
|
41
40
|
when /ppc|powerpc/
|
|
42
41
|
"powerpc"
|
|
43
42
|
|
|
43
|
+
when /^arm/
|
|
44
|
+
"arm"
|
|
45
|
+
|
|
44
46
|
else
|
|
45
|
-
|
|
47
|
+
RbConfig::CONFIG['host_cpu']
|
|
46
48
|
end
|
|
47
49
|
|
|
48
|
-
OS = case
|
|
50
|
+
OS = case RbConfig::CONFIG['host_os'].downcase
|
|
49
51
|
when /linux/
|
|
50
52
|
"linux"
|
|
51
53
|
when /darwin/
|
|
@@ -59,78 +61,48 @@ OS = case Config::CONFIG['host_os'].downcase
|
|
|
59
61
|
when /mswin|mingw/
|
|
60
62
|
"win32"
|
|
61
63
|
else
|
|
62
|
-
|
|
64
|
+
RbConfig::CONFIG['host_os'].downcase
|
|
63
65
|
end
|
|
64
66
|
|
|
65
|
-
CC=ENV['CC'] ||
|
|
67
|
+
CC = ENV['CC'] || RbConfig::CONFIG['CC'] || "gcc"
|
|
66
68
|
|
|
67
|
-
GMAKE =
|
|
69
|
+
GMAKE = system('which gmake >/dev/null') && 'gmake' || 'make'
|
|
68
70
|
|
|
69
71
|
LIBTEST = "build/libtest.#{LIBEXT}"
|
|
70
72
|
BUILD_DIR = "build"
|
|
71
|
-
BUILD_EXT_DIR = File.join(BUILD_DIR, "#{
|
|
72
|
-
|
|
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 = '0.6.0'
|
|
79
|
-
PROJ.rubyforge.name = 'ffi'
|
|
80
|
-
PROJ.readme_file = 'README.rdoc'
|
|
81
|
-
|
|
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(LICENSE README.rdoc Rakefile) + Dir.glob("{ext,gen,lib,spec}/**/*")
|
|
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"
|
|
73
|
+
BUILD_EXT_DIR = File.join(BUILD_DIR, "#{RbConfig::CONFIG['arch']}", 'ffi_c', RUBY_VERSION)
|
|
104
74
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
# Dependencies
|
|
75
|
+
def gem_spec
|
|
76
|
+
@gem_spec ||= Gem::Specification.load('ffi.gemspec')
|
|
77
|
+
end
|
|
110
78
|
|
|
111
|
-
|
|
79
|
+
Gem::PackageTask.new(gem_spec) do |pkg|
|
|
80
|
+
pkg.need_zip = true
|
|
81
|
+
pkg.need_tar = true
|
|
82
|
+
pkg.package_dir = 'pkg'
|
|
83
|
+
end
|
|
112
84
|
|
|
113
85
|
TEST_DEPS = [ LIBTEST ]
|
|
114
86
|
if RUBY_PLATFORM == "java"
|
|
115
87
|
desc "Run all specs"
|
|
116
88
|
task :specs => TEST_DEPS do
|
|
117
|
-
sh %{#{Gem.ruby} -S
|
|
89
|
+
sh %{#{Gem.ruby} -w -S rspec #{Dir["spec/ffi/*_spec.rb"].join(" ")} -fs --color}
|
|
118
90
|
end
|
|
119
91
|
desc "Run rubinius specs"
|
|
120
92
|
task :rbxspecs => TEST_DEPS do
|
|
121
|
-
sh %{#{Gem.ruby} -S
|
|
93
|
+
sh %{#{Gem.ruby} -w -S rspec #{Dir["spec/ffi/rbx/*_spec.rb"].join(" ")} -fs --color}
|
|
122
94
|
end
|
|
123
95
|
else
|
|
124
96
|
TEST_DEPS.unshift :compile
|
|
125
97
|
desc "Run all specs"
|
|
126
98
|
task :specs => TEST_DEPS do
|
|
127
99
|
ENV["MRI_FFI"] = "1"
|
|
128
|
-
sh %{#{Gem.ruby} -Ilib -I#{BUILD_EXT_DIR} -S
|
|
100
|
+
sh %{#{Gem.ruby} -w -Ilib -I#{BUILD_EXT_DIR} -S rspec #{Dir["spec/ffi/*_spec.rb"].join(" ")} -fs --color}
|
|
129
101
|
end
|
|
130
102
|
desc "Run rubinius specs"
|
|
131
103
|
task :rbxspecs => TEST_DEPS do
|
|
132
104
|
ENV["MRI_FFI"] = "1"
|
|
133
|
-
sh %{#{Gem.ruby} -Ilib -I#{BUILD_EXT_DIR} -S
|
|
105
|
+
sh %{#{Gem.ruby} -w -Ilib -I#{BUILD_EXT_DIR} -S rspec #{Dir["spec/ffi/rbx/*_spec.rb"].join(" ")} -fs --color}
|
|
134
106
|
end
|
|
135
107
|
end
|
|
136
108
|
|
|
@@ -140,20 +112,26 @@ task :package => 'gem:package'
|
|
|
140
112
|
desc "Install the gem locally"
|
|
141
113
|
task :install => 'gem:install'
|
|
142
114
|
|
|
115
|
+
namespace :gem do
|
|
116
|
+
task :install => :gem do
|
|
117
|
+
ruby %{ -S gem install pkg/ffi-#{gem_spec.version}.gem }
|
|
118
|
+
end
|
|
119
|
+
end
|
|
143
120
|
|
|
144
121
|
desc "Clean all built files"
|
|
145
122
|
task :distclean => :clobber do
|
|
146
123
|
FileUtils.rm_rf('build')
|
|
147
|
-
FileUtils.rm_rf(Dir["lib/**/ffi_c.#{
|
|
124
|
+
FileUtils.rm_rf(Dir["lib/**/ffi_c.#{RbConfig::CONFIG['DLEXT']}"])
|
|
148
125
|
FileUtils.rm_rf('lib/1.8')
|
|
149
126
|
FileUtils.rm_rf('lib/1.9')
|
|
127
|
+
FileUtils.rm_rf('lib/ffi/types.conf')
|
|
150
128
|
FileUtils.rm_rf('conftest.dSYM')
|
|
151
129
|
FileUtils.rm_rf('pkg')
|
|
152
130
|
end
|
|
153
131
|
|
|
154
132
|
|
|
155
133
|
desc "Build the native test lib"
|
|
156
|
-
|
|
134
|
+
file "build/libtest.#{LIBEXT}" => FileList['libtest/**/*.[ch]'] do
|
|
157
135
|
sh %{#{GMAKE} -f libtest/GNUmakefile CPU=#{CPU} OS=#{OS} }
|
|
158
136
|
end
|
|
159
137
|
|
|
@@ -186,3 +164,54 @@ task 'spec:specdoc' => TEST_DEPS
|
|
|
186
164
|
|
|
187
165
|
task :default => :specs
|
|
188
166
|
|
|
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/Call.c
CHANGED
|
@@ -142,10 +142,10 @@ rbffi_SetupCallParams(int argc, VALUE* argv, int paramCount, NativeType* paramTy
|
|
|
142
142
|
|
|
143
143
|
case NATIVE_BOOL:
|
|
144
144
|
if (type != T_TRUE && type != T_FALSE) {
|
|
145
|
-
rb_raise(rb_eTypeError, "
|
|
145
|
+
rb_raise(rb_eTypeError, "wrong argument type (expected a boolean parameter)");
|
|
146
146
|
}
|
|
147
|
-
param->
|
|
148
|
-
ADJ(param,
|
|
147
|
+
param->s8 = argv[argidx++] == Qtrue;
|
|
148
|
+
ADJ(param, INT8);
|
|
149
149
|
break;
|
|
150
150
|
|
|
151
151
|
|
data/ext/ffi_c/Ffi_c.iml
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<module type="RUBY_MODULE" version="4">
|
|
3
|
+
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
|
4
|
+
<exclude-output />
|
|
5
|
+
<content url="file://$MODULE_DIR$">
|
|
6
|
+
<sourceFolder url="file://$MODULE_DIR$" isTestSource="false" />
|
|
7
|
+
</content>
|
|
8
|
+
<orderEntry type="inheritedJdk" />
|
|
9
|
+
<orderEntry type="sourceFolder" forTests="false" />
|
|
10
|
+
</component>
|
|
11
|
+
</module>
|
|
12
|
+
|
data/ext/ffi_c/Function.c
CHANGED
|
@@ -374,7 +374,7 @@ callback_invoke(ffi_cif* cif, void* retval, void** parameters, void* user_data)
|
|
|
374
374
|
param = rbffi_Pointer_NewInstance(*(void **) parameters[i]);
|
|
375
375
|
break;
|
|
376
376
|
case NATIVE_BOOL:
|
|
377
|
-
param = (*(
|
|
377
|
+
param = (*(uint8_t *) parameters[i]) ? Qtrue : Qfalse;
|
|
378
378
|
break;
|
|
379
379
|
|
|
380
380
|
case NATIVE_FUNCTION:
|
|
@@ -428,8 +428,9 @@ callback_invoke(ffi_cif* cif, void* retval, void** parameters, void* user_data)
|
|
|
428
428
|
*((void **) retval) = NULL;
|
|
429
429
|
}
|
|
430
430
|
break;
|
|
431
|
+
|
|
431
432
|
case NATIVE_BOOL:
|
|
432
|
-
*((
|
|
433
|
+
*((ffi_arg *) retval) = rbReturnValue == Qtrue;
|
|
433
434
|
break;
|
|
434
435
|
|
|
435
436
|
case NATIVE_FUNCTION:
|
data/ext/ffi_c/Struct.c
CHANGED
|
@@ -71,6 +71,8 @@ typedef struct InlineArray_ {
|
|
|
71
71
|
static void struct_mark(Struct *);
|
|
72
72
|
static void struct_layout_builder_mark(StructLayoutBuilder *);
|
|
73
73
|
static void struct_layout_builder_free(StructLayoutBuilder *);
|
|
74
|
+
static VALUE struct_class_layout(VALUE klass);
|
|
75
|
+
static void struct_malloc(Struct* s);
|
|
74
76
|
static void inline_array_mark(InlineArray *);
|
|
75
77
|
|
|
76
78
|
static inline int align(int offset, int align);
|
|
@@ -116,10 +118,8 @@ struct_initialize(int argc, VALUE* argv, VALUE self)
|
|
|
116
118
|
/* Call up into ruby code to adjust the layout */
|
|
117
119
|
if (nargs > 1) {
|
|
118
120
|
s->rbLayout = rb_funcall2(CLASS_OF(self), id_layout, RARRAY_LEN(rest), RARRAY_PTR(rest));
|
|
119
|
-
} else if (rb_cvar_defined(klass, id_layout_ivar)) {
|
|
120
|
-
s->rbLayout = rb_cvar_get(klass, id_layout_ivar);
|
|
121
121
|
} else {
|
|
122
|
-
|
|
122
|
+
s->rbLayout = struct_class_layout(klass);
|
|
123
123
|
}
|
|
124
124
|
|
|
125
125
|
if (!rb_obj_is_kind_of(s->rbLayout, rbffi_StructLayoutClass)) {
|
|
@@ -132,13 +132,74 @@ struct_initialize(int argc, VALUE* argv, VALUE self)
|
|
|
132
132
|
s->pointer = MEMORY(rbPointer);
|
|
133
133
|
s->rbPointer = rbPointer;
|
|
134
134
|
} else {
|
|
135
|
-
|
|
136
|
-
s->pointer = (AbstractMemory *) DATA_PTR(s->rbPointer);
|
|
135
|
+
struct_malloc(s);
|
|
137
136
|
}
|
|
138
137
|
|
|
139
138
|
return self;
|
|
140
139
|
}
|
|
141
140
|
|
|
141
|
+
static VALUE
|
|
142
|
+
struct_class_layout(VALUE klass)
|
|
143
|
+
{
|
|
144
|
+
VALUE layout;
|
|
145
|
+
if (!rb_cvar_defined(klass, id_layout_ivar)) {
|
|
146
|
+
rb_raise(rb_eRuntimeError, "no Struct layout configured for %s", rb_class2name(klass));
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
layout = rb_cvar_get(klass, id_layout_ivar);
|
|
150
|
+
if (!rb_obj_is_kind_of(layout, rbffi_StructLayoutClass)) {
|
|
151
|
+
rb_raise(rb_eRuntimeError, "invalid Struct layout for %s", rb_class2name(klass));
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return layout;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
static StructLayout*
|
|
158
|
+
struct_layout(VALUE self)
|
|
159
|
+
{
|
|
160
|
+
Struct* s = (Struct *) DATA_PTR(self);
|
|
161
|
+
if (s->layout != NULL) {
|
|
162
|
+
return s->layout;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (s->layout == NULL) {
|
|
166
|
+
s->rbLayout = struct_class_layout(CLASS_OF(self));
|
|
167
|
+
Data_Get_Struct(s->rbLayout, StructLayout, s->layout);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return s->layout;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
static Struct*
|
|
174
|
+
struct_validate(VALUE self)
|
|
175
|
+
{
|
|
176
|
+
Struct* s;
|
|
177
|
+
Data_Get_Struct(self, Struct, s);
|
|
178
|
+
|
|
179
|
+
if (struct_layout(self) == NULL) {
|
|
180
|
+
rb_raise(rb_eRuntimeError, "struct layout == null");
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
if (s->pointer == NULL) {
|
|
184
|
+
struct_malloc(s);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
return s;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
static void
|
|
191
|
+
struct_malloc(Struct* s)
|
|
192
|
+
{
|
|
193
|
+
if (s->rbPointer == Qnil) {
|
|
194
|
+
s->rbPointer = rbffi_MemoryPointer_NewInstance(s->layout->size, 1, true);
|
|
195
|
+
|
|
196
|
+
} else if (!rb_obj_is_kind_of(s->rbPointer, rbffi_AbstractMemoryClass)) {
|
|
197
|
+
rb_raise(rb_eRuntimeError, "invalid pointer in struct");
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
s->pointer = (AbstractMemory *) DATA_PTR(s->rbPointer);
|
|
201
|
+
}
|
|
202
|
+
|
|
142
203
|
static void
|
|
143
204
|
struct_mark(Struct *s)
|
|
144
205
|
{
|
|
@@ -151,9 +212,6 @@ struct_field(Struct* s, VALUE fieldName)
|
|
|
151
212
|
{
|
|
152
213
|
StructLayout* layout = s->layout;
|
|
153
214
|
VALUE rbField;
|
|
154
|
-
if (layout == NULL) {
|
|
155
|
-
rb_raise(rb_eRuntimeError, "layout not set for Struct");
|
|
156
|
-
}
|
|
157
215
|
|
|
158
216
|
rbField = rb_hash_aref(layout->rbFieldMap, fieldName);
|
|
159
217
|
if (rbField == Qnil) {
|
|
@@ -170,8 +228,9 @@ struct_aref(VALUE self, VALUE fieldName)
|
|
|
170
228
|
Struct* s;
|
|
171
229
|
VALUE rbField;
|
|
172
230
|
StructField* f;
|
|
173
|
-
|
|
174
|
-
|
|
231
|
+
|
|
232
|
+
s = struct_validate(self);
|
|
233
|
+
|
|
175
234
|
rbField = struct_field(s, fieldName);
|
|
176
235
|
f = (StructField *) DATA_PTR(rbField);
|
|
177
236
|
|
|
@@ -196,7 +255,8 @@ struct_aset(VALUE self, VALUE fieldName, VALUE value)
|
|
|
196
255
|
StructField* f;
|
|
197
256
|
|
|
198
257
|
|
|
199
|
-
|
|
258
|
+
s = struct_validate(self);
|
|
259
|
+
|
|
200
260
|
rbField = struct_field(s, fieldName);
|
|
201
261
|
f = (StructField *) DATA_PTR(rbField);
|
|
202
262
|
if (f->put != NULL) {
|
|
@@ -221,12 +281,25 @@ static VALUE
|
|
|
221
281
|
struct_set_pointer(VALUE self, VALUE pointer)
|
|
222
282
|
{
|
|
223
283
|
Struct* s;
|
|
284
|
+
StructLayout* layout;
|
|
285
|
+
AbstractMemory* memory;
|
|
224
286
|
|
|
225
287
|
if (!rb_obj_is_kind_of(pointer, rbffi_AbstractMemoryClass)) {
|
|
226
|
-
rb_raise(
|
|
288
|
+
rb_raise(rb_eTypeError, "wrong argument type %s (expected Pointer or Buffer)",
|
|
289
|
+
rb_obj_classname(pointer));
|
|
290
|
+
return Qnil;
|
|
227
291
|
}
|
|
228
292
|
|
|
293
|
+
|
|
229
294
|
Data_Get_Struct(self, Struct, s);
|
|
295
|
+
Data_Get_Struct(pointer, AbstractMemory, memory);
|
|
296
|
+
layout = struct_layout(self);
|
|
297
|
+
|
|
298
|
+
if (layout->base.ffiType->size > memory->size) {
|
|
299
|
+
rb_raise(rb_eArgError, "memory of %d bytes too small for struct %s (expected at least %d)",
|
|
300
|
+
memory->size, rb_obj_classname(self), layout->base.ffiType->size);
|
|
301
|
+
}
|
|
302
|
+
|
|
230
303
|
s->pointer = MEMORY(pointer);
|
|
231
304
|
s->rbPointer = pointer;
|
|
232
305
|
rb_ivar_set(self, id_pointer_ivar, pointer);
|
|
@@ -251,7 +324,9 @@ struct_set_layout(VALUE self, VALUE layout)
|
|
|
251
324
|
Data_Get_Struct(self, Struct, s);
|
|
252
325
|
|
|
253
326
|
if (!rb_obj_is_kind_of(layout, rbffi_StructLayoutClass)) {
|
|
254
|
-
rb_raise(
|
|
327
|
+
rb_raise(rb_eTypeError, "wrong argument type %s (expected %s)",
|
|
328
|
+
rb_obj_classname(layout), rb_class2name(rbffi_StructLayoutClass));
|
|
329
|
+
return Qnil;
|
|
255
330
|
}
|
|
256
331
|
|
|
257
332
|
Data_Get_Struct(layout, StructLayout, s->layout);
|
data/ext/ffi_c/StructLayout.c
CHANGED
|
@@ -360,7 +360,8 @@ struct_layout_initialize(VALUE self, VALUE field_names, VALUE fields, VALUE size
|
|
|
360
360
|
rb_raise(rb_eTypeError, "wrong type for field %d.", i);
|
|
361
361
|
}
|
|
362
362
|
|
|
363
|
-
|
|
363
|
+
field = layout->fields[i];
|
|
364
|
+
Data_Get_Struct(rbField, StructField, field);
|
|
364
365
|
|
|
365
366
|
if (field->type == NULL || field->type->ffiType == NULL) {
|
|
366
367
|
rb_raise(rb_eRuntimeError, "type of field %d not supported", i);
|
data/ext/ffi_c/Types.c
CHANGED
|
@@ -76,7 +76,7 @@ rbffi_NativeValue_ToRuby(Type* type, VALUE rbType, const void* ptr, VALUE enums)
|
|
|
76
76
|
case NATIVE_POINTER:
|
|
77
77
|
return rbffi_Pointer_NewInstance(*(void **) ptr);
|
|
78
78
|
case NATIVE_BOOL:
|
|
79
|
-
return ((
|
|
79
|
+
return ((unsigned char) *(ffi_arg *) ptr) ? Qtrue : Qfalse;
|
|
80
80
|
case NATIVE_ENUM:
|
|
81
81
|
return rb_funcall(rbType, id_find, 1, INT2NUM((unsigned int) *(ffi_arg *) ptr));
|
|
82
82
|
|
data/ext/ffi_c/libffi/configure
CHANGED
|
@@ -9021,7 +9021,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
|
|
|
9021
9021
|
old_archive_from_new_cmds='true'
|
|
9022
9022
|
# FIXME: Should let the user specify the lib program.
|
|
9023
9023
|
old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs'
|
|
9024
|
-
fix_srcfile_path='`cygpath -w "$srcfile"`'
|
|
9024
|
+
# fix_srcfile_path='`cygpath -w "$srcfile"`'
|
|
9025
9025
|
enable_shared_with_static_runtimes=yes
|
|
9026
9026
|
;;
|
|
9027
9027
|
|