rdkit-rb 0.1.3 → 0.1.4

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: de1fbdf8335abfdf268303d9d236fad4baaf6fcbfb467a5891c3964756d9ce08
4
- data.tar.gz: 5ddcfc7d66cb137fe609094a7d0a0a964cb72e42803084e56b0b55ce8994d988
3
+ metadata.gz: c0a8054f7d7636d54bb74c37a0767f39c5ac39618f56b634bfc0deac77c7be13
4
+ data.tar.gz: 9fc6f39cfc0f9b683d538fb8e7ce567ed147513085b6b6e06053a1ec5551ce8c
5
5
  SHA512:
6
- metadata.gz: ada580d3d792cd300fb8080d57e33f6e996c62996b577b4b356cd6413bbba49e8849017ab1d3ff00c6e367d1886132150422736e9f4e86243385d13dae320aff
7
- data.tar.gz: 8f18f2ce745ba8ec893f4e95ada45130a4a65b6b6e9a3e4aac39209bf961d07cc50d533d8db03235f213588350cb862201f010a714ccef62540d270e5eb8c8c1
6
+ metadata.gz: 0a000053252d7c363f5e24f2c7670650d5097c808372cd93de6fa6c8723382f3a918baef986dbd21db3d83a77125352a9bf6efbd7690c31492dc9d80551f27a3
7
+ data.tar.gz: 47de8c95416133f86cc9abde50778939536e12a2d10cc74bfb90df72547b0572d670b1013c136f8e7aaa0b13fa7cc46fa26cb29eeccb3f8bfe13840c920901be
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ ## 0.1.4 (2025-05-04)
2
+
3
+ - Fixed memory leaks
4
+
1
5
  ## 0.1.3 (2024-12-29)
2
6
 
3
7
  - Fixed warning with Ruby 3.4
data/lib/rdkit/ffi.rb CHANGED
@@ -70,7 +70,7 @@ module RDKit
70
70
 
71
71
  # housekeeping
72
72
  # treat as void *ptr since calls free() internally
73
- FREE = extern "void free_ptr(char *ptr)"
73
+ extern "void free_ptr(char *ptr)"
74
74
 
75
75
  # other
76
76
  extern "char *version()"
@@ -46,15 +46,19 @@ module RDKit
46
46
  end
47
47
 
48
48
  def fragments(sanitize: true)
49
- sz_arr = Fiddle::Pointer.malloc(Fiddle::SIZEOF_VOIDP)
50
- num_frags = Fiddle::Pointer.malloc(Fiddle::SIZEOF_SIZE_T)
49
+ sz_arr = Fiddle::Pointer.malloc(Fiddle::SIZEOF_VOIDP, Fiddle::RUBY_FREE)
50
+ num_frags = Fiddle::Pointer.malloc(Fiddle::SIZEOF_SIZE_T, Fiddle::RUBY_FREE)
51
51
  details = {
52
52
  sanitizeFrags: sanitize
53
53
  }
54
- arr = FFI.get_mol_frags(@ptr, @sz, sz_arr.ref, num_frags.ref, to_details(details), nil)
54
+ arr = FFI.get_mol_frags(@ptr, @sz, sz_arr, num_frags, to_details(details), nil)
55
55
  check_ptr(arr)
56
+ arr.free = FFI["free_ptr"]
57
+ sz_arr = sz_arr.ptr
58
+ sz_arr.free = FFI["free_ptr"]
56
59
 
57
- num_frags.to_i.times.map do |i|
60
+ num = num_frags.to_str(Fiddle::SIZEOF_SIZE_T).unpack1(Fiddle::SIZEOF_SIZE_T == 4 ? "L" : "Q")
61
+ num.times.map do |i|
58
62
  ptr = (arr + i * Fiddle::SIZEOF_VOIDP).ptr
59
63
  sz = (sz_arr + i * Fiddle::SIZEOF_SIZE_T).ptr
60
64
 
@@ -62,9 +66,6 @@ module RDKit
62
66
  mol.send(:load_ptr, ptr, sz)
63
67
  mol
64
68
  end
65
- ensure
66
- free_ptr(sz_arr)
67
- free_ptr(arr)
68
69
  end
69
70
 
70
71
  def rdkit_fingerprint(min_path: 1, max_path: 7, length: 2048, bits_per_hash: 2, use_hs: true, branched_paths: true, use_bond_order: true)
@@ -145,8 +146,7 @@ module RDKit
145
146
  end
146
147
 
147
148
  def add_hs!
148
- check_status(FFI.add_hs(@ptr.ref, @sz.ref))
149
- self
149
+ modify(:add_hs)
150
150
  end
151
151
 
152
152
  def remove_hs
@@ -154,8 +154,7 @@ module RDKit
154
154
  end
155
155
 
156
156
  def remove_hs!
157
- check_status(FFI.remove_all_hs(@ptr.ref, @sz.ref))
158
- self
157
+ modify(:remove_all_hs)
159
158
  end
160
159
 
161
160
  def cleanup
@@ -163,8 +162,7 @@ module RDKit
163
162
  end
164
163
 
165
164
  def cleanup!
166
- check_status(FFI.cleanup(@ptr.ref, @sz.ref, to_details({})))
167
- self
165
+ modify(:cleanup, to_details({}))
168
166
  end
169
167
 
170
168
  def normalize
@@ -172,8 +170,7 @@ module RDKit
172
170
  end
173
171
 
174
172
  def normalize!
175
- check_status(FFI.normalize(@ptr.ref, @sz.ref, to_details({})))
176
- self
173
+ modify(:normalize, to_details({}))
177
174
  end
178
175
 
179
176
  def neutralize
@@ -181,8 +178,7 @@ module RDKit
181
178
  end
182
179
 
183
180
  def neutralize!
184
- check_status(FFI.neutralize(@ptr.ref, @sz.ref, to_details({})))
185
- self
181
+ modify(:neutralize, to_details({}))
186
182
  end
187
183
 
188
184
  def reionize
@@ -190,8 +186,7 @@ module RDKit
190
186
  end
191
187
 
192
188
  def reionize!
193
- check_status(FFI.reionize(@ptr.ref, @sz.ref, to_details({})))
194
- self
189
+ modify(:reionize, to_details({}))
195
190
  end
196
191
 
197
192
  def canonical_tautomer
@@ -199,8 +194,7 @@ module RDKit
199
194
  end
200
195
 
201
196
  def canonical_tautomer!
202
- check_status(FFI.canonical_tautomer(@ptr.ref, @sz.ref, to_details({})))
203
- self
197
+ modify(:canonical_tautomer, to_details({}))
204
198
  end
205
199
 
206
200
  def charge_parent
@@ -208,8 +202,7 @@ module RDKit
208
202
  end
209
203
 
210
204
  def charge_parent!
211
- check_status(FFI.charge_parent(@ptr.ref, @sz.ref, to_details({})))
212
- self
205
+ modify(:charge_parent, to_details({}))
213
206
  end
214
207
 
215
208
  def fragment_parent
@@ -217,8 +210,7 @@ module RDKit
217
210
  end
218
211
 
219
212
  def fragment_parent!
220
- check_status(FFI.fragment_parent(@ptr.ref, @sz.ref, to_details({})))
221
- self
213
+ modify(:fragment_parent, to_details({}))
222
214
  end
223
215
 
224
216
  def to_smiles
@@ -262,20 +254,20 @@ module RDKit
262
254
  end
263
255
 
264
256
  def load_smiles(input, sanitize: true, kekulize: true, remove_hs: true)
265
- sz = Fiddle::Pointer.malloc(Fiddle::SIZEOF_SIZE_T)
257
+ sz = Fiddle::Pointer.malloc(Fiddle::SIZEOF_SIZE_T, Fiddle::RUBY_FREE)
266
258
  details = {
267
259
  sanitize: sanitize,
268
260
  kekulize: kekulize,
269
261
  removeHs: remove_hs
270
262
  }
271
- ptr = FFI.get_mol(input.to_str, sz.ref, to_details(details))
272
- load_ptr(ptr, sz)
263
+ ptr = FFI.get_mol(+input.to_str, sz, to_details(details))
264
+ load_ptr(ptr, Utils.read_size(sz))
273
265
  end
274
266
 
275
267
  def load_smarts(input)
276
- sz = Fiddle::Pointer.malloc(Fiddle::SIZEOF_SIZE_T)
277
- ptr = FFI.get_qmol(input.to_str, sz.ref, to_details({}))
278
- load_ptr(ptr, sz)
268
+ sz = Fiddle::Pointer.malloc(Fiddle::SIZEOF_SIZE_T, Fiddle::RUBY_FREE)
269
+ ptr = FFI.get_qmol(+input.to_str, sz, to_details({}))
270
+ load_ptr(ptr, Utils.read_size(sz))
279
271
  end
280
272
 
281
273
  def load_ptr(ptr, sz)
@@ -284,7 +276,7 @@ module RDKit
284
276
  end
285
277
 
286
278
  @ptr = ptr
287
- @ptr.free = FFI::FREE
279
+ @ptr.free = FFI["free_ptr"]
288
280
  @sz = sz
289
281
  end
290
282
 
@@ -313,22 +305,15 @@ module RDKit
313
305
  end
314
306
 
315
307
  def check_ptr(ptr)
316
- if ptr.nil? || ptr.null?
308
+ if ptr.null?
317
309
  raise Error, "bad pointer"
318
310
  end
319
311
  end
320
312
 
321
- def free_ptr(ptr)
322
- FFI.free_ptr(ptr) if ptr
323
- end
324
-
325
313
  def check_string(ptr)
326
314
  check_ptr(ptr)
327
- begin
328
- ptr.to_s
329
- ensure
330
- free_ptr(ptr)
331
- end
315
+ ptr.free = FFI["free_ptr"]
316
+ ptr.to_s
332
317
  end
333
318
 
334
319
  def check_status(status)
@@ -336,5 +321,13 @@ module RDKit
336
321
  raise Error, "bad status: #{status}"
337
322
  end
338
323
  end
324
+
325
+ def modify(op, *args)
326
+ # TODO write as size_t
327
+ sz = Fiddle::Pointer.new(@sz)
328
+ check_status(FFI[op.to_s].call(@ptr.ref, sz.ref, *args))
329
+ @sz = Utils.read_size(sz.ref)
330
+ self
331
+ end
339
332
  end
340
333
  end
@@ -24,10 +24,10 @@ module RDKit
24
24
  private
25
25
 
26
26
  def load_rxn(input)
27
- sz = Fiddle::Pointer.malloc(Fiddle::SIZEOF_SIZE_T)
27
+ sz = Fiddle::Pointer.malloc(Fiddle::SIZEOF_SIZE_T, Fiddle::RUBY_FREE)
28
28
  @input = input.to_str
29
- ptr = FFI.get_rxn(@input, sz.ref, to_details({}))
30
- load_ptr(ptr, sz)
29
+ ptr = FFI.get_rxn(+@input, sz, to_details({}))
30
+ load_ptr(ptr, Utils.read_size(sz))
31
31
  end
32
32
 
33
33
  def load_ptr(ptr, sz)
@@ -36,7 +36,7 @@ module RDKit
36
36
  end
37
37
 
38
38
  @ptr = ptr
39
- @ptr.free = FFI::FREE
39
+ @ptr.free = FFI["free_ptr"]
40
40
  @sz = sz
41
41
  end
42
42
 
@@ -45,22 +45,15 @@ module RDKit
45
45
  end
46
46
 
47
47
  def check_ptr(ptr)
48
- if ptr.nil? || ptr.null?
48
+ if ptr.null?
49
49
  raise Error, "bad pointer"
50
50
  end
51
51
  end
52
52
 
53
- def free_ptr(ptr)
54
- FFI.free_ptr(ptr) if ptr
55
- end
56
-
57
53
  def check_string(ptr)
58
54
  check_ptr(ptr)
59
- begin
60
- ptr.to_s
61
- ensure
62
- free_ptr(ptr)
63
- end
55
+ ptr.free = FFI["free_ptr"]
56
+ ptr.to_s
64
57
  end
65
58
  end
66
59
  end
@@ -0,0 +1,8 @@
1
+ module RDKit
2
+ module Utils
3
+ def self.read_size(ptr)
4
+ # TODO read as size_t
5
+ ptr.ptr.to_i
6
+ end
7
+ end
8
+ end
data/lib/rdkit/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module RDKit
2
- VERSION = "0.1.3"
2
+ VERSION = "0.1.4"
3
3
  end
data/lib/rdkit.rb CHANGED
@@ -6,6 +6,7 @@ require "json"
6
6
  require_relative "rdkit/molecule"
7
7
  require_relative "rdkit/reaction"
8
8
  require_relative "rdkit/version"
9
+ require_relative "rdkit/utils"
9
10
 
10
11
  module RDKit
11
12
  class Error < StandardError; end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rdkit-rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kane
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2024-12-29 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: fiddle
@@ -36,6 +36,7 @@ files:
36
36
  - lib/rdkit/ffi.rb
37
37
  - lib/rdkit/molecule.rb
38
38
  - lib/rdkit/reaction.rb
39
+ - lib/rdkit/utils.rb
39
40
  - lib/rdkit/version.rb
40
41
  - vendor/aarch64-linux/ChemReactions-license.txt
41
42
  - vendor/aarch64-linux/librdkitcffi.so
@@ -75,7 +76,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
75
76
  - !ruby/object:Gem::Version
76
77
  version: '0'
77
78
  requirements: []
78
- rubygems_version: 3.6.2
79
+ rubygems_version: 3.6.7
79
80
  specification_version: 4
80
81
  summary: Cheminformatics for Ruby, powered by RDKit
81
82
  test_files: []