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 +4 -4
- data/Rakefile +9 -0
- data/lib/fiddle/cparser.rb +1 -1
- data/lib/fiddle/ffi_backend.rb +43 -18
- 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: b031b86e4ccc2f94430cb9322a38e7d06932800eb597452f130f01329ecd78ed
|
4
|
+
data.tar.gz: 0b6ccf708b048792e7e6afec9f3f7114289b0d9755353c37d95857085f1fadef
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
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
|
|
@@ -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.
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
371
|
+
ffi_ptr.null?
|
359
372
|
end
|
360
373
|
|
361
374
|
def to_ptr
|
362
|
-
|
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(
|
394
|
+
LibC::FREE.call(ffi_ptr)
|
382
395
|
else
|
383
|
-
@free.call(
|
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.
|
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
|
-
|
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
|
-
|
478
|
-
|
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
|
|
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.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:
|
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: []
|