gga, gga wrote: > GD ha escrito: > >>I'm keeping things fairly simple; I mostly just bind functions/methods >>and wrap pointers in opaque data structures (eg. using Data_Wrap_Struct >>in the Ruby version). My plan was to store a pointer to the calling class >>in an opaque structure and store it in the corresponding Ruby class, so >>I can reference it when needed. > > > That's possible, but it can get ugly. Do what SWIG does. Create a > hash that stores a mapping between the ruby object and the C++ object > (and/or viceversa). Every time you allocate a new class, you enter it > in the hash. Every time the free function for the class is called, the > mapping is removed from the hash. > You can even use ruby's own hashes to do so. > That way, you don't need to pass any pointer, and can access any class > at any time from any function. > Also, if your classes contain or return pointers to other C++ classes, > you need to keep telling the GC about it. See the SWIG Zoo/Animal > tutorial in the Ruby section. This is an interesting idea but may be overkill for what I'm trying to do. >> >>- The documentation is not at all clear how you protect something from the >> >>garbage collector, or indicate it is no longer in use. >> > >> >>Should some of the tricks used by SWIG be mentioned on the official >>Ruby site, perhaps? Seems odd that an offsite source is considered >>(mildly) authoritative. > > > Well, all that stuff IS properly documented in the PickAxe, in the > extending Ruby section. The PickAxe is somewhat poor in that it does > cover properly wrapping methods that return new C++ objects (the Zoo > and Animal tutorial in SWIG is a top-notch example of all the headaches > you can run into on wrapping a complex library). The online version of the PickAxe has been my main reference. It is missing a bit of info, generally relating to marking and garbage collection. My secondary reference... > You also have this, if you haven't read it. > > http://metaeditor.sourceforge.net/embed/ > > I found it somewhat confusing, but it is probably another source. ... is this one. This one fills in some of the gaps from the first. It is no literary masterpiece but it is quite useful. >>Okay, so just like an object. Good news. Very elegant and Ruby-ish. :) >>Any way to grab the class from the Ruby script? What I really want is >>to replace your first line with something like: >> >>VALUE cFoo = rb_grab_class_from_script("ClassDefinedInScript") >> > > > Class names are just constants. > If your class is in the global namespace, use: > > VALUE cFoo = rb_const_get( rb_cObject, rb_intern("YourClass") ); > > If not, replace rb_cObject for the proper module name. This I didn't know. So class names are basically constants and can be accessed that way. > VALUE result = rb_protect( wrap_callback, VALUE(&data), &error ); You can do this!? Is this safe? It would seem to work on the idea that VALUE is always going to be of sufficient size and structure to hold a pointer directly. Is there any authoritative source that says: "directly casting a pointer to a VALUE is perfectly fine and will continue to be supported". If so, VALUE can be used (effectively) in the same way as a void*, so there is no need to convert everything into Ruby objects as I had thought. If not, I'm not sure this call can be counted on to work reliably in the future. >>The Python docs look decent, I'd just rather not relearn Python again, >>I chose Ruby years ago, I'm good with it, and I like it better than >>Python! :) But I'd rather move on from LUA if I can... > > Python is worse at embedding than Ruby is. So if you have troubles > with Ruby, good luck with Python! On python you don't need to just > take care of garbage collecting, but of reference counting. It is a > royal pain if you are doing it manually like you are. I'll probably give it a shot for interest's sake. Looking closer at the Python docs that don't seem as strong as first impressions suggest, although there are some decent examples. >>I've spent close to two days on embedding Ruby and can't get the basic >>things I've described working. > > You should be able to get ruby up and running in about a couple of > hours (that's all it took me). Yes, I should (something basic anyway). Unfortunately, I didn't (*). This is the problem. When such difficulties arise, they can suggest: - it is the user's fault; or - there is a problem with the documentation; or - the interface is unintuitive; or - the library itself is buggy. I shouldn't have to explain why the likelihood of the first reduces significantly with the number of external libraries the user has successfully integrated in the past and the number of years they have been working in software development. Any of the remaining three are worth bringing to the attention of the dev gods. Anyway I'm hoping that someone with the requisite knowledge spots these posts, thinks "hey, perhaps we could look again at issue X" and something comes of my experiences here. Or perhaps not, but nobody can say I never mentioned it. Ultimately, the selfish aspect of my motivation is that someone spots these posts, and dispenses some form of guru-like wisdom that instantly solves the problems I am having. Googling some of the error messages I am seeing and issues I am facing suggest I may not be alone. (*) - Technically I _did_ in a couple of hours, but it wasn't stable and crashed randomly, so I tried to figure out what was going wrong. No luck. > Wrapping complex classes that return > pointers to other classes and the like, however, is hairy. But SWIG is > there to help now. > >>I dearly want to be completely wrong. > > You are. That was unwarranted. Anyway, in this exchange a number of issues have come up that an experienced Ruby user (definitely not a guru though!) completely new to the embedded interface tripped up on completely. I would suggest that a good place for these little tips and tricks that keep coming up would be somewhere near the official documentation, so that the next person who comes along to play with embedded Ruby can start off slightly further ahead than I did. Garth