2

I have a situation where I need to hold a reference to a Ruby object (instance of VALUE) SOLELY from a C struct; i.e., the Ruby object is created and passed to the C library.

Currently, the Ruby object stays valid so long as, somewhere in my Ruby app, something else also reference the object. But as soon as the only reference to the object is held by the C struct, garbage collection reaps it since mark-and-sweep no longer can find it.

I need a way to keep such objects alive; i.e., I want them to live until such a time as either the C struct is released or else the object's reference is removed.

mcpierce
  • 312
  • 5
  • 16
  • 2
    Basically, call `rb_gc_mark` on it . . . but how to set this up depends on your existing C/Ruby integration. Could you show some relevant code? The most important part is how you set up the object. Are you using `Data_Wrap_Struct` for instance to create a Ruby-accessible ref to the C struct? – Neil Slater Mar 06 '15 at 13:47
  • You can see the code I'm working on [here](http://github.com/mcpierce/Proton/tree/PROTON-799-Ruby-engine-apis) in the proton-c/bindings/ruby directory. Our project uses Swig to generate the majority of the bindings, with my being able to add additional bits through the ruby.i file in the ruby language directory. – mcpierce Mar 06 '15 at 18:31
  • Unfortunately I am not sure of how to make necessary changes to a Swig project, although I suspect it is the same and Swig may well of created the function you need to edit already. In addition, I am not sure anyone will go looking through your whole project in order to figure out how to help you. To prevent that blocking you, please add relevant information and code into the question (there is an *edit* link just under the tag list). – Neil Slater Mar 06 '15 at 18:43

1 Answers1

0

Sorry it's been a while since I followed up on this. In the end.

I had tried attaching the Ruby object to the Swig wrapper for the C struct, but Swig does not guarantee that those wrappers will be idempotent. IOW, if I got a wrapper for a C struct and then asked for another reference to the same struct, the two wrappers were different objects and did not equate.

Additionally, if the Swig wrapper object goes out of scope, even if the C struct isn't GC'd, the reference would go away and my Ruby object would get reaped as well.

In the end, the solution was to create a Ruby hash and to hook into the C libraries lifecycle events; i.e., when a C struct that references a Ruby object is GC'd then remove the Ruby object from the hash.

In the end it was the only way to do this.

mcpierce
  • 312
  • 5
  • 16