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 +4 -4
- data/Rakefile +9 -0
- data/lib/fiddle/cparser.rb +1 -1
- data/lib/fiddle/ffi_backend.rb +43 -20
- data/lib/fiddle/version.rb +1 -1
- data/lib/fiddle.rb +76 -75
- metadata +3 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1afa5c96f5b8b581a576ab625a4f9b5816ff859fc71c446174e51a7448200f0b
|
4
|
+
data.tar.gz: 60bad8470283ab5b5c65561b5069fc793c7374d73b7812e811361bac90ef7afd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
data/lib/fiddle/cparser.rb
CHANGED
data/lib/fiddle/ffi_backend.rb
CHANGED
@@ -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
|
-
|
192
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
369
|
+
ffi_ptr.null?
|
359
370
|
end
|
360
371
|
|
361
372
|
def to_ptr
|
362
|
-
|
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(
|
392
|
+
LibC::FREE.call(ffi_ptr)
|
382
393
|
else
|
383
|
-
@free.call(
|
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.
|
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
|
-
|
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
|
-
|
478
|
-
|
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
|
|
data/lib/fiddle/version.rb
CHANGED
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
|
14
|
-
|
15
|
-
|
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
|
-
|
26
|
-
|
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
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
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
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
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
|
-
|
55
|
-
|
56
|
-
|
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
|
-
|
67
|
-
|
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
|
-
|
77
|
-
|
78
|
-
|
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
|
96
|
-
when /
|
97
|
-
|
98
|
-
|
99
|
-
|
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.
|
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:
|
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.
|
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: []
|