ffi 1.15.5-x64-mingw-ucrt → 1.16.0-x64-mingw-ucrt

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 36a218e970f5a550202d0423024605d6253164ea15c3b5abaa75cb998c20579c
4
- data.tar.gz: 858d0ef9099b6d311dde34bf49968840f53e3b8b04cc9d89d1a0fd3c696a7267
3
+ metadata.gz: 6be6d426dd4c7a4cb5830dcfb8d338d3680166d34e3db1414866d08a2ea1e8e6
4
+ data.tar.gz: 9ec420e8785e8541fd55f484c104be8f58c55f64749cbfcd4f89305e6922a21e
5
5
  SHA512:
6
- metadata.gz: 547e6f97d52e5a0d6b9581fa43d0cb0947f95a22758e041dc622baddbda7ac8f9d27c4e9eb16722a2d6eea6ac99996565385ad1fb6899a16262cfc9a9fedff8e
7
- data.tar.gz: 2e3a028c0d658c86889e18f4a081354a98b42cc2cebd2db82deea2cd6eb01fe69551bd3e1abd2480866225114c2bf77754bc6dd7320e7d1e3b64bc60ff16650e
6
+ metadata.gz: 4c3a88ee0d781baa72703011e1e2ef3abb7162da123b2cbdaeba4ce9d8ac2bb85389cf83d04a847c506c7cf110757f3b629fb1a5bf55f4323183630b316993a5
7
+ data.tar.gz: db0a7d3fcf2c0dd5929f1465944a2c7f3a4e97c884f5f47415faec11f3e66af391c790e20662c726b00146ffdade577d9cc62146e66a1c37ddf99b9aa57c0ccd
data/CHANGELOG.md CHANGED
@@ -1,3 +1,57 @@
1
+ 1.16.0 / 2023-09-23
2
+ -------------------
3
+
4
+ Fixed:
5
+ * Fix an issue with signed bitmasks when using flags on the most significant bit. #949
6
+ * Fix FFI::Pointer#initialize using NUM2LL instead of NUM2ULL.
7
+ * Fix FFI::Type#inspect to properly display the constant name. #1002
8
+ * Use libffi closure allocations on hppa-Linux. #1017
9
+ Previously they would segfault.
10
+ * Fix class name of Symbol#inspect.
11
+ * Fix MSVC support of libtest. #1028
12
+ * Fix attach_function of functions ending in ? or ! #971
13
+
14
+ Added:
15
+ * Convert all C-based classes to TypedData and use write barriers. #994, #995, #996, #997, #998, #999, #1000, #1001, #1003, #1004, #1005, #1006, #1007, #1008, #1009, #1010, #1011, #1012
16
+ This results in less pressure on the garbage collector, since the objects can be promoted to the old generation, which means they only get marked on major GC.
17
+ * Implement `ObjectSpace.memsize_of()` of all C-based classes.
18
+ * Make FFI Ractor compatible. #1023
19
+ Modules extended per `extend FFI::Library` need to be frozen in order to be used by non-main Ractors.
20
+ This can be done by calling `freeze` below of all C interface definitions.
21
+ * In a Ractor it's possible to:
22
+ * load DLLs and call its functions, access its global variables
23
+ * use builtin typedefs
24
+ * use and modify ractor local typedefs
25
+ * define callbacks
26
+ * receive async callbacks from non-ruby threads
27
+ * use frozen FFI::Library based modules with all attributes (enums, structs, typedefs, functions, callbacks)
28
+ * invoke frozen functions and callbacks defined in the main Ractor
29
+ * use FFI::Struct definitions from the main Ractor
30
+ * In a Ractor it's impossible to:
31
+ * create new FFI::Library based modules
32
+ * create new FFI::Struct definitions
33
+ * use custom global typedefs
34
+ * use non-frozen FFI::Library based modules
35
+ * Allow type retrieval of attached functions+variables. #1023
36
+ * Make FFI classes `GC.compact` friendly. #1021
37
+ * Update libffi and disable custom trampoline when using libffi closure allocation. #1020
38
+ This is because libffi changed the way how closures are allocated to static trampolines.
39
+ * Add types.conf for loongarch64-linux. #943
40
+ * Add types.conf for sw_64-linux (Shen Wei 64-bit, based on Alpha). #1018
41
+ * Add support for aarch64-windows. #1035
42
+ * Windows: Update LoadLibrary error message to include error code. #1026
43
+ * Allow private release method for FFI::ManagedStruct and FFI::AutoPointer. #1029
44
+ * Add support for passing ABI version to FFI.map_library_name. #963
45
+ This adds the new class FFI::LibraryPath .
46
+ * Add support for ruby-3.2 to windows binary gem. #1047
47
+ * Enable debug symbols for `rake compile` builds to ease debugging. #1048
48
+
49
+ Removed:
50
+ * Remove allocator of AbstractMemory. #1013
51
+ This disables AbstractMemory.new, which has no practical use.
52
+ * Remove unused FFI::SizeTypes. #1022
53
+
54
+
1
55
  1.15.5 / 2022-01-10
2
56
  -------------------
3
57
 
data/Gemfile CHANGED
@@ -2,7 +2,7 @@ source 'https://rubygems.org'
2
2
 
3
3
  group :development do
4
4
  gem 'rake', '~> 13.0'
5
- gem 'rake-compiler', '~> 1.0.3'
5
+ gem 'rake-compiler', '~> 1.1'
6
6
  gem 'rake-compiler-dock', '~> 1.0'
7
7
  gem 'rspec', '~> 3.0'
8
8
  gem 'bundler', '>= 1.16', '< 3'
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Ruby-FFI https://github.com/ffi/ffi/wiki [![Build Status](https://travis-ci.com/ffi/ffi.svg?branch=master)](https://travis-ci.com/ffi/ffi) [![Build status Windows](https://ci.appveyor.com/api/projects/status/r8wxn1sd4s794gg1/branch/master?svg=true)](https://ci.appveyor.com/project/larskanis/ffi-aofqa/branch/master)
1
+ # Ruby-FFI https://github.com/ffi/ffi/wiki
2
2
 
3
3
  ## Description
4
4
 
@@ -15,6 +15,7 @@ using Ruby-FFI](https://github.com/ffi/ffi/wiki/why-use-ffi).
15
15
  * C structs (also nested), enums and global variables
16
16
  * Callbacks from C to Ruby
17
17
  * Automatic garbage collection of native memory
18
+ * Usable in Ractor
18
19
 
19
20
  ## Synopsis
20
21
 
@@ -62,7 +63,7 @@ On JRuby and TruffleRuby, there are no requirements to install the FFI gem, and
62
63
  From rubygems:
63
64
 
64
65
  [sudo] gem install ffi
65
-
66
+
66
67
  From a Gemfile using git or GitHub
67
68
 
68
69
  gem 'ffi', github: 'ffi/ffi', submodules: true
data/Rakefile CHANGED
@@ -1,7 +1,7 @@
1
1
  require 'rbconfig'
2
2
  require 'date'
3
3
  require 'fileutils'
4
- require 'rbconfig'
4
+ require 'yaml'
5
5
  require 'rspec/core/rake_task'
6
6
  require 'rubygems/package_task'
7
7
  require 'rake/extensiontask'
@@ -30,9 +30,8 @@ CLEAN.include 'spec/ffi/fixtures/libtest.{dylib,so,dll}'
30
30
  CLEAN.include 'spec/ffi/fixtures/*.o'
31
31
  CLEAN.include 'spec/ffi/embed-test/ext/*.{o,def}'
32
32
  CLEAN.include 'spec/ffi/embed-test/ext/Makefile'
33
- CLEAN.include "pkg/ffi-*-{mingw32,java}"
34
- CLEAN.include 'lib/1.*'
35
- CLEAN.include 'lib/2.*'
33
+ CLEAN.include "pkg/ffi-*-*/"
34
+ CLEAN.include 'lib/{2,3}.*'
36
35
 
37
36
  # clean all shipped files, that are not in git
38
37
  CLEAN.include(
@@ -87,6 +86,8 @@ task 'gem:java' => 'java:gem'
87
86
  FfiGemHelper.install_tasks
88
87
  # Register windows gems to be pushed to rubygems.org
89
88
  Bundler::GemHelper.instance.cross_platforms = %w[x86-mingw32 x64-mingw-ucrt x64-mingw32]
89
+ # These platforms are not yet enabled, since there are issues on musl-based distors (alpine-linux):
90
+ # + %w[x86-linux x86_64-linux arm-linux aarch64-linux x86_64-darwin arm64-darwin]
90
91
 
91
92
  if RUBY_ENGINE == 'ruby' || RUBY_ENGINE == 'rbx'
92
93
  require 'rake/extensiontask'
@@ -99,6 +100,8 @@ if RUBY_ENGINE == 'ruby' || RUBY_ENGINE == 'rbx'
99
100
  ext.cross_compiling do |spec|
100
101
  spec.files.reject! { |path| File.fnmatch?('ext/*', path) }
101
102
  end
103
+ # Enable debug info for 'rake compile' but not for 'gem install'
104
+ ext.config_options << "--enable-debug"
102
105
 
103
106
  end
104
107
  else
@@ -121,9 +124,9 @@ namespace "gem" do
121
124
  desc "Build the native gem for #{plat}"
122
125
  task plat => ['prepare', 'build'] do
123
126
  RakeCompilerDock.sh <<-EOT, platform: plat
124
- sudo apt-get update &&
125
- sudo apt-get install -y libltdl-dev && bundle --local &&
126
- rake cross native gem MAKE='nice make -j`nproc`' RUBY_CC_VERSION=${RUBY_CC_VERSION/:2.2.2/}
127
+ #{ "sudo apt-get update && sudo apt-get install -y libltdl-dev &&" if plat !~ /linux/ }
128
+ bundle --local &&
129
+ rake native:#{plat} pkg/#{gem_spec.full_name}-#{plat}.gem MAKE='nice make -j`nproc`' RUBY_CC_VERSION=${RUBY_CC_VERSION/:2.4.0/}
127
130
  EOT
128
131
  end
129
132
  end
data/ffi.gemspec CHANGED
@@ -34,9 +34,9 @@ Gem::Specification.new do |s|
34
34
  s.rdoc_options = %w[--exclude=ext/ffi_c/.*\.o$ --exclude=ffi_c\.(bundle|so)$]
35
35
  s.license = 'BSD-3-Clause'
36
36
  s.require_paths << 'ext/ffi_c'
37
- s.required_ruby_version = '>= 2.3'
37
+ s.required_ruby_version = '>= 2.5'
38
38
  s.add_development_dependency 'rake', '~> 13.0'
39
- s.add_development_dependency 'rake-compiler', '~> 1.0'
39
+ s.add_development_dependency 'rake-compiler', '~> 1.1'
40
40
  s.add_development_dependency 'rake-compiler-dock', '~> 1.0'
41
41
  s.add_development_dependency 'rspec', '~> 2.14.1'
42
42
  end
data/lib/3.1/ffi_c.so CHANGED
Binary file
data/lib/3.2/ffi_c.so ADDED
Binary file
@@ -76,21 +76,21 @@ module FFI
76
76
  # going to be useful if you subclass {AutoPointer}, and override
77
77
  # #release, which by default does nothing.
78
78
  def initialize(ptr, proc=nil, &block)
79
+ raise TypeError, "Invalid pointer" if ptr.nil? || !ptr.kind_of?(Pointer) ||
80
+ ptr.kind_of?(MemoryPointer) || ptr.kind_of?(AutoPointer)
79
81
  super(ptr.type_size, ptr)
80
- raise TypeError, "Invalid pointer" if ptr.nil? || !ptr.kind_of?(Pointer) \
81
- || ptr.kind_of?(MemoryPointer) || ptr.kind_of?(AutoPointer)
82
82
 
83
83
  @releaser = if proc
84
84
  if not proc.respond_to?(:call)
85
85
  raise RuntimeError.new("proc must be callable")
86
86
  end
87
- CallableReleaser.new(ptr, proc)
87
+ Releaser.new(ptr, proc)
88
88
 
89
89
  else
90
- if not self.class.respond_to?(:release)
90
+ if not self.class.respond_to?(:release, true)
91
91
  raise RuntimeError.new("no release method defined")
92
92
  end
93
- DefaultReleaser.new(ptr, self.class)
93
+ Releaser.new(ptr, self.class.method(:release))
94
94
  end
95
95
 
96
96
  ObjectSpace.define_finalizer(self, @releaser)
@@ -107,6 +107,7 @@ module FFI
107
107
  # @return [Boolean] +autorelease+
108
108
  # Set +autorelease+ property. See {Pointer Autorelease section at Pointer}.
109
109
  def autorelease=(autorelease)
110
+ raise FrozenError.new("can't modify frozen #{self.class}") if frozen?
110
111
  @releaser.autorelease=(autorelease)
111
112
  end
112
113
 
@@ -149,23 +150,7 @@ module FFI
149
150
  def call(*args)
150
151
  release(@ptr) if @autorelease && @ptr
151
152
  end
152
- end
153
-
154
- # DefaultReleaser is a {Releaser} used when an {AutoPointer} is defined
155
- # without Proc or Method. In this case, the pointer to release must be of
156
- # a class derived from AutoPointer with a {release} class method.
157
- class DefaultReleaser < Releaser
158
- # @param [Pointer] ptr
159
- # @return [nil]
160
- # Release +ptr+ using the {release} class method of its class.
161
- def release(ptr)
162
- @proc.release(ptr)
163
- end
164
- end
165
153
 
166
- # CallableReleaser is a {Releaser} used when an {AutoPointer} is defined with a
167
- # Proc or a Method.
168
- class CallableReleaser < Releaser
169
154
  # Release +ptr+ by using Proc or Method defined at +ptr+
170
155
  # {AutoPointer#initialize initialization}.
171
156
  #
@@ -182,7 +167,7 @@ module FFI
182
167
  # @return [Type::POINTER]
183
168
  # @raise {RuntimeError} if class does not implement a +#release+ method
184
169
  def self.native_type
185
- if not self.respond_to?(:release)
170
+ if not self.respond_to?(:release, true)
186
171
  raise RuntimeError.new("no release method defined for #{self.inspect}")
187
172
  end
188
173
  Type::POINTER
data/lib/ffi/compat.rb ADDED
@@ -0,0 +1,43 @@
1
+ #
2
+ # Copyright (C) 2023-2023 Lars Kanis
3
+ #
4
+ # This file is part of ruby-ffi.
5
+ #
6
+ # All rights reserved.
7
+ #
8
+ # Redistribution and use in source and binary forms, with or without
9
+ # modification, are permitted provided that the following conditions are met:
10
+ #
11
+ # * Redistributions of source code must retain the above copyright notice, this
12
+ # list of conditions and the following disclaimer.
13
+ # * Redistributions in binary form must reproduce the above copyright notice
14
+ # this list of conditions and the following disclaimer in the documentation
15
+ # and/or other materials provided with the distribution.
16
+ # * Neither the name of the Ruby FFI project nor the names of its contributors
17
+ # may be used to endorse or promote products derived from this software
18
+ # without specific prior written permission.
19
+ #
20
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
24
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
+ #
31
+
32
+ module FFI
33
+ if defined?(Ractor.make_shareable)
34
+ # This is for FFI internal use only.
35
+ def self.make_shareable(obj)
36
+ Ractor.make_shareable(obj)
37
+ end
38
+ else
39
+ def self.make_shareable(obj)
40
+ obj.freeze
41
+ end
42
+ end
43
+ end
@@ -31,7 +31,7 @@
31
31
  module FFI
32
32
  # This module is used to extend somes classes and give then a common API.
33
33
  #
34
- # Most of methods defined here must be overriden.
34
+ # Most of methods defined here must be overridden.
35
35
  module DataConverter
36
36
  # Get native type.
37
37
  #
@@ -41,7 +41,7 @@ module FFI
41
41
  # Get native type from +type+.
42
42
  #
43
43
  # @overload native_type
44
- # @raise {NotImplementedError} This method must be overriden.
44
+ # @raise {NotImplementedError} This method must be overridden.
45
45
  def native_type(type = nil)
46
46
  if type
47
47
  @native_type = FFI.find_type(type)
@@ -0,0 +1,89 @@
1
+ #
2
+ # Copyright (C) 2008-2010 Wayne Meissner
3
+ #
4
+ # This file is part of ruby-ffi.
5
+ #
6
+ # All rights reserved.
7
+ #
8
+ # Redistribution and use in source and binary forms, with or without
9
+ # modification, are permitted provided that the following conditions are met:
10
+ #
11
+ # * Redistributions of source code must retain the above copyright notice, this
12
+ # list of conditions and the following disclaimer.
13
+ # * Redistributions in binary form must reproduce the above copyright notice
14
+ # this list of conditions and the following disclaimer in the documentation
15
+ # and/or other materials provided with the distribution.
16
+ # * Neither the name of the Ruby FFI project nor the names of its contributors
17
+ # may be used to endorse or promote products derived from this software
18
+ # without specific prior written permission.
19
+ #
20
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
24
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.#
30
+
31
+ module FFI
32
+ class DynamicLibrary
33
+ SEARCH_PATH = %w[/usr/lib /usr/local/lib /opt/local/lib]
34
+ if FFI::Platform::ARCH == 'aarch64' && FFI::Platform.mac?
35
+ SEARCH_PATH << '/opt/homebrew/lib'
36
+ end
37
+
38
+ SEARCH_PATH_MESSAGE = "Searched in <system library path>, #{SEARCH_PATH.join(', ')}".freeze
39
+
40
+ def self.load_library(name, flags)
41
+ if name == FFI::CURRENT_PROCESS
42
+ FFI::DynamicLibrary.open(nil, RTLD_LAZY | RTLD_LOCAL)
43
+ else
44
+ flags ||= RTLD_LAZY | RTLD_LOCAL
45
+
46
+ libnames = (name.is_a?(::Array) ? name : [name])
47
+ libnames = libnames.map(&:to_s).map { |n| [n, FFI.map_library_name(n)].uniq }.flatten.compact
48
+ errors = []
49
+
50
+ libnames.each do |libname|
51
+ lib = try_load(libname, flags, errors)
52
+ return lib if lib
53
+
54
+ unless libname.start_with?("/") || FFI::Platform.windows?
55
+ SEARCH_PATH.each do |prefix|
56
+ path = "#{prefix}/#{libname}"
57
+ if File.exist?(path)
58
+ lib = try_load(path, flags, errors)
59
+ return lib if lib
60
+ end
61
+ end
62
+ end
63
+ end
64
+
65
+ raise LoadError, [*errors, SEARCH_PATH_MESSAGE].join(".\n")
66
+ end
67
+ end
68
+ private_class_method :load_library
69
+
70
+ def self.try_load(libname, flags, errors)
71
+ begin
72
+ lib = FFI::DynamicLibrary.open(libname, flags)
73
+ return lib if lib
74
+
75
+ # LoadError for C ext & JRuby, RuntimeError for TruffleRuby
76
+ rescue LoadError, RuntimeError => ex
77
+ if ex.message =~ /(([^ \t()])+\.so([^ \t:()])*):([ \t])*(invalid ELF header|file too short|invalid file format)/
78
+ if File.binread($1) =~ /(?:GROUP|INPUT) *\( *([^ \)]+)/
79
+ return try_load($1, flags, errors)
80
+ end
81
+ end
82
+
83
+ errors << ex
84
+ nil
85
+ end
86
+ end
87
+ private_class_method :try_load
88
+ end
89
+ end
data/lib/ffi/enum.rb CHANGED
@@ -192,6 +192,7 @@ module FFI
192
192
  # @param [nil, Symbol] tag name of new Bitmask
193
193
  def initialize(*args)
194
194
  @native_type = args.first.kind_of?(FFI::Type) ? args.shift : Type::INT
195
+ @signed = [Type::INT8, Type::INT16, Type::INT32, Type::INT64].include?(@native_type)
195
196
  info, @tag = *args
196
197
  @kv_map = Hash.new
197
198
  unless info.nil?
@@ -220,7 +221,7 @@ module FFI
220
221
  # @param [Symbol] query
221
222
  # @return [Integer]
222
223
  # @overload [](query)
223
- # Get bitmaks value from symbol array
224
+ # Get bitmask value from symbol array
224
225
  # @param [Array<Symbol>] query
225
226
  # @return [Integer]
226
227
  # @overload [](*query)
@@ -240,7 +241,7 @@ module FFI
240
241
  when Symbol
241
242
  flat_query.inject(0) do |val, o|
242
243
  v = @kv_map[o]
243
- if v then val |= v else val end
244
+ if v then val | v else val end
244
245
  end
245
246
  when Integer, ->(o) { o.respond_to?(:to_int) }
246
247
  val = flat_query.inject(0) { |mask, o| mask |= o.to_int }
@@ -260,35 +261,41 @@ module FFI
260
261
  def to_native(query, ctx)
261
262
  return 0 if query.nil?
262
263
  flat_query = [query].flatten
263
- flat_query.inject(0) do |val, o|
264
+ res = flat_query.inject(0) do |val, o|
264
265
  case o
265
266
  when Symbol
266
267
  v = @kv_map[o]
267
268
  raise ArgumentError, "invalid bitmask value, #{o.inspect}" unless v
268
- val |= v
269
+ val | v
269
270
  when Integer
270
- val |= o
271
+ val | o
271
272
  when ->(obj) { obj.respond_to?(:to_int) }
272
- val |= o.to_int
273
+ val | o.to_int
273
274
  else
274
275
  raise ArgumentError, "invalid bitmask value, #{o.inspect}"
275
276
  end
276
277
  end
278
+ # Take two's complement of positive values bigger than the max value
279
+ # for the type when native type is signed.
280
+ if @signed && res >= (1 << (@native_type.size * 8 - 1))
281
+ res = -(-res & ((1 << (@native_type.size * 8)) - 1))
282
+ end
283
+ res
277
284
  end
278
285
 
279
286
  # @param [Integer] val
280
287
  # @param ctx unused
281
288
  # @return [Array<Symbol, Integer>] list of symbol names corresponding to val, plus an optional remainder if some bits don't match any constant
282
289
  def from_native(val, ctx)
283
- list = @kv_map.select { |_, v| v & val != 0 }.keys
290
+ flags = @kv_map.select { |_, v| v & val != 0 }
291
+ list = flags.keys
292
+ # force an unsigned value of the correct size
293
+ val &= (1 << (@native_type.size * 8)) - 1 if @signed
284
294
  # If there are unmatch flags,
285
295
  # return them in an integer,
286
296
  # else information can be lost.
287
297
  # Similar to Enum behavior.
288
- remainder = val ^ list.inject(0) do |tmp, o|
289
- v = @kv_map[o]
290
- if v then tmp |= v else tmp end
291
- end
298
+ remainder = val ^ flags.values.reduce(0, :|)
292
299
  list.push remainder unless remainder == 0
293
300
  return list
294
301
  end
data/lib/ffi/ffi.rb CHANGED
@@ -28,9 +28,11 @@
28
28
  # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
29
  # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
30
 
31
+ require 'ffi/compat'
31
32
  require 'ffi/platform'
32
33
  require 'ffi/data_converter'
33
34
  require 'ffi/types'
35
+ require 'ffi/library_path'
34
36
  require 'ffi/library'
35
37
  require 'ffi/errno'
36
38
  require 'ffi/abstract_memory'
@@ -45,3 +47,4 @@ require 'ffi/autopointer'
45
47
  require 'ffi/variadic'
46
48
  require 'ffi/enum'
47
49
  require 'ffi/version'
50
+ require 'ffi/function'
@@ -0,0 +1,71 @@
1
+ #
2
+ # Copyright (C) 2008-2010 JRuby project
3
+ #
4
+ # This file is part of ruby-ffi.
5
+ #
6
+ # All rights reserved.
7
+ #
8
+ # Redistribution and use in source and binary forms, with or without
9
+ # modification, are permitted provided that the following conditions are met:
10
+ #
11
+ # * Redistributions of source code must retain the above copyright notice, this
12
+ # list of conditions and the following disclaimer.
13
+ # * Redistributions in binary form must reproduce the above copyright notice
14
+ # this list of conditions and the following disclaimer in the documentation
15
+ # and/or other materials provided with the distribution.
16
+ # * Neither the name of the Ruby FFI project nor the names of its contributors
17
+ # may be used to endorse or promote products derived from this software
18
+ # without specific prior written permission.
19
+ #
20
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
24
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
+
31
+ module FFI
32
+ class Function
33
+ # Only MRI allows function type queries
34
+ if private_method_defined?(:type)
35
+ # Retrieve the return type of the function
36
+ #
37
+ # This method returns FFI type returned by the function.
38
+ #
39
+ # @return [FFI::Type]
40
+ def return_type
41
+ type.return_type
42
+ end
43
+
44
+ # Retrieve Array of parameter types
45
+ #
46
+ # This method returns an Array of FFI types accepted as function parameters.
47
+ #
48
+ # @return [Array<FFI::Type>]
49
+ def param_types
50
+ type.param_types
51
+ end
52
+ end
53
+
54
+ # Stash the Function in a module variable so it can be inspected by attached_functions.
55
+ # On CRuby it also ensures that it does not get garbage collected.
56
+ module RegisterAttach
57
+ def attach(mod, name)
58
+ funcs = mod.instance_variable_get("@ffi_functions")
59
+ unless funcs
60
+ funcs = {}
61
+ mod.instance_variable_set("@ffi_functions", funcs)
62
+ end
63
+ funcs[name.to_sym] = self
64
+ # Jump to the native attach method of CRuby, JRuby or Tuffleruby
65
+ super
66
+ end
67
+ end
68
+ private_constant :RegisterAttach
69
+ prepend RegisterAttach
70
+ end
71
+ end