From: Chris Uzdavinis Date: 2001-11-17T00:48:56+09:00 Subject: [ruby-talk:25451] Re: embedding C++ Matthias Lampert writes: > > There are a few ways to do this. One slowish way is to > > heap-allocate all your C++ objects and keep track of them in a global > > structure. You can stuff these objects into Ruby objects and let the > > Ruby garbage collector take care of the memory for you if you'd like. > > (But you still need to keep track of those ruby objects somewhere so > > you can mark them for the garbage collector while you're still using > > them.) > > That's certainly the easiest solution. By the way, Java has become > tremendously popular among coders despite or even for handling matters > just like that. In reality, I think that just creating "local" variables on the heap and stuffing them into the ruby garbage collector is all that would need to be done. Being that ruby (the interpreter) is single threaded, it would not be possible for the GC to be invoked while in the middle of our function call. Therefore, the local variables would be out of scope by the time the GC runs, so we would not need to store the ruby objects at all, and would not need to mark them to stay alive. > > Another thing you can do is create local scopes around local > > variables in such a way that they always go out of scope before > > any ruby function that can possibly "throw" is called. This is a > > variation of the design rule of "don't allow ANY stack-based > > variables to exist who need a destructor invoked to exist when you > > call ruby functions." > > That seems to me the most performative solution, and as far as I can see, > it's also the cleanest. .... when it works. There are cases where this just isn't possible. A "smart pointer" in C++ will hold a raw pointer, and will clean it up in its destructor. But it depends on the stack. For example, I use Ruby to wrap CORBA calls. A CORBA sequence is like an array, but it is a variable length object and is therefore allocated on the heap. If I want to make this sequence accessible to my Ruby script, I need to do the following: 1) make the corba call to get the sequence 2) make a ruby array object 3) iterate through the sequence, creating corresponding ruby elements and pushing those elements into the (ruby) array object In this case, my CORBA sequence must be cleaned up or it will leak, but it must exist while I'm creating the ruby array. Normally, you would use a CORBA _var object--a smart pointer--which automatically manages the reference count on the sequence, and when it goes out of scope, it decrements the reference count and the sequence is freed. However, if creating one of the ruby elements causes a ruby exception to be raised, my sequence will leak because the _var object is not destroyed. This is one of those cases where it's just not possible to use the "no C++ objects exist while a ruby function is called" rule, because it must exist, by definition. I think wrapping the sequence in a ruby object is the best way to go. Then we still have automatic cleanup, but it may be delayed a bit. But it is safe and works. > > A final way to accomplish this may be to use setjmp yourself in > > each of your C++ functions, however I have not experimented at all > > with this approach and it sounds like a high-overhead solution. > > I don't know yet what calling setjmp implies. As for my own code, I > could manipulate XEmacs to automatically produce markers in my > methods that can be handled by some useful tool (Ruby, for instance) > to be converted into the appropriate C++ code. Just two other lines > in the Makefile ought to do the job in time. The ruby exception handling functions themselves could encapsulate this. For example we could always make calls to ruby functions in a rb_rescue function call, but that would absorb the exception and our script wouldn't see it. I'm not ashamed to admit how inexperienced with longjmp I am. > Of course, this can't easily be done on third-party code... > And what about third-party C++ code that throws exceptions > itself? ... > Honestly, I consider obtaining some more tobacco! I have solved the problem of C++ exceptions being thrown while inside a ruby function. I'll describe that sometime. > Some German success trainer said: If you have a problem you can't > solve, tell the world that there's a problem and it WILL be solved. Thanks. That's just the encouragement I need. :) -- Chris