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

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.
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