The most important thing to get worked out for this is the memory
management semantics between C and Ruby. From what I can tell from your
branch, it looks like you haven't done that yet.

As I've said before, the first step to wrapping the engine API is to work
out a simple strategy for wrapping C objects from the host language. In the
case of python this is done with the wrapper.py mixin. It uses various
python hooks as well as elements of python's C extension API to allow C
objects to hold references to python objects and keep them alive according
to python's memory management semantics. Just translating this wrapper code
from python to ruby won't do much good as Ruby's memory management
semantics are different and it's C extension API is different.

The first step you should take before bothering to wrap any code is to
figure out how you can have C objects hold pointers to ruby objects without
either incurring memory leaks or seg faults. Judging from what you've done
in ruby.i:

+ static void pn_rbref_incref(void *object) {  + // no reference counting
in Ruby  + }  +  + static void pn_rbref_decref(void *object) {  + // no
reference counting in Ruby  + }  +  + static int pn_rbref_refcount(void
*object) {  + return 1;  + }  +  + static const pn_class_t
*pn_rbref_reify(void *object) {  + return PN_RBREF;  + }

I suspect if you were to actually try anything significant you would incur
either seg faults or memory leaks or both, depending on precisely how Ruby
GC works. The excerpt from your branch above is creating a class of pointer
that will lie to proton and tell it that it always has a reference when it
doesn't really, and yet also lie to the Ruby VM because it is keeping a
pointer to a Ruby object without any way for the Ruby GC mechanism to be
informed.

I recommend starting with a very simple test case for one object, i.e.
define a wrapper mixin for ruby and use it to wrap just one proton object,
e.g. Connection. Don't bother with wrapping any of the methods on
Connection, all you really want to do is verify that object
creation/deletion works properly. Once you've done that you can run
creation/deletion in a  loop and verify that you don't leak memory. Before
this though, you'll need to read up on Ruby's C extension API in order to
figure out how to interface to it's memory management system so that the C
objects can hold pointers to Ruby objects and actually keep them alive, and
also free them when the C objects go away. Until you can do this and get
the basic loop test working with a simple object, there isn't really much
point in trying to wrap anything else.

--Rafael

On Wed, Jan 21, 2015 at 2:22 PM, Darryl L. Pierce <dpie...@redhat.com>
wrote:

> I've been working on providing the low-level engine APIs in Ruby over
> the past few weeks, and from what I can see I think I'm near to
> completion regarding wrapping them.
>
> However, I'm not sure if I'm missing something since I don't see a way
> to use the code to create a connection. :D
>
> Specifically, what I want to do next is create examples of working with
> these low-level APIs, initially a simple send/receive example would be
> best with a receiver that listens for a connection and a sender that
> connects to it, all while being able to toggle tracing the
> communication, etc. I see nothing existing for other languages to use as
> a guide, so am a little stumped at the moment.
>
> The work I've done to date is here:
>
> https://github.com/mcpierce/Proton/tree/PROTON-799-Ruby-engine-apis
>
> --
> Darryl L. Pierce, Sr. Software Engineer @ Red Hat, Inc.
> Delivering value year after year.
> Red Hat ranks #1 in value among software vendors.
> http://www.redhat.com/promo/vendor/
>
>

Reply via email to