fiddle 1.1.6 → 1.1.7

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: b031b86e4ccc2f94430cb9322a38e7d06932800eb597452f130f01329ecd78ed
4
+ data.tar.gz: 0b6ccf708b048792e7e6afec9f3f7114289b0d9755353c37d95857085f1fadef
5
5
  SHA512:
6
- metadata.gz: 4abc678600a35970e801719b4319908312e312db6ff987c020b52047c37ec123e2168346db6ad534462d0591645eaa40ea57851fd0e2e7bab92e297928c0d464
7
- data.tar.gz: 9a8cbe9817d22c1d740caecf58252781c8268eea84a9957fe1704ac917482981fe4fe862d6d95d4a17ce8ac94a6b9cbc1272609ae77ab6d1f97901dcb2239a09
6
+ metadata.gz: 4e98b34f7c1deed926635fa0a99c24beadf19d4f5804acc87dec5ceab87a364a27538d5e715b1c7064b34cce8966de0b594a0a4c4131a3f9dfa5952935b2d1d5
7
+ data.tar.gz: 52782b8d2ab08ef3ac8cdecf78271b7e6fdcbc62e0e27bdad576034dfe0eabf410ba57f4809b14e0f26e24180c80f89234a812ead950088e1b56b80444e3ad47
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
 
@@ -240,7 +242,7 @@ module Fiddle
240
242
  def self.to_ptr(value)
241
243
  if value.is_a?(String)
242
244
  cptr = Pointer.malloc(value.bytesize)
243
- cptr.ffi_ptr.put_string(0, value)
245
+ cptr.ffi_ptr.put_bytes(0, value)
244
246
  cptr
245
247
 
246
248
  elsif value.is_a?(Array)
@@ -283,7 +285,7 @@ module Fiddle
283
285
  value = value.to_str(args[1])
284
286
  end
285
287
 
286
- @ffi_ptr.put_bytes(args[0], value, 0, args[1])
288
+ ffi_ptr.put_bytes(args[0], value, 0, args[1])
287
289
  elsif args.size == 1
288
290
  if value.is_a?(Fiddle::Pointer)
289
291
  value = value.to_str(args[0] + 1)
@@ -291,7 +293,7 @@ module Fiddle
291
293
  value = value.chr
292
294
  end
293
295
 
294
- @ffi_ptr.put_bytes(args[0], value, 0, 1)
296
+ ffi_ptr.put_bytes(args[0], value, 0, 1)
295
297
  end
296
298
  rescue FFI::NullPointerError
297
299
  raise DLError.new("NULL pointer access")
@@ -321,12 +323,23 @@ module Fiddle
321
323
  FFI::Pointer.new(Integer(addr))
322
324
  end
323
325
 
324
- @size = size ? size : ptr.size
326
+ if size
327
+ @size = size
328
+ elsif ptr.size_limit?
329
+ @size = ptr.size
330
+ else
331
+ @size = 0
332
+ end
325
333
  @free = free
326
334
  @ffi_ptr = ptr
335
+ @addr_ptr = nil
327
336
  @freed = false
328
337
  end
329
338
 
339
+ def ffi_ptr
340
+ @addr_ptr ? @addr_ptr.get_pointer(0) : @ffi_ptr
341
+ end
342
+
330
343
  module LibC
331
344
  extend FFI::Library
332
345
  ffi_lib FFI::Library::LIBC
@@ -355,11 +368,11 @@ module Fiddle
355
368
  end
356
369
 
357
370
  def null?
358
- @ffi_ptr.null?
371
+ ffi_ptr.null?
359
372
  end
360
373
 
361
374
  def to_ptr
362
- @ffi_ptr
375
+ ffi_ptr
363
376
  end
364
377
 
365
378
  def size
@@ -378,9 +391,9 @@ module Fiddle
378
391
  return if @free.nil?
379
392
  return if @freed
380
393
  if @free == RUBY_FREE
381
- LibC::FREE.call(@ffi_ptr)
394
+ LibC::FREE.call(ffi_ptr)
382
395
  else
383
- @free.call(@ffi_ptr)
396
+ @free.call(ffi_ptr)
384
397
  end
385
398
  @freed = true
386
399
  end
@@ -408,12 +421,13 @@ module Fiddle
408
421
  end
409
422
  alias to_int to_i
410
423
 
411
- # without \0
412
424
  def to_s(len = nil)
413
425
  if len
414
- ffi_ptr.get_string(0, len)
426
+ ffi_ptr.read_string(len)
427
+ elsif @size == 0
428
+ ffi_ptr.read_string
415
429
  else
416
- ffi_ptr.get_string(0)
430
+ ffi_ptr.get_string(0, @size)
417
431
  end
418
432
  rescue FFI::NullPointerError
419
433
  raise DLError.new("NULL pointer access")
@@ -423,6 +437,9 @@ module Fiddle
423
437
  if len
424
438
  ffi_ptr.read_string(len)
425
439
  else
440
+ if @size < 0
441
+ raise ArgumentError.new("negative string size (or size too big)")
442
+ end
426
443
  ffi_ptr.read_string(@size)
427
444
  end
428
445
  rescue FFI::NullPointerError
@@ -434,7 +451,16 @@ module Fiddle
434
451
  end
435
452
 
436
453
  def inspect
437
- "#<#{self.class.name} ptr=#{to_i.to_s(16)} size=#{@size} free=#{@free.inspect}>"
454
+ # SIZEOF_VOIDP * 2 == Math.log(2 ** (SIZEOF_VOIDP * 8), 16)
455
+ pointer_inspect_width = SIZEOF_VOIDP * 2
456
+ "#<%s ptr=0x%0.*x size=%d free=0x%0.*x>" % [
457
+ self.class.name,
458
+ pointer_inspect_width,
459
+ to_i,
460
+ size,
461
+ pointer_inspect_width,
462
+ @free || 0,
463
+ ]
438
464
  end
439
465
 
440
466
  def +(delta)
@@ -474,9 +500,8 @@ module Fiddle
474
500
  end
475
501
 
476
502
  def ref
477
- cptr = Pointer.malloc(FFI::Type::POINTER.size, RUBY_FREE)
478
- cptr.ffi_ptr.put_pointer(0, ffi_ptr)
479
- cptr
503
+ @addr_ptr ||= FFI::MemoryPointer.new(:pointer).put_pointer(0, @ffi_ptr)
504
+ Pointer.new(@addr_ptr, 0)
480
505
  end
481
506
  end
482
507
 
@@ -1,3 +1,3 @@
1
1
  module Fiddle
2
- VERSION = "1.1.6"
2
+ VERSION = "1.1.7"
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.7
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: []