fiddle 1.1.6 → 1.1.8

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: a45e277aca605b7e6ca64874fcb263a34c4ec365ee3c718c3df7e6d37e0786d7
4
- data.tar.gz: a441f4a982a218093e53de55f101f1afb0307c8764a028ad60b703d0f81c906e
3
+ metadata.gz: 1afa5c96f5b8b581a576ab625a4f9b5816ff859fc71c446174e51a7448200f0b
4
+ data.tar.gz: 60bad8470283ab5b5c65561b5069fc793c7374d73b7812e811361bac90ef7afd
5
5
  SHA512:
6
- metadata.gz: 4abc678600a35970e801719b4319908312e312db6ff987c020b52047c37ec123e2168346db6ad534462d0591645eaa40ea57851fd0e2e7bab92e297928c0d464
7
- data.tar.gz: 9a8cbe9817d22c1d740caecf58252781c8268eea84a9957fe1704ac917482981fe4fe862d6d95d4a17ce8ac94a6b9cbc1272609ae77ab6d1f97901dcb2239a09
6
+ metadata.gz: f674fef3c10f2d667c9de9decb69782a12a7d27b5797964d5b6a3a28e76e4021064cfd338e746a93e8dd00f1230a9bf8c7ba9b6588cec0f16d190f100d9f8261
7
+ data.tar.gz: bb36a9ea6cf98d2f7b805b4435456a859bff7f427aa5e40f40895bff1a9fbf7f47d8c6213d352a19c754ca1e0265a1942c557bbc8b6bfa0ce31f21a00e526e9a
data/Rakefile CHANGED
@@ -5,6 +5,15 @@ task :test do
5
5
  ruby("test/run.rb")
6
6
  end
7
7
 
8
+ release_task = Rake.application["release"]
9
+ release_task.prerequisites.delete("build")
10
+ release_task.prerequisites.delete("release:rubygem_push")
11
+ release_task_comment = release_task.comment
12
+ if release_task_comment
13
+ release_task.clear_comments
14
+ release_task.comment = release_task_comment.gsub(/ and build.*$/, "")
15
+ end
16
+
8
17
  namespace :version do
9
18
  desc "Bump version"
10
19
  task :bump do
@@ -247,7 +247,7 @@ module Fiddle
247
247
  return TYPE_INTPTR_T
248
248
  when /\Auintptr_t(?:\s+\w+)?\z/
249
249
  return TYPE_UINTPTR_T
250
- when "bool"
250
+ when /\Abool(?:\s+\w+)?\z/
251
251
  return TYPE_BOOL
252
252
  when /\*/, /\[[\s\d]*\]/
253
253
  return TYPE_VOIDP
@@ -188,8 +188,10 @@ module Fiddle
188
188
  end
189
189
  return_type = Fiddle::FFIBackend.to_ffi_type(@ctype)
190
190
  raise "#{self.class} must implement #call" unless respond_to?(:call)
191
- callable = method(:call)
192
- @function = FFI::Function.new(return_type, ffi_args, callable, convention: abi)
191
+ wrapper = lambda do |*args|
192
+ call(*args.map { |v| v.is_a?(FFI::Pointer) ? Pointer.new(v) : v })
193
+ end
194
+ @function = FFI::Function.new(return_type, ffi_args, wrapper, convention: abi)
193
195
  @freed = false
194
196
  end
195
197
 
@@ -216,8 +218,8 @@ module Fiddle
216
218
  class DLError < Error; end
217
219
  class ClearedReferenceError < Error; end
218
220
 
221
+ # Pointer isn't thread safe for now
219
222
  class Pointer
220
- attr_reader :ffi_ptr
221
223
  extend FFI::DataConverter
222
224
  native_type FFI::Type::Builtin::POINTER
223
225
 
@@ -239,9 +241,7 @@ module Fiddle
239
241
 
240
242
  def self.to_ptr(value)
241
243
  if value.is_a?(String)
242
- cptr = Pointer.malloc(value.bytesize)
243
- cptr.ffi_ptr.put_string(0, value)
244
- cptr
244
+ Pointer.new(FFI::MemoryPointer.from_string(value), value.bytesize)
245
245
 
246
246
  elsif value.is_a?(Array)
247
247
  raise NotImplementedError, "array ptr"
@@ -283,7 +283,7 @@ module Fiddle
283
283
  value = value.to_str(args[1])
284
284
  end
285
285
 
286
- @ffi_ptr.put_bytes(args[0], value, 0, args[1])
286
+ ffi_ptr.put_bytes(args[0], value, 0, args[1])
287
287
  elsif args.size == 1
288
288
  if value.is_a?(Fiddle::Pointer)
289
289
  value = value.to_str(args[0] + 1)
@@ -291,7 +291,7 @@ module Fiddle
291
291
  value = value.chr
292
292
  end
293
293
 
294
- @ffi_ptr.put_bytes(args[0], value, 0, 1)
294
+ ffi_ptr.put_bytes(args[0], value, 0, 1)
295
295
  end
296
296
  rescue FFI::NullPointerError
297
297
  raise DLError.new("NULL pointer access")
@@ -321,12 +321,23 @@ module Fiddle
321
321
  FFI::Pointer.new(Integer(addr))
322
322
  end
323
323
 
324
- @size = size ? size : ptr.size
324
+ if size
325
+ @size = size
326
+ elsif ptr.size_limit?
327
+ @size = ptr.size
328
+ else
329
+ @size = 0
330
+ end
325
331
  @free = free
326
332
  @ffi_ptr = ptr
333
+ @addr_ptr = nil
327
334
  @freed = false
328
335
  end
329
336
 
337
+ def ffi_ptr
338
+ @addr_ptr ? @addr_ptr.get_pointer(0) : @ffi_ptr
339
+ end
340
+
330
341
  module LibC
331
342
  extend FFI::Library
332
343
  ffi_lib FFI::Library::LIBC
@@ -355,11 +366,11 @@ module Fiddle
355
366
  end
356
367
 
357
368
  def null?
358
- @ffi_ptr.null?
369
+ ffi_ptr.null?
359
370
  end
360
371
 
361
372
  def to_ptr
362
- @ffi_ptr
373
+ ffi_ptr
363
374
  end
364
375
 
365
376
  def size
@@ -378,9 +389,9 @@ module Fiddle
378
389
  return if @free.nil?
379
390
  return if @freed
380
391
  if @free == RUBY_FREE
381
- LibC::FREE.call(@ffi_ptr)
392
+ LibC::FREE.call(ffi_ptr)
382
393
  else
383
- @free.call(@ffi_ptr)
394
+ @free.call(ffi_ptr)
384
395
  end
385
396
  @freed = true
386
397
  end
@@ -408,12 +419,13 @@ module Fiddle
408
419
  end
409
420
  alias to_int to_i
410
421
 
411
- # without \0
412
422
  def to_s(len = nil)
413
423
  if len
414
- ffi_ptr.get_string(0, len)
424
+ ffi_ptr.read_string(len)
425
+ elsif @size == 0
426
+ ffi_ptr.read_string
415
427
  else
416
- ffi_ptr.get_string(0)
428
+ ffi_ptr.get_string(0, @size)
417
429
  end
418
430
  rescue FFI::NullPointerError
419
431
  raise DLError.new("NULL pointer access")
@@ -423,6 +435,9 @@ module Fiddle
423
435
  if len
424
436
  ffi_ptr.read_string(len)
425
437
  else
438
+ if @size < 0
439
+ raise ArgumentError.new("negative string size (or size too big)")
440
+ end
426
441
  ffi_ptr.read_string(@size)
427
442
  end
428
443
  rescue FFI::NullPointerError
@@ -434,7 +449,16 @@ module Fiddle
434
449
  end
435
450
 
436
451
  def inspect
437
- "#<#{self.class.name} ptr=#{to_i.to_s(16)} size=#{@size} free=#{@free.inspect}>"
452
+ # SIZEOF_VOIDP * 2 == Math.log(2 ** (SIZEOF_VOIDP * 8), 16)
453
+ pointer_inspect_width = SIZEOF_VOIDP * 2
454
+ "#<%s ptr=0x%0.*x size=%d free=0x%0.*x>" % [
455
+ self.class.name,
456
+ pointer_inspect_width,
457
+ to_i,
458
+ size,
459
+ pointer_inspect_width,
460
+ @free || 0,
461
+ ]
438
462
  end
439
463
 
440
464
  def +(delta)
@@ -474,9 +498,8 @@ module Fiddle
474
498
  end
475
499
 
476
500
  def ref
477
- cptr = Pointer.malloc(FFI::Type::POINTER.size, RUBY_FREE)
478
- cptr.ffi_ptr.put_pointer(0, ffi_ptr)
479
- cptr
501
+ @addr_ptr ||= FFI::MemoryPointer.new(:pointer).put_pointer(0, @ffi_ptr)
502
+ Pointer.new(@addr_ptr, 0)
480
503
  end
481
504
  end
482
505
 
@@ -1,3 +1,3 @@
1
1
  module Fiddle
2
- VERSION = "1.1.6"
2
+ VERSION = "1.1.8"
3
3
  end
data/lib/fiddle.rb CHANGED
@@ -10,98 +10,80 @@ require 'fiddle/function'
10
10
  require 'fiddle/version'
11
11
 
12
12
  module Fiddle
13
- if WINDOWS
14
- # Returns the last win32 +Error+ of the current executing +Thread+ or nil
15
- # if none
16
- def self.win32_last_error
17
- if RUBY_ENGINE == 'jruby'
18
- errno = FFI.errno
19
- errno == 0 ? nil : errno
20
- else
21
- Thread.current[:__FIDDLE_WIN32_LAST_ERROR__]
22
- end
13
+ if RUBY_ENGINE != 'ruby' # FFI backend
14
+ def self.last_error
15
+ FFI.errno
23
16
  end
24
17
 
25
- # Sets the last win32 +Error+ of the current executing +Thread+ to +error+
26
- def self.win32_last_error= error
27
- if RUBY_ENGINE == 'jruby'
28
- FFI.errno = error || 0
29
- else
30
- Thread.current[:__FIDDLE_WIN32_LAST_ERROR__] = error
31
- end
18
+ def self.last_error=(error)
19
+ FFI.errno = error || 0
32
20
  end
33
21
 
34
- # Returns the last win32 socket +Error+ of the current executing
35
- # +Thread+ or nil if none
36
- def self.win32_last_socket_error
37
- if RUBY_ENGINE == 'jruby'
38
- errno = FFI.errno
39
- errno == 0 ? nil : errno
40
- else
41
- Thread.current[:__FIDDLE_WIN32_LAST_SOCKET_ERROR__]
42
- end
43
- end
22
+ if WINDOWS
23
+ class << self
24
+ def win32_last_error
25
+ FFI.errno.nonzero?
26
+ end
27
+ def win32_last_error=(error)
28
+ FFI.errno = error || 0
29
+ end
44
30
 
45
- # Sets the last win32 socket +Error+ of the current executing
46
- # +Thread+ to +error+
47
- def self.win32_last_socket_error= error
48
- if RUBY_ENGINE == 'jruby'
49
- FFI.errno = error || 0
50
- else
51
- Thread.current[:__FIDDLE_WIN32_LAST_SOCKET_ERROR__] = error
31
+ def win32_last_socket_error
32
+ FFI.errno.nonzero?
33
+ end
34
+ def win32_last_socket_error=(error)
35
+ FFI.errno = error || 0
36
+ end
52
37
  end
53
38
  end
54
- end
55
-
56
- # Returns the last +Error+ of the current executing +Thread+ or nil if none
57
- def self.last_error
58
- if RUBY_ENGINE == 'jruby'
59
- errno = FFI.errno
60
- errno == 0 ? nil : errno
61
- else
39
+ else
40
+ # Returns the last +Error+ of the current executing +Thread+ or nil if none
41
+ def self.last_error
62
42
  Thread.current[:__FIDDLE_LAST_ERROR__]
63
43
  end
64
- end
65
44
 
66
- # Sets the last +Error+ of the current executing +Thread+ to +error+
67
- def self.last_error= error
68
- if RUBY_ENGINE == 'jruby'
69
- FFI.errno = error || 0
70
- else
45
+ # Sets the last +Error+ of the current executing +Thread+ to +error+
46
+ def self.last_error= error
71
47
  Thread.current[:__DL2_LAST_ERROR__] = error
72
48
  Thread.current[:__FIDDLE_LAST_ERROR__] = error
73
49
  end
50
+
51
+ if WINDOWS
52
+ # Returns the last win32 +Error+ of the current executing +Thread+ or nil
53
+ # if none
54
+ def self.win32_last_error
55
+ Thread.current[:__FIDDLE_WIN32_LAST_ERROR__]
56
+ end
57
+
58
+ # Sets the last win32 +Error+ of the current executing +Thread+ to +error+
59
+ def self.win32_last_error= error
60
+ Thread.current[:__FIDDLE_WIN32_LAST_ERROR__] = error
61
+ end
62
+
63
+ # Returns the last win32 socket +Error+ of the current executing
64
+ # +Thread+ or nil if none
65
+ def self.win32_last_socket_error
66
+ Thread.current[:__FIDDLE_WIN32_LAST_SOCKET_ERROR__]
67
+ end
68
+
69
+ # Sets the last win32 socket +Error+ of the current executing
70
+ # +Thread+ to +error+
71
+ def self.win32_last_socket_error= error
72
+ Thread.current[:__FIDDLE_WIN32_LAST_SOCKET_ERROR__] = error
73
+ end
74
+ end
74
75
  end
75
76
 
76
- # call-seq: dlopen(library) => Fiddle::Handle
77
- #
78
- # Creates a new handler that opens +library+, and returns an instance of
79
- # Fiddle::Handle.
80
- #
81
- # If +nil+ is given for the +library+, Fiddle::Handle::DEFAULT is used, which
82
- # is the equivalent to RTLD_DEFAULT. See <code>man 3 dlopen</code> for more.
83
- #
84
- # lib = Fiddle.dlopen(nil)
85
- #
86
- # The default is dependent on OS, and provide a handle for all libraries
87
- # already loaded. For example, in most cases you can use this to access
88
- # +libc+ functions, or ruby functions like +rb_str_new+.
89
- #
90
- # See Fiddle::Handle.new for more.
91
- def dlopen library
92
- begin
77
+ case RUBY_PLATFORM
78
+ when /linux/
79
+ def dlopen library
93
80
  Fiddle::Handle.new(library)
94
81
  rescue DLError => error
95
- case RUBY_PLATFORM
96
- when /linux/
97
- case error.message
98
- when /\A(\/.+?): (?:invalid ELF header|file too short)/
99
- # This may be a linker script:
100
- # https://sourceware.org/binutils/docs/ld.html#Scripts
101
- path = $1
102
- else
103
- raise
104
- end
82
+ case error.message
83
+ when /\A(\/.+?): (?:invalid ELF header|file too short)/
84
+ # This may be a linker script:
85
+ # https://sourceware.org/binutils/docs/ld.html#Scripts
86
+ path = $1
105
87
  else
106
88
  raise
107
89
  end
@@ -123,6 +105,25 @@ module Fiddle
123
105
  # Not found
124
106
  raise
125
107
  end
108
+ else
109
+ # call-seq: dlopen(library) => Fiddle::Handle
110
+ #
111
+ # Creates a new handler that opens +library+, and returns an instance of
112
+ # Fiddle::Handle.
113
+ #
114
+ # If +nil+ is given for the +library+, Fiddle::Handle::DEFAULT is used, which
115
+ # is the equivalent to RTLD_DEFAULT. See <code>man 3 dlopen</code> for more.
116
+ #
117
+ # lib = Fiddle.dlopen(nil)
118
+ #
119
+ # The default is dependent on OS, and provide a handle for all libraries
120
+ # already loaded. For example, in most cases you can use this to access
121
+ # +libc+ functions, or ruby functions like +rb_str_new+.
122
+ #
123
+ # See Fiddle::Handle.new for more.
124
+ def dlopen library
125
+ Fiddle::Handle.new(library)
126
+ end
126
127
  end
127
128
  module_function :dlopen
128
129
 
metadata CHANGED
@@ -1,15 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fiddle
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.6
4
+ version: 1.1.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aaron Patterson
8
8
  - SHIBATA Hiroshi
9
- autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2024-12-12 00:00:00.000000000 Z
11
+ date: 1980-01-02 00:00:00.000000000 Z
13
12
  dependencies: []
14
13
  description: A libffi wrapper for Ruby.
15
14
  email:
@@ -56,7 +55,6 @@ licenses:
56
55
  metadata:
57
56
  msys2_mingw_dependencies: libffi
58
57
  changelog_uri: https://github.com/ruby/fiddle/releases
59
- post_install_message:
60
58
  rdoc_options: []
61
59
  require_paths:
62
60
  - lib
@@ -71,8 +69,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
71
69
  - !ruby/object:Gem::Version
72
70
  version: '0'
73
71
  requirements: []
74
- rubygems_version: 3.5.22
75
- signing_key:
72
+ rubygems_version: 3.6.7
76
73
  specification_version: 4
77
74
  summary: A libffi wrapper for Ruby.
78
75
  test_files: []