fiddle 1.0.9 → 1.1.1

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.
data/ext/fiddle/pointer.c CHANGED
@@ -6,13 +6,13 @@
6
6
  #include <ruby/ruby.h>
7
7
  #include <ruby/io.h>
8
8
 
9
+ #include <ctype.h>
10
+ #include <fiddle.h>
11
+
9
12
  #ifdef HAVE_RUBY_MEMORY_VIEW_H
10
13
  # include <ruby/memory_view.h>
11
14
  #endif
12
15
 
13
- #include <ctype.h>
14
- #include <fiddle.h>
15
-
16
16
  #ifdef PRIsVALUE
17
17
  # define RB_OBJ_CLASSNAME(obj) rb_obj_class(obj)
18
18
  # define RB_OBJ_STRING(obj) (obj)
@@ -24,7 +24,7 @@
24
24
 
25
25
  VALUE rb_cPointer;
26
26
 
27
- typedef void (*freefunc_t)(void*);
27
+ typedef rb_fiddle_freefunc_t freefunc_t;
28
28
 
29
29
  struct ptr_data {
30
30
  void *ptr;
@@ -92,7 +92,7 @@ static const rb_data_type_t fiddle_ptr_data_type = {
92
92
  {fiddle_ptr_mark, fiddle_ptr_free, fiddle_ptr_memsize,},
93
93
  };
94
94
 
95
- #ifdef FIDDLE_MEMORY_VIEW
95
+ #ifdef HAVE_RUBY_MEMORY_VIEW_H
96
96
  static struct ptr_data *
97
97
  fiddle_ptr_check_memory_view(VALUE obj)
98
98
  {
@@ -125,7 +125,7 @@ static const rb_memory_view_entry_t fiddle_ptr_memory_view_entry = {
125
125
  #endif
126
126
 
127
127
  static VALUE
128
- rb_fiddle_ptr_new2(VALUE klass, void *ptr, long size, freefunc_t func)
128
+ rb_fiddle_ptr_new2(VALUE klass, void *ptr, long size, freefunc_t func, VALUE wrap0, VALUE wrap1)
129
129
  {
130
130
  struct ptr_data *data;
131
131
  VALUE val;
@@ -135,14 +135,22 @@ rb_fiddle_ptr_new2(VALUE klass, void *ptr, long size, freefunc_t func)
135
135
  data->free = func;
136
136
  data->freed = false;
137
137
  data->size = size;
138
+ data->wrap[0] = wrap0;
139
+ data->wrap[1] = wrap1;
138
140
 
139
141
  return val;
140
142
  }
141
143
 
144
+ VALUE
145
+ rb_fiddle_ptr_new_wrap(void *ptr, long size, freefunc_t func, VALUE wrap0, VALUE wrap1)
146
+ {
147
+ return rb_fiddle_ptr_new2(rb_cPointer, ptr, size, func, wrap0, wrap1);
148
+ }
149
+
142
150
  static VALUE
143
151
  rb_fiddle_ptr_new(void *ptr, long size, freefunc_t func)
144
152
  {
145
- return rb_fiddle_ptr_new2(rb_cPointer, ptr, size, func);
153
+ return rb_fiddle_ptr_new2(rb_cPointer, ptr, size, func, 0, 0);
146
154
  }
147
155
 
148
156
  static VALUE
@@ -152,7 +160,7 @@ rb_fiddle_ptr_malloc(VALUE klass, long size, freefunc_t func)
152
160
 
153
161
  ptr = ruby_xmalloc((size_t)size);
154
162
  memset(ptr,0,(size_t)size);
155
- return rb_fiddle_ptr_new2(klass, ptr, size, func);
163
+ return rb_fiddle_ptr_new2(klass, ptr, size, func, 0, 0);
156
164
  }
157
165
 
158
166
  static void *
@@ -833,7 +841,7 @@ Init_fiddle_pointer(void)
833
841
  rb_define_method(rb_cPointer, "size", rb_fiddle_ptr_size_get, 0);
834
842
  rb_define_method(rb_cPointer, "size=", rb_fiddle_ptr_size_set, 1);
835
843
 
836
- #ifdef FIDDLE_MEMORY_VIEW
844
+ #ifdef HAVE_RUBY_MEMORY_VIEW_H
837
845
  rb_memory_view_register(rb_cPointer, &fiddle_ptr_memory_view_entry);
838
846
  #endif
839
847
 
data/fiddle.gemspec CHANGED
@@ -20,15 +20,12 @@ Gem::Specification.new do |spec|
20
20
  "LICENSE.txt",
21
21
  "README.md",
22
22
  "Rakefile",
23
- "bin/downloader.rb",
24
- "bin/extlibs.rb",
25
23
  "ext/fiddle/closure.c",
26
24
  "ext/fiddle/closure.h",
27
25
  "ext/fiddle/conversions.c",
28
26
  "ext/fiddle/conversions.h",
29
27
  "ext/fiddle/depend",
30
28
  "ext/fiddle/extconf.rb",
31
- "ext/fiddle/extlibs",
32
29
  "ext/fiddle/fiddle.c",
33
30
  "ext/fiddle/fiddle.h",
34
31
  "ext/fiddle/function.c",
@@ -56,11 +53,7 @@ Gem::Specification.new do |spec|
56
53
  spec.require_paths = ["lib"]
57
54
  spec.extensions = ["ext/fiddle/extconf.rb"]
58
55
 
59
- spec.required_ruby_version = ">= 2.3.0"
60
-
61
- spec.add_development_dependency "bundler"
62
- spec.add_development_dependency "rake"
63
- spec.add_development_dependency "rake-compiler"
56
+ spec.required_ruby_version = ">= 2.5.0"
64
57
 
65
58
  spec.metadata["msys2_mingw_dependencies"] = "libffi"
66
59
  end
@@ -1,6 +1,31 @@
1
1
  # frozen_string_literal: true
2
2
  module Fiddle
3
3
  class Closure
4
+ class << self
5
+ # Create a new closure. If a block is given, the created closure
6
+ # is automatically freed after the given block is executed.
7
+ #
8
+ # The all given arguments are passed to Fiddle::Closure.new. So
9
+ # using this method without block equals to Fiddle::Closure.new.
10
+ #
11
+ # == Example
12
+ #
13
+ # Fiddle::Closure.create(TYPE_INT, [TYPE_INT]) do |closure|
14
+ # # closure is freed automatically when this block is finished.
15
+ # end
16
+ def create(*args)
17
+ if block_given?
18
+ closure = new(*args)
19
+ begin
20
+ yield(closure)
21
+ ensure
22
+ closure.free
23
+ end
24
+ else
25
+ new(*args)
26
+ end
27
+ end
28
+ end
4
29
 
5
30
  # the C type of the return of the FFI closure
6
31
  attr_reader :ctype
@@ -164,23 +164,23 @@ module Fiddle
164
164
  unless Fiddle.const_defined?(:TYPE_LONG_LONG)
165
165
  raise(RuntimeError, "unsupported type: #{ty}")
166
166
  end
167
- return -TYPE_LONG_LONG
167
+ return TYPE_ULONG_LONG
168
168
  when /\A(?:signed\s+)?long(?:\s+int\s+)?(?:\s+\w+)?\z/
169
169
  return TYPE_LONG
170
170
  when /\Aunsigned\s+long(?:\s+int\s+)?(?:\s+\w+)?\z/
171
- return -TYPE_LONG
171
+ return TYPE_ULONG
172
172
  when /\A(?:signed\s+)?int(?:\s+\w+)?\z/
173
173
  return TYPE_INT
174
174
  when /\A(?:unsigned\s+int|uint)(?:\s+\w+)?\z/
175
- return -TYPE_INT
175
+ return TYPE_UINT
176
176
  when /\A(?:signed\s+)?short(?:\s+int\s+)?(?:\s+\w+)?\z/
177
177
  return TYPE_SHORT
178
178
  when /\Aunsigned\s+short(?:\s+int\s+)?(?:\s+\w+)?\z/
179
- return -TYPE_SHORT
179
+ return TYPE_USHORT
180
180
  when /\A(?:signed\s+)?char(?:\s+\w+)?\z/
181
181
  return TYPE_CHAR
182
182
  when /\Aunsigned\s+char(?:\s+\w+)?\z/
183
- return -TYPE_CHAR
183
+ return TYPE_UCHAR
184
184
  when /\Aint8_t(?:\s+\w+)?\z/
185
185
  unless Fiddle.const_defined?(:TYPE_INT8_T)
186
186
  raise(RuntimeError, "unsupported type: #{ty}")
@@ -190,7 +190,7 @@ module Fiddle
190
190
  unless Fiddle.const_defined?(:TYPE_INT8_T)
191
191
  raise(RuntimeError, "unsupported type: #{ty}")
192
192
  end
193
- return -TYPE_INT8_T
193
+ return TYPE_UINT8_T
194
194
  when /\Aint16_t(?:\s+\w+)?\z/
195
195
  unless Fiddle.const_defined?(:TYPE_INT16_T)
196
196
  raise(RuntimeError, "unsupported type: #{ty}")
@@ -200,7 +200,7 @@ module Fiddle
200
200
  unless Fiddle.const_defined?(:TYPE_INT16_T)
201
201
  raise(RuntimeError, "unsupported type: #{ty}")
202
202
  end
203
- return -TYPE_INT16_T
203
+ return TYPE_UINT16_T
204
204
  when /\Aint32_t(?:\s+\w+)?\z/
205
205
  unless Fiddle.const_defined?(:TYPE_INT32_T)
206
206
  raise(RuntimeError, "unsupported type: #{ty}")
@@ -210,7 +210,7 @@ module Fiddle
210
210
  unless Fiddle.const_defined?(:TYPE_INT32_T)
211
211
  raise(RuntimeError, "unsupported type: #{ty}")
212
212
  end
213
- return -TYPE_INT32_T
213
+ return TYPE_UINT32_T
214
214
  when /\Aint64_t(?:\s+\w+)?\z/
215
215
  unless Fiddle.const_defined?(:TYPE_INT64_T)
216
216
  raise(RuntimeError, "unsupported type: #{ty}")
@@ -220,7 +220,7 @@ module Fiddle
220
220
  unless Fiddle.const_defined?(:TYPE_INT64_T)
221
221
  raise(RuntimeError, "unsupported type: #{ty}")
222
222
  end
223
- return -TYPE_INT64_T
223
+ return TYPE_UINT64_T
224
224
  when /\Afloat(?:\s+\w+)?\z/
225
225
  return TYPE_FLOAT
226
226
  when /\Adouble(?:\s+\w+)?\z/
data/lib/fiddle/pack.rb CHANGED
@@ -11,24 +11,24 @@ module Fiddle
11
11
  TYPE_LONG => ALIGN_LONG,
12
12
  TYPE_FLOAT => ALIGN_FLOAT,
13
13
  TYPE_DOUBLE => ALIGN_DOUBLE,
14
- -TYPE_CHAR => ALIGN_CHAR,
15
- -TYPE_SHORT => ALIGN_SHORT,
16
- -TYPE_INT => ALIGN_INT,
17
- -TYPE_LONG => ALIGN_LONG,
14
+ TYPE_UCHAR => ALIGN_CHAR,
15
+ TYPE_USHORT => ALIGN_SHORT,
16
+ TYPE_UINT => ALIGN_INT,
17
+ TYPE_ULONG => ALIGN_LONG,
18
18
  }
19
19
 
20
20
  PACK_MAP = {
21
- TYPE_VOIDP => "l!",
21
+ TYPE_VOIDP => "L!",
22
22
  TYPE_CHAR => "c",
23
23
  TYPE_SHORT => "s!",
24
24
  TYPE_INT => "i!",
25
25
  TYPE_LONG => "l!",
26
26
  TYPE_FLOAT => "f",
27
27
  TYPE_DOUBLE => "d",
28
- -TYPE_CHAR => "c",
29
- -TYPE_SHORT => "s!",
30
- -TYPE_INT => "i!",
31
- -TYPE_LONG => "l!",
28
+ TYPE_UCHAR => "C",
29
+ TYPE_USHORT => "S!",
30
+ TYPE_UINT => "I!",
31
+ TYPE_ULONG => "L!",
32
32
  }
33
33
 
34
34
  SIZE_MAP = {
@@ -39,16 +39,17 @@ module Fiddle
39
39
  TYPE_LONG => SIZEOF_LONG,
40
40
  TYPE_FLOAT => SIZEOF_FLOAT,
41
41
  TYPE_DOUBLE => SIZEOF_DOUBLE,
42
- -TYPE_CHAR => SIZEOF_CHAR,
43
- -TYPE_SHORT => SIZEOF_SHORT,
44
- -TYPE_INT => SIZEOF_INT,
45
- -TYPE_LONG => SIZEOF_LONG,
42
+ TYPE_UCHAR => SIZEOF_CHAR,
43
+ TYPE_USHORT => SIZEOF_SHORT,
44
+ TYPE_UINT => SIZEOF_INT,
45
+ TYPE_ULONG => SIZEOF_LONG,
46
46
  }
47
47
  if defined?(TYPE_LONG_LONG)
48
- ALIGN_MAP[TYPE_LONG_LONG] = ALIGN_MAP[-TYPE_LONG_LONG] = ALIGN_LONG_LONG
49
- PACK_MAP[TYPE_LONG_LONG] = PACK_MAP[-TYPE_LONG_LONG] = "q"
50
- SIZE_MAP[TYPE_LONG_LONG] = SIZE_MAP[-TYPE_LONG_LONG] = SIZEOF_LONG_LONG
51
- PACK_MAP[TYPE_VOIDP] = "q" if SIZEOF_LONG_LONG == SIZEOF_VOIDP
48
+ ALIGN_MAP[TYPE_LONG_LONG] = ALIGN_MAP[TYPE_ULONG_LONG] = ALIGN_LONG_LONG
49
+ PACK_MAP[TYPE_LONG_LONG] = "q"
50
+ PACK_MAP[TYPE_ULONG_LONG] = "Q"
51
+ SIZE_MAP[TYPE_LONG_LONG] = SIZE_MAP[TYPE_ULONG_LONG] = SIZEOF_LONG_LONG
52
+ PACK_MAP[TYPE_VOIDP] = "Q" if SIZEOF_LONG_LONG == SIZEOF_VOIDP
52
53
  end
53
54
 
54
55
  def align(addr, align)
data/lib/fiddle/struct.rb CHANGED
@@ -13,6 +13,58 @@ module Fiddle
13
13
  CStructEntity
14
14
  end
15
15
 
16
+ def self.offsetof(name, members, types) # :nodoc:
17
+ offset = 0
18
+ worklist = name.split('.')
19
+ this_type = self
20
+ while search_name = worklist.shift
21
+ index = 0
22
+ member_index = members.index(search_name)
23
+
24
+ unless member_index
25
+ # Possibly a sub-structure
26
+ member_index = members.index { |member_name, _|
27
+ member_name == search_name
28
+ }
29
+ return unless member_index
30
+ end
31
+
32
+ types.each { |type, count = 1|
33
+ orig_offset = offset
34
+ if type.respond_to?(:entity_class)
35
+ align = type.alignment
36
+ type_size = type.size
37
+ else
38
+ align = PackInfo::ALIGN_MAP[type]
39
+ type_size = PackInfo::SIZE_MAP[type]
40
+ end
41
+
42
+ # Unions shouldn't advance the offset
43
+ if this_type.entity_class == CUnionEntity
44
+ type_size = 0
45
+ end
46
+
47
+ offset = PackInfo.align(orig_offset, align)
48
+
49
+ if worklist.empty?
50
+ return offset if index == member_index
51
+ else
52
+ if index == member_index
53
+ subtype = types[member_index]
54
+ members = subtype.members
55
+ types = subtype.types
56
+ this_type = subtype
57
+ break
58
+ end
59
+ end
60
+
61
+ offset += (type_size * count)
62
+ index += 1
63
+ }
64
+ end
65
+ nil
66
+ end
67
+
16
68
  def each
17
69
  return enum_for(__function__) unless block_given?
18
70
 
@@ -75,6 +127,10 @@ module Fiddle
75
127
  def CUnion.entity_class
76
128
  CUnionEntity
77
129
  end
130
+
131
+ def self.offsetof(name, members, types) # :nodoc:
132
+ 0
133
+ end
78
134
  end
79
135
 
80
136
  # Wrapper for arrays within a struct
@@ -172,6 +228,21 @@ module Fiddle
172
228
  define_method(:to_i){ @entity.to_i }
173
229
  define_singleton_method(:types) { types }
174
230
  define_singleton_method(:members) { members }
231
+
232
+ # Return the offset of a struct member given its name.
233
+ # For example:
234
+ #
235
+ # MyStruct = struct [
236
+ # "int64_t i",
237
+ # "char c",
238
+ # ]
239
+ #
240
+ # MyStruct.offsetof("i") # => 0
241
+ # MyStruct.offsetof("c") # => 8
242
+ #
243
+ define_singleton_method(:offsetof) { |name|
244
+ klass.offsetof(name, members, types)
245
+ }
175
246
  members.each{|name|
176
247
  name = name[0] if name.is_a?(Array) # name is a nested struct
177
248
  next if method_defined?(name)
@@ -1,3 +1,3 @@
1
1
  module Fiddle
2
- VERSION = "1.0.9"
2
+ VERSION = "1.1.1"
3
3
  end
data/lib/fiddle.rb CHANGED
@@ -58,7 +58,36 @@ module Fiddle
58
58
  #
59
59
  # See Fiddle::Handle.new for more.
60
60
  def dlopen library
61
- Fiddle::Handle.new library
61
+ begin
62
+ Fiddle::Handle.new(library)
63
+ rescue DLError => error
64
+ case RUBY_PLATFORM
65
+ when /linux/
66
+ case error.message
67
+ when /\A(\/.+?): (?:invalid ELF header|file too short)/
68
+ # This may be a linker script:
69
+ # https://sourceware.org/binutils/docs/ld.html#Scripts
70
+ path = $1
71
+ else
72
+ raise
73
+ end
74
+ else
75
+ raise
76
+ end
77
+
78
+ File.open(path) do |input|
79
+ input.each_line do |line|
80
+ case line
81
+ when /\A\s*(?:INPUT|GROUP)\s*\(\s*([^\s,\)]+)/
82
+ # TODO: Should we support multiple files?
83
+ return dlopen($1)
84
+ end
85
+ end
86
+ end
87
+
88
+ # Not found
89
+ raise
90
+ end
62
91
  end
63
92
  module_function :dlopen
64
93
 
@@ -67,4 +96,8 @@ module Fiddle
67
96
  RTLD_GLOBAL = Handle::RTLD_GLOBAL # :nodoc:
68
97
  RTLD_LAZY = Handle::RTLD_LAZY # :nodoc:
69
98
  RTLD_NOW = Handle::RTLD_NOW # :nodoc:
99
+
100
+ Fiddle::Types.constants.each do |type|
101
+ const_set "TYPE_#{type}", Fiddle::Types.const_get(type)
102
+ end
70
103
  end
metadata CHANGED
@@ -1,58 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fiddle
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.9
4
+ version: 1.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aaron Patterson
8
8
  - SHIBATA Hiroshi
9
- autorequire:
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2021-06-19 00:00:00.000000000 Z
13
- dependencies:
14
- - !ruby/object:Gem::Dependency
15
- name: bundler
16
- requirement: !ruby/object:Gem::Requirement
17
- requirements:
18
- - - ">="
19
- - !ruby/object:Gem::Version
20
- version: '0'
21
- type: :development
22
- prerelease: false
23
- version_requirements: !ruby/object:Gem::Requirement
24
- requirements:
25
- - - ">="
26
- - !ruby/object:Gem::Version
27
- version: '0'
28
- - !ruby/object:Gem::Dependency
29
- name: rake
30
- requirement: !ruby/object:Gem::Requirement
31
- requirements:
32
- - - ">="
33
- - !ruby/object:Gem::Version
34
- version: '0'
35
- type: :development
36
- prerelease: false
37
- version_requirements: !ruby/object:Gem::Requirement
38
- requirements:
39
- - - ">="
40
- - !ruby/object:Gem::Version
41
- version: '0'
42
- - !ruby/object:Gem::Dependency
43
- name: rake-compiler
44
- requirement: !ruby/object:Gem::Requirement
45
- requirements:
46
- - - ">="
47
- - !ruby/object:Gem::Version
48
- version: '0'
49
- type: :development
50
- prerelease: false
51
- version_requirements: !ruby/object:Gem::Requirement
52
- requirements:
53
- - - ">="
54
- - !ruby/object:Gem::Version
55
- version: '0'
12
+ date: 2022-12-08 00:00:00.000000000 Z
13
+ dependencies: []
56
14
  description: A libffi wrapper for Ruby.
57
15
  email:
58
16
  - aaron@tenderlovemaking.com
@@ -65,15 +23,12 @@ files:
65
23
  - LICENSE.txt
66
24
  - README.md
67
25
  - Rakefile
68
- - bin/downloader.rb
69
- - bin/extlibs.rb
70
26
  - ext/fiddle/closure.c
71
27
  - ext/fiddle/closure.h
72
28
  - ext/fiddle/conversions.c
73
29
  - ext/fiddle/conversions.h
74
30
  - ext/fiddle/depend
75
31
  - ext/fiddle/extconf.rb
76
- - ext/fiddle/extlibs
77
32
  - ext/fiddle/fiddle.c
78
33
  - ext/fiddle/fiddle.h
79
34
  - ext/fiddle/function.c
@@ -103,7 +58,7 @@ licenses:
103
58
  - BSD-2-Clause
104
59
  metadata:
105
60
  msys2_mingw_dependencies: libffi
106
- post_install_message:
61
+ post_install_message:
107
62
  rdoc_options: []
108
63
  require_paths:
109
64
  - lib
@@ -111,15 +66,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
111
66
  requirements:
112
67
  - - ">="
113
68
  - !ruby/object:Gem::Version
114
- version: 2.3.0
69
+ version: 2.5.0
115
70
  required_rubygems_version: !ruby/object:Gem::Requirement
116
71
  requirements:
117
72
  - - ">="
118
73
  - !ruby/object:Gem::Version
119
74
  version: '0'
120
75
  requirements: []
121
- rubygems_version: 3.3.0.dev
122
- signing_key:
76
+ rubygems_version: 3.4.0.dev
77
+ signing_key:
123
78
  specification_version: 4
124
79
  summary: A libffi wrapper for Ruby.
125
80
  test_files: []