onnxruntime 0.9.3-arm64-darwin → 0.10.0-arm64-darwin

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: a0f68aa52a14030b633fd2424395a803150d0f336259de1c97a7e27430259191
4
- data.tar.gz: 6619423585e62a142abf5298f90ebecd16396264b689da3885535967f6dca1d1
3
+ metadata.gz: f7dad037f608d84cfab56c437400214af6a2337f82fdde99da832fd439f427b6
4
+ data.tar.gz: c5add82f70cc8262f8d8650fbf27ec862b20d287b30b58a5166d922b6b761181
5
5
  SHA512:
6
- metadata.gz: 616c2f43fd027b2461e3ceb798d7de8288afc6cf0df46982635bfd0507b5c46ab607b6088fffbb1c969f036e109a25aaafb661ca9d8fd88562e5c3af3c27ab89
7
- data.tar.gz: aa82092853cfa49307d665972348b54eab01d685cd638ebfda8c5adfe7d3d4f43bb31aa9a1e93ea4740a7de6e21efea8711365509ae155035d1cdafff7a9bb1f
6
+ metadata.gz: c77c90b6fd4d689ce048ead1c2a06e5122b2c15a55826224fda7268413d0443f4a1bff65c3e1c87b367fa795d2c7c80ea012462d5de355647edda0d72c5830f5
7
+ data.tar.gz: acb452d01571852dac8807ecc989714bfd13374c4d58c1c1dfb3a084a17cb04fd9c0ac658756d8a93ef387766bf3e5101e0e7e573270a40adf9583d6c082b9c8
data/CHANGELOG.md CHANGED
@@ -1,3 +1,12 @@
1
+ ## 0.10.0 (2025-05-11)
2
+
3
+ - Updated ONNX Runtime to 1.22.0
4
+ - Dropped support for Ruby < 3.2
5
+
6
+ ## 0.9.4 (2025-03-08)
7
+
8
+ - Updated ONNX Runtime to 1.21.0
9
+
1
10
  ## 0.9.3 (2024-11-01)
2
11
 
3
12
  - Updated ONNX Runtime to 1.20.0
data/LICENSE.txt CHANGED
@@ -1,7 +1,7 @@
1
1
  MIT License
2
2
 
3
3
  Copyright (c) Microsoft Corporation
4
- Copyright (c) 2019-2024 Andrew Kane
4
+ Copyright (c) 2019-2025 Andrew Kane
5
5
 
6
6
  Permission is hereby granted, free of charge, to any person obtaining a copy
7
7
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -4,6 +4,8 @@
4
4
 
5
5
  Check out [an example](https://ankane.org/tensorflow-ruby)
6
6
 
7
+ For transformer models, check out [Informers](https://github.com/ankane/informers)
8
+
7
9
  [![Build Status](https://github.com/ankane/onnxruntime-ruby/actions/workflows/build.yml/badge.svg)](https://github.com/ankane/onnxruntime-ruby/actions)
8
10
 
9
11
  ## Installation
@@ -147,7 +147,7 @@ module OnnxRuntime
147
147
  :FillStringTensorElement, callback(%i[pointer string size_t], :pointer),
148
148
  :AddSessionConfigEntry, callback(%i[pointer string string], :pointer),
149
149
  :CreateAllocator, callback(%i[], :pointer),
150
- :ReleaseAllocator, callback(%i[], :pointer),
150
+ :ReleaseAllocator, callback(%i[pointer], :pointer),
151
151
  :RunWithBinding, callback(%i[], :pointer),
152
152
  :CreateIoBinding, callback(%i[], :pointer),
153
153
  :ReleaseIoBinding, callback(%i[], :pointer),
@@ -249,7 +249,7 @@ module OnnxRuntime
249
249
  def self.api
250
250
  @api ||= begin
251
251
  api = self.OrtGetApiBase[:GetApi].call(ORT_API_VERSION)
252
- api = Api.by_ref.from_native(api, nil) if RUBY_PLATFORM == "java"
252
+ api = Api.by_ref.from_native(api, nil) if RUBY_ENGINE == "jruby"
253
253
  api
254
254
  end
255
255
  end
@@ -6,52 +6,54 @@ module OnnxRuntime
6
6
  # session options
7
7
  session_options = ::FFI::MemoryPointer.new(:pointer)
8
8
  check_status api[:CreateSessionOptions].call(session_options)
9
+ session_options = ::FFI::AutoPointer.new(session_options.read_pointer, api[:ReleaseSessionOptions])
10
+
9
11
  if enable_cpu_mem_arena
10
- check_status api[:EnableCpuMemArena].call(session_options.read_pointer)
12
+ check_status api[:EnableCpuMemArena].call(session_options)
11
13
  else
12
- check_status api[:DisableCpuMemArena].call(session_options.read_pointer)
14
+ check_status api[:DisableCpuMemArena].call(session_options)
13
15
  end
14
16
  if enable_mem_pattern
15
- check_status api[:EnableMemPattern].call(session_options.read_pointer)
17
+ check_status api[:EnableMemPattern].call(session_options)
16
18
  else
17
- check_status api[:DisableMemPattern].call(session_options.read_pointer)
19
+ check_status api[:DisableMemPattern].call(session_options)
18
20
  end
19
21
  if enable_profiling
20
- check_status api[:EnableProfiling].call(session_options.read_pointer, ort_string(profile_file_prefix || "onnxruntime_profile_"))
22
+ check_status api[:EnableProfiling].call(session_options, ort_string(profile_file_prefix || "onnxruntime_profile_"))
21
23
  else
22
- check_status api[:DisableProfiling].call(session_options.read_pointer)
24
+ check_status api[:DisableProfiling].call(session_options)
23
25
  end
24
26
  if execution_mode
25
27
  execution_modes = {sequential: 0, parallel: 1}
26
28
  mode = execution_modes[execution_mode]
27
29
  raise ArgumentError, "Invalid execution mode" unless mode
28
- check_status api[:SetSessionExecutionMode].call(session_options.read_pointer, mode)
30
+ check_status api[:SetSessionExecutionMode].call(session_options, mode)
29
31
  end
30
32
  if free_dimension_overrides_by_denotation
31
33
  free_dimension_overrides_by_denotation.each do |k, v|
32
- check_status api[:AddFreeDimensionOverride].call(session_options.read_pointer, k.to_s, v)
34
+ check_status api[:AddFreeDimensionOverride].call(session_options, k.to_s, v)
33
35
  end
34
36
  end
35
37
  if free_dimension_overrides_by_name
36
38
  free_dimension_overrides_by_name.each do |k, v|
37
- check_status api[:AddFreeDimensionOverrideByName].call(session_options.read_pointer, k.to_s, v)
39
+ check_status api[:AddFreeDimensionOverrideByName].call(session_options, k.to_s, v)
38
40
  end
39
41
  end
40
42
  if graph_optimization_level
41
43
  optimization_levels = {none: 0, basic: 1, extended: 2, all: 99}
42
44
  level = optimization_levels[graph_optimization_level]
43
45
  raise ArgumentError, "Invalid graph optimization level" unless level
44
- check_status api[:SetSessionGraphOptimizationLevel].call(session_options.read_pointer, level)
46
+ check_status api[:SetSessionGraphOptimizationLevel].call(session_options, level)
45
47
  end
46
- check_status api[:SetInterOpNumThreads].call(session_options.read_pointer, inter_op_num_threads) if inter_op_num_threads
47
- check_status api[:SetIntraOpNumThreads].call(session_options.read_pointer, intra_op_num_threads) if intra_op_num_threads
48
- check_status api[:SetSessionLogSeverityLevel].call(session_options.read_pointer, log_severity_level) if log_severity_level
49
- check_status api[:SetSessionLogVerbosityLevel].call(session_options.read_pointer, log_verbosity_level) if log_verbosity_level
50
- check_status api[:SetSessionLogId].call(session_options.read_pointer, logid) if logid
51
- check_status api[:SetOptimizedModelFilePath].call(session_options.read_pointer, ort_string(optimized_model_filepath)) if optimized_model_filepath
48
+ check_status api[:SetInterOpNumThreads].call(session_options, inter_op_num_threads) if inter_op_num_threads
49
+ check_status api[:SetIntraOpNumThreads].call(session_options, intra_op_num_threads) if intra_op_num_threads
50
+ check_status api[:SetSessionLogSeverityLevel].call(session_options, log_severity_level) if log_severity_level
51
+ check_status api[:SetSessionLogVerbosityLevel].call(session_options, log_verbosity_level) if log_verbosity_level
52
+ check_status api[:SetSessionLogId].call(session_options, logid) if logid
53
+ check_status api[:SetOptimizedModelFilePath].call(session_options, ort_string(optimized_model_filepath)) if optimized_model_filepath
52
54
  if session_config_entries
53
55
  session_config_entries.each do |k, v|
54
- check_status api[:AddSessionConfigEntry].call(session_options.read_pointer, k.to_s, v.to_s)
56
+ check_status api[:AddSessionConfigEntry].call(session_options, k.to_s, v.to_s)
55
57
  end
56
58
  end
57
59
  providers.each do |provider|
@@ -64,15 +66,15 @@ module OnnxRuntime
64
66
  when "CUDAExecutionProvider"
65
67
  cuda_options = ::FFI::MemoryPointer.new(:pointer)
66
68
  check_status api[:CreateCUDAProviderOptions].call(cuda_options)
67
- check_status api[:SessionOptionsAppendExecutionProvider_CUDA_V2].call(session_options.read_pointer, cuda_options.read_pointer)
68
- release :CUDAProviderOptions, cuda_options
69
+ cuda_options = ::FFI::AutoPointer.new(cuda_options.read_pointer, api[:ReleaseCUDAProviderOptions])
70
+ check_status api[:SessionOptionsAppendExecutionProvider_CUDA_V2].call(session_options, cuda_options)
69
71
  when "CoreMLExecutionProvider"
70
72
  unless FFI.respond_to?(:OrtSessionOptionsAppendExecutionProvider_CoreML)
71
73
  raise ArgumentError, "Provider not available: #{provider}"
72
74
  end
73
75
 
74
76
  coreml_flags = 0
75
- check_status FFI.OrtSessionOptionsAppendExecutionProvider_CoreML(session_options.read_pointer, coreml_flags)
77
+ check_status FFI.OrtSessionOptionsAppendExecutionProvider_CoreML(session_options, coreml_flags)
76
78
  when "CPUExecutionProvider"
77
79
  break
78
80
  else
@@ -81,13 +83,9 @@ module OnnxRuntime
81
83
  end
82
84
 
83
85
  @session = load_session(path_or_bytes, session_options)
84
- ObjectSpace.define_finalizer(@session, self.class.finalize(read_pointer.to_i))
85
-
86
86
  @allocator = Utils.allocator
87
87
  @inputs = load_inputs
88
88
  @outputs = load_outputs
89
- ensure
90
- release :SessionOptions, session_options
91
89
  end
92
90
 
93
91
  def run(output_names, input_feed, log_severity_level: nil, log_verbosity_level: nil, logid: nil, terminate: nil, output_type: :ruby)
@@ -119,51 +117,57 @@ module OnnxRuntime
119
117
  # run options
120
118
  run_options = ::FFI::MemoryPointer.new(:pointer)
121
119
  check_status api[:CreateRunOptions].call(run_options)
122
- check_status api[:RunOptionsSetRunLogSeverityLevel].call(run_options.read_pointer, log_severity_level) if log_severity_level
123
- check_status api[:RunOptionsSetRunLogVerbosityLevel].call(run_options.read_pointer, log_verbosity_level) if log_verbosity_level
124
- check_status api[:RunOptionsSetRunTag].call(run_options.read_pointer, logid) if logid
125
- check_status api[:RunOptionsSetTerminate].call(run_options.read_pointer) if terminate
120
+ run_options = ::FFI::AutoPointer.new(run_options.read_pointer, api[:ReleaseRunOptions])
126
121
 
127
- check_status api[:Run].call(read_pointer, run_options.read_pointer, input_node_names, input_tensor, input_feed.size, output_node_names, output_names.size, output_tensor)
122
+ check_status api[:RunOptionsSetRunLogSeverityLevel].call(run_options, log_severity_level) if log_severity_level
123
+ check_status api[:RunOptionsSetRunLogVerbosityLevel].call(run_options, log_verbosity_level) if log_verbosity_level
124
+ check_status api[:RunOptionsSetRunTag].call(run_options, logid) if logid
125
+ check_status api[:RunOptionsSetTerminate].call(run_options) if terminate
128
126
 
129
- output_names.size.times.map { |i| OrtValue.new(output_tensor[i]) }
130
- ensure
131
- release :RunOptions, run_options
127
+ check_status api[:Run].call(@session, run_options, input_node_names, input_tensor, input_feed.size, output_node_names, output_names.size, output_tensor)
128
+
129
+ output_names.size.times.map { |i| OrtValue.new(output_tensor[i].read_pointer) }
132
130
  end
133
131
 
134
132
  def modelmeta
133
+ metadata = ::FFI::MemoryPointer.new(:pointer)
134
+ check_status api[:SessionGetModelMetadata].call(@session, metadata)
135
+ metadata = ::FFI::AutoPointer.new(metadata.read_pointer, api[:ReleaseModelMetadata])
136
+
135
137
  keys = ::FFI::MemoryPointer.new(:pointer)
136
138
  num_keys = ::FFI::MemoryPointer.new(:int64_t)
137
- description = ::FFI::MemoryPointer.new(:string)
138
- domain = ::FFI::MemoryPointer.new(:string)
139
- graph_name = ::FFI::MemoryPointer.new(:string)
140
- graph_description = ::FFI::MemoryPointer.new(:string)
141
- producer_name = ::FFI::MemoryPointer.new(:string)
142
- version = ::FFI::MemoryPointer.new(:int64_t)
143
-
144
- metadata = ::FFI::MemoryPointer.new(:pointer)
145
- check_status api[:SessionGetModelMetadata].call(read_pointer, metadata)
139
+ check_status api[:ModelMetadataGetCustomMetadataMapKeys].call(metadata, @allocator, keys, num_keys)
140
+ keys = keys.read_pointer
146
141
 
147
142
  custom_metadata_map = {}
148
- check_status api[:ModelMetadataGetCustomMetadataMapKeys].call(metadata.read_pointer, @allocator.read_pointer, keys, num_keys)
149
143
  num_keys.read(:int64_t).times do |i|
150
- key_ptr = keys.read_pointer[i * ::FFI::Pointer.size]
151
- key = key_ptr.read_pointer.read_string
152
- value = ::FFI::MemoryPointer.new(:string)
153
- check_status api[:ModelMetadataLookupCustomMetadataMap].call(metadata.read_pointer, @allocator.read_pointer, key, value)
144
+ key_ptr = keys.get_pointer(i * ::FFI::Pointer.size)
145
+ key = key_ptr.read_string
146
+ value = ::FFI::MemoryPointer.new(:pointer)
147
+ check_status api[:ModelMetadataLookupCustomMetadataMap].call(metadata, @allocator, key, value)
154
148
  custom_metadata_map[key] = value.read_pointer.read_string
155
149
 
156
150
  allocator_free key_ptr
157
- allocator_free value
151
+ allocator_free value.read_pointer
158
152
  end
159
- allocator_free keys
160
153
 
161
- check_status api[:ModelMetadataGetDescription].call(metadata.read_pointer, @allocator.read_pointer, description)
162
- check_status api[:ModelMetadataGetDomain].call(metadata.read_pointer, @allocator.read_pointer, domain)
163
- check_status api[:ModelMetadataGetGraphName].call(metadata.read_pointer, @allocator.read_pointer, graph_name)
164
- check_status api[:ModelMetadataGetGraphDescription].call(metadata.read_pointer, @allocator.read_pointer, graph_description)
165
- check_status api[:ModelMetadataGetProducerName].call(metadata.read_pointer, @allocator.read_pointer, producer_name)
166
- check_status api[:ModelMetadataGetVersion].call(metadata.read_pointer, version)
154
+ description = ::FFI::MemoryPointer.new(:pointer)
155
+ check_status api[:ModelMetadataGetDescription].call(metadata, @allocator, description)
156
+
157
+ domain = ::FFI::MemoryPointer.new(:pointer)
158
+ check_status api[:ModelMetadataGetDomain].call(metadata, @allocator, domain)
159
+
160
+ graph_name = ::FFI::MemoryPointer.new(:pointer)
161
+ check_status api[:ModelMetadataGetGraphName].call(metadata, @allocator, graph_name)
162
+
163
+ graph_description = ::FFI::MemoryPointer.new(:pointer)
164
+ check_status api[:ModelMetadataGetGraphDescription].call(metadata, @allocator, graph_description)
165
+
166
+ producer_name = ::FFI::MemoryPointer.new(:pointer)
167
+ check_status api[:ModelMetadataGetProducerName].call(metadata, @allocator, producer_name)
168
+
169
+ version = ::FFI::MemoryPointer.new(:int64_t)
170
+ check_status api[:ModelMetadataGetVersion].call(metadata, version)
167
171
 
168
172
  {
169
173
  custom_metadata_map: custom_metadata_map,
@@ -175,19 +179,23 @@ module OnnxRuntime
175
179
  version: version.read(:int64_t)
176
180
  }
177
181
  ensure
178
- release :ModelMetadata, metadata
179
- allocator_free description
180
- allocator_free domain
181
- allocator_free graph_name
182
- allocator_free graph_description
183
- allocator_free producer_name
182
+ allocator_free keys
183
+ allocator_free description.read_pointer
184
+ allocator_free domain.read_pointer
185
+ allocator_free graph_name.read_pointer
186
+ allocator_free graph_description.read_pointer
187
+ allocator_free producer_name.read_pointer
184
188
  end
185
189
 
186
190
  # return value has double underscore like Python
187
191
  def end_profiling
188
- out = ::FFI::MemoryPointer.new(:string)
189
- check_status api[:SessionEndProfiling].call(read_pointer, @allocator.read_pointer, out)
190
- out.read_pointer.read_string
192
+ out = ::FFI::MemoryPointer.new(:pointer)
193
+ check_status api[:SessionEndProfiling].call(@session, @allocator, out)
194
+ begin
195
+ out.read_pointer.read_string
196
+ ensure
197
+ allocator_free out.read_pointer
198
+ end
191
199
  end
192
200
 
193
201
  # no way to set providers with C API yet
@@ -197,10 +205,7 @@ module OnnxRuntime
197
205
  length_ptr = ::FFI::MemoryPointer.new(:int)
198
206
  check_status api[:GetAvailableProviders].call(out_ptr, length_ptr)
199
207
  length = length_ptr.read_int
200
- providers = []
201
- length.times do |i|
202
- providers << out_ptr.read_pointer[i * ::FFI::Pointer.size].read_pointer.read_string
203
- end
208
+ providers = out_ptr.read_pointer.read_array_of_pointer(length).map(&:read_string)
204
209
  api[:ReleaseAvailableProviders].call(out_ptr.read_pointer, length)
205
210
  providers
206
211
  end
@@ -208,7 +213,6 @@ module OnnxRuntime
208
213
  private
209
214
 
210
215
  def load_session(path_or_bytes, session_options)
211
- session = ::FFI::MemoryPointer.new(:pointer)
212
216
  from_memory =
213
217
  if path_or_bytes.respond_to?(:read)
214
218
  path_or_bytes = path_or_bytes.read
@@ -218,44 +222,49 @@ module OnnxRuntime
218
222
  false
219
223
  end
220
224
 
225
+ session = ::FFI::MemoryPointer.new(:pointer)
221
226
  if from_memory
222
- check_status api[:CreateSessionFromArray].call(env.read_pointer, path_or_bytes, path_or_bytes.bytesize, session_options.read_pointer, session)
227
+ check_status api[:CreateSessionFromArray].call(env, path_or_bytes, path_or_bytes.bytesize, session_options, session)
223
228
  else
224
- check_status api[:CreateSession].call(env.read_pointer, ort_string(path_or_bytes), session_options.read_pointer, session)
229
+ check_status api[:CreateSession].call(env, ort_string(path_or_bytes), session_options, session)
225
230
  end
226
- session
231
+ ::FFI::AutoPointer.new(session.read_pointer, api[:ReleaseSession])
227
232
  end
228
233
 
229
234
  def load_inputs
230
- inputs = []
231
235
  num_input_nodes = ::FFI::MemoryPointer.new(:size_t)
232
- check_status api[:SessionGetInputCount].call(read_pointer, num_input_nodes)
233
- num_input_nodes.read(:size_t).times do |i|
234
- name_ptr = ::FFI::MemoryPointer.new(:string)
235
- check_status api[:SessionGetInputName].call(read_pointer, i, @allocator.read_pointer, name_ptr)
236
- # freed in node_info
236
+ check_status api[:SessionGetInputCount].call(@session, num_input_nodes)
237
+
238
+ num_input_nodes.read(:size_t).times.map do |i|
239
+ name_ptr = ::FFI::MemoryPointer.new(:pointer)
240
+ check_status api[:SessionGetInputName].call(@session, i, @allocator, name_ptr)
241
+ name_str = name_ptr.read_pointer.read_string
242
+ allocator_free name_ptr.read_pointer
243
+
237
244
  typeinfo = ::FFI::MemoryPointer.new(:pointer)
238
- check_status api[:SessionGetInputTypeInfo].call(read_pointer, i, typeinfo)
239
- inputs << {name: name_ptr.read_pointer.read_string}.merge(Utils.node_info(typeinfo))
240
- allocator_free name_ptr
245
+ check_status api[:SessionGetInputTypeInfo].call(@session, i, typeinfo)
246
+ typeinfo = ::FFI::AutoPointer.new(typeinfo.read_pointer, api[:ReleaseTypeInfo])
247
+
248
+ {name: name_str}.merge(Utils.node_info(typeinfo))
241
249
  end
242
- inputs
243
250
  end
244
251
 
245
252
  def load_outputs
246
- outputs = []
247
253
  num_output_nodes = ::FFI::MemoryPointer.new(:size_t)
248
- check_status api[:SessionGetOutputCount].call(read_pointer, num_output_nodes)
249
- num_output_nodes.read(:size_t).times do |i|
250
- name_ptr = ::FFI::MemoryPointer.new(:string)
251
- check_status api[:SessionGetOutputName].call(read_pointer, i, @allocator.read_pointer, name_ptr)
252
- # freed in node_info
254
+ check_status api[:SessionGetOutputCount].call(@session, num_output_nodes)
255
+
256
+ num_output_nodes.read(:size_t).times.map do |i|
257
+ name_ptr = ::FFI::MemoryPointer.new(:pointer)
258
+ check_status api[:SessionGetOutputName].call(@session, i, @allocator, name_ptr)
259
+ name_str = name_ptr.read_pointer.read_string
260
+ allocator_free name_ptr.read_pointer
261
+
253
262
  typeinfo = ::FFI::MemoryPointer.new(:pointer)
254
- check_status api[:SessionGetOutputTypeInfo].call(read_pointer, i, typeinfo)
255
- outputs << {name: name_ptr.read_pointer.read_string}.merge(Utils.node_info(typeinfo))
256
- allocator_free name_ptr
263
+ check_status api[:SessionGetOutputTypeInfo].call(@session, i, typeinfo)
264
+ typeinfo = ::FFI::AutoPointer.new(typeinfo.read_pointer, api[:ReleaseTypeInfo])
265
+
266
+ {name: name_str}.merge(Utils.node_info(typeinfo))
257
267
  end
258
- outputs
259
268
  end
260
269
 
261
270
  def create_input_tensor(input_feed)
@@ -285,10 +294,6 @@ module OnnxRuntime
285
294
  ptr
286
295
  end
287
296
 
288
- def read_pointer
289
- @session.read_pointer
290
- end
291
-
292
297
  def check_status(status)
293
298
  Utils.check_status(status)
294
299
  end
@@ -301,27 +306,14 @@ module OnnxRuntime
301
306
  self.class.api
302
307
  end
303
308
 
304
- def release(*args)
305
- self.class.release(*args)
306
- end
307
-
308
309
  def allocator_free(ptr)
309
- api[:AllocatorFree].call(@allocator.read_pointer, ptr.read_pointer)
310
+ api[:AllocatorFree].call(@allocator, ptr)
310
311
  end
311
312
 
312
313
  def self.api
313
314
  FFI.api
314
315
  end
315
316
 
316
- def self.release(type, pointer)
317
- Utils.release(type, pointer)
318
- end
319
-
320
- def self.finalize(addr)
321
- # must use proc instead of stabby lambda
322
- proc { api[:ReleaseSession].call(::FFI::Pointer.new(:pointer, addr)) }
323
- end
324
-
325
317
  # wide string on Windows
326
318
  # char string on Linux
327
319
  # see ORTCHAR_T in onnxruntime_c_api.h
@@ -333,7 +325,8 @@ module OnnxRuntime
333
325
  raise Error, "Expected mbstowcs to return #{str.size}, got #{ret}" if ret != str.size
334
326
  dest
335
327
  else
336
- str
328
+ # prevent frozen string literal warnings
329
+ +str
337
330
  end
338
331
  end
339
332
 
@@ -343,7 +336,7 @@ module OnnxRuntime
343
336
  @@env ||= begin
344
337
  env = ::FFI::MemoryPointer.new(:pointer)
345
338
  check_status api[:CreateEnv].call(3, "Default", env)
346
- at_exit { release :Env, env }
339
+ env = ::FFI::AutoPointer.new(env.read_pointer, api[:ReleaseEnv])
347
340
  # disable telemetry
348
341
  # https://github.com/microsoft/onnxruntime/blob/master/docs/Privacy.md
349
342
  check_status api[:DisableTelemetryEvents].call(env)
@@ -1,9 +1,8 @@
1
1
  module OnnxRuntime
2
2
  class OrtValue
3
3
  def initialize(ptr, ref = nil)
4
- @ptr = ptr.read_pointer
4
+ @ptr = ::FFI::AutoPointer.new(ptr, FFI.api[:ReleaseValue])
5
5
  @ref = ref # keep reference to data
6
- ObjectSpace.define_finalizer(@ptr, self.class.finalize(@ptr.to_i))
7
6
  end
8
7
 
9
8
  def self.from_numo(numo_obj)
@@ -27,14 +26,14 @@ module OnnxRuntime
27
26
  if element_type == :string
28
27
  # keep reference to _str_ptrs until FillStringTensor call
29
28
  input_tensor_values, _str_ptrs = create_input_strings(input)
30
- Utils.check_status FFI.api[:CreateTensorAsOrtValue].call(Utils.allocator.read_pointer, input_node_dims, shape.size, type_enum, ptr)
29
+ Utils.check_status FFI.api[:CreateTensorAsOrtValue].call(Utils.allocator, input_node_dims, shape.size, type_enum, ptr)
31
30
  Utils.check_status FFI.api[:FillStringTensor].call(ptr.read_pointer, input_tensor_values, input_tensor_values.size / input_tensor_values.type_size)
32
31
  else
33
32
  input_tensor_values = create_input_data(input, element_type)
34
- Utils.check_status FFI.api[:CreateTensorWithDataAsOrtValue].call(allocator_info.read_pointer, input_tensor_values, input_tensor_values.size, input_node_dims, shape.size, type_enum, ptr)
33
+ Utils.check_status FFI.api[:CreateTensorWithDataAsOrtValue].call(allocator_info, input_tensor_values, input_tensor_values.size, input_node_dims, shape.size, type_enum, ptr)
35
34
  end
36
35
 
37
- new(ptr, input_tensor_values)
36
+ new(ptr.read_pointer, input_tensor_values)
38
37
  end
39
38
 
40
39
  def self.from_shape_and_type(shape, element_type)
@@ -45,9 +44,9 @@ module OnnxRuntime
45
44
  input_node_dims.write_array_of_int64(shape)
46
45
 
47
46
  ptr = ::FFI::MemoryPointer.new(:pointer)
48
- Utils.check_status FFI.api[:CreateTensorAsOrtValue].call(Utils.allocator.read_pointer, input_node_dims, shape.size, type_enum, ptr)
47
+ Utils.check_status FFI.api[:CreateTensorAsOrtValue].call(Utils.allocator, input_node_dims, shape.size, type_enum, ptr)
49
48
 
50
- new(ptr)
49
+ new(ptr.read_pointer)
51
50
  end
52
51
 
53
52
  def self.create_input_data(input, tensor_type)
@@ -88,6 +87,7 @@ module OnnxRuntime
88
87
  @data_type ||= begin
89
88
  typeinfo = ::FFI::MemoryPointer.new(:pointer)
90
89
  Utils.check_status FFI.api[:GetTypeInfo].call(@ptr, typeinfo)
90
+ typeinfo = ::FFI::AutoPointer.new(typeinfo.read_pointer, FFI.api[:ReleaseTypeInfo])
91
91
  Utils.node_info(typeinfo)[:type]
92
92
  end
93
93
  end
@@ -134,13 +134,10 @@ module OnnxRuntime
134
134
 
135
135
  def type_and_shape_info
136
136
  @type_and_shape_info ||= begin
137
- begin
138
- typeinfo = ::FFI::MemoryPointer.new(:pointer)
139
- Utils.check_status FFI.api[:GetTensorTypeAndShape].call(@ptr, typeinfo)
140
- Utils.tensor_type_and_shape(typeinfo)
141
- ensure
142
- Utils.release :TensorTypeAndShapeInfo, typeinfo
143
- end
137
+ typeinfo = ::FFI::MemoryPointer.new(:pointer)
138
+ Utils.check_status FFI.api[:GetTensorTypeAndShape].call(@ptr, typeinfo)
139
+ typeinfo = ::FFI::AutoPointer.new(typeinfo.read_pointer, FFI.api[:ReleaseTensorTypeAndShapeInfo])
140
+ Utils.tensor_type_and_shape(typeinfo)
144
141
  end
145
142
  end
146
143
 
@@ -153,6 +150,7 @@ module OnnxRuntime
153
150
  when :tensor
154
151
  typeinfo = ::FFI::MemoryPointer.new(:pointer)
155
152
  Utils.check_status FFI.api[:GetTensorTypeAndShape].call(out_ptr, typeinfo)
153
+ typeinfo = ::FFI::AutoPointer.new(typeinfo.read_pointer, FFI.api[:ReleaseTensorTypeAndShapeInfo])
156
154
 
157
155
  type, shape = Utils.tensor_type_and_shape(typeinfo)
158
156
 
@@ -160,11 +158,9 @@ module OnnxRuntime
160
158
  Utils.check_status FFI.api[:GetTensorMutableData].call(out_ptr, tensor_data)
161
159
 
162
160
  out_size = ::FFI::MemoryPointer.new(:size_t)
163
- Utils.check_status FFI.api[:GetTensorShapeElementCount].call(typeinfo.read_pointer, out_size)
161
+ Utils.check_status FFI.api[:GetTensorShapeElementCount].call(typeinfo, out_size)
164
162
  output_tensor_size = out_size.read(:size_t)
165
163
 
166
- Utils.release :TensorTypeAndShapeInfo, typeinfo
167
-
168
164
  # TODO support more types
169
165
  type = FFI::TensorElementDataType[type]
170
166
 
@@ -203,20 +199,22 @@ module OnnxRuntime
203
199
 
204
200
  out.read(:size_t).times.map do |i|
205
201
  seq = ::FFI::MemoryPointer.new(:pointer)
206
- Utils.check_status FFI.api[:GetValue].call(out_ptr, i, Utils.allocator.read_pointer, seq)
202
+ Utils.check_status FFI.api[:GetValue].call(out_ptr, i, Utils.allocator, seq)
207
203
  create_from_onnx_value(seq.read_pointer, output_type)
208
204
  end
209
205
  when :map
210
- type_shape = ::FFI::MemoryPointer.new(:pointer)
211
206
  map_keys = ::FFI::MemoryPointer.new(:pointer)
207
+ Utils.check_status FFI.api[:GetValue].call(out_ptr, 0, Utils.allocator, map_keys)
208
+
212
209
  map_values = ::FFI::MemoryPointer.new(:pointer)
213
- elem_type = ::FFI::MemoryPointer.new(:int)
210
+ Utils.check_status FFI.api[:GetValue].call(out_ptr, 1, Utils.allocator, map_values)
214
211
 
215
- Utils.check_status FFI.api[:GetValue].call(out_ptr, 0, Utils.allocator.read_pointer, map_keys)
216
- Utils.check_status FFI.api[:GetValue].call(out_ptr, 1, Utils.allocator.read_pointer, map_values)
212
+ type_shape = ::FFI::MemoryPointer.new(:pointer)
217
213
  Utils.check_status FFI.api[:GetTensorTypeAndShape].call(map_keys.read_pointer, type_shape)
218
- Utils.check_status FFI.api[:GetTensorElementType].call(type_shape.read_pointer, elem_type)
219
- Utils.release :TensorTypeAndShapeInfo, type_shape
214
+ type_shape = ::FFI::AutoPointer.new(type_shape.read_pointer, FFI.api[:ReleaseTensorTypeAndShapeInfo])
215
+
216
+ elem_type = ::FFI::MemoryPointer.new(:int)
217
+ Utils.check_status FFI.api[:GetTensorElementType].call(type_shape, elem_type)
220
218
 
221
219
  # TODO support more types
222
220
  elem_type = FFI::TensorElementDataType[elem_type.read_int]
@@ -255,23 +253,17 @@ module OnnxRuntime
255
253
  end
256
254
 
257
255
  def reshape(arr, dims)
258
- arr = arr.flatten
259
256
  dims[1..-1].reverse_each do |dim|
260
257
  arr = arr.each_slice(dim)
261
258
  end
262
259
  arr.to_a
263
260
  end
264
261
 
265
- def self.finalize(addr)
266
- # must use proc instead of stabby lambda
267
- proc { FFI.api[:ReleaseValue].call(::FFI::Pointer.new(:pointer, addr)) }
268
- end
269
-
270
262
  def self.allocator_info
271
263
  @allocator_info ||= begin
272
264
  allocator_info = ::FFI::MemoryPointer.new(:pointer)
273
265
  Utils.check_status FFI.api[:CreateCpuMemoryInfo].call(1, 0, allocator_info)
274
- allocator_info
266
+ ::FFI::AutoPointer.new(allocator_info.read_pointer, FFI.api[:ReleaseMemoryInfo])
275
267
  end
276
268
  end
277
269
  end