From: emilie3012@... (Steve Hart) Date: 2003-04-10T09:01:55+09:00 Subject: Re: embedding ruby with swig "Simon Strandgaard" <0bz63fz3m1qt3001@sneakemail.com> wrote in message news:... > On Tue, 08 Apr 2003 19:56:33 +0000, Steve Hart wrote: > > > The scripts are loaded into a stack within my c++ code > > I have a c++ class 'GMScript' and have used swig to wrap into ruby > > I use a ruby script that inherits this class > > i.e. > > class Test1 < Gm::GMScript > > > > def initialize(sg,p1,p2) > > > > super(sg,p1,p2) > > > > @object1 = Gm::GMObjectNode.new("object1") > > end > > . > > . > > . > > end > > I had some trouble with extending a SWIG-class, it resulted > in a exception: nameerror. > You are using inheiritance, no problems here. > > > > in c++ I call at start > > > > ruby_init(); > > ruby_init_loadpath(); > > ruby_script("embedded"); > > rb_require("gm.so"); - swigged up wrapper lib > > Look fine. > > > > then each time a script load is requested i do the following (protect > > code removed for clarity) > > > > rb_load_protect(rb_str_new2("Test1.rb"),Qfalse,&state); > > > > then > > oClass = rb_const_get(rb_cObject, rb_intern("Test1")); > > scriptObject = rb_funcall(oClass, rb_intern("new"), > > 3,sgValue,pathName,className); > > Data_Get_Struct(scriptObject,GMScript,scriptPtr); > > scriptPtr->obj = scriptObject; > > This code could be the problem. > * bootstrapping of your swig class. > * you are not registering scriptObject, so GC won't know that its > in usage and thus thinks it must get killed. > > How does your SWIG interface file look like ??? > If it includes a .H file how does it look like ??? > > > > The problem is that as I load more scripts previous scripts get freed > > of by the GC. In addition, the GMObjectNode's created within the > > Scripts are also freed. > > Sounds like you object is holding ruby-childen. > You will need to do rb_mark on thise. > > > > What I want to do is only free off the Script > > when the user deletes it > > from the script stack and decide at this time if the GMObjectNode > > should > > also be deleted. I assumed that since the scriptObject is stored > > within the C code the GC would not free these off (or is it because > > the scriptObject is stored in GMScript superclass itself. > > Wrong assumption. It depends on wheter or not you have registered > your scriptObject. > > > > I cannot > > mark the object since this is under the control of Swig. I have tried > > > > rb_global_variable(&scriptObject) > > > > but this does not prevent the freeing and in addition crashes the > > program with an error: > > How did you "try" it ??? > > > Read my text on embedding, look at the tar.gz file :-) > http://metaeditor.sourceforge.net/embed/ Thanks for reply - i looked at your tgz last night (as well as vim and mod_ruby.) Thats how I've got this far! Sorry for denseness but what does bootstrapping swig class mean and why is it bad. ? I have had a chance to look into problem further and found swig now supports user defined mark and free functions. I have defined these in the interface file but still no joy. This is a cut down version of my code: gm.i: ^^^^ %module gm %{ #include "GMScript.h" %} %{ static void GMScript_freefunc(void *ptr) { cerr << "FREE\n"; GMScript *script = (GMScript *) ptr; delete script; } %} %{ static void GMScript_markfunc(void *ptr) { cerr << "MARK\n"; GMScript *script = (GMScript *) ptr; rb_gc_mark(reinterpret_cast((script->scriptObj))); } %} %markfunc GMScript "GMScript_markfunc" %freefunc GMScript "GMScript_freefunc" %include GMScript.h GMScript.h ^^^^^^^^^^ #ifndef _GMSCRIPT_H #define _GMSCRIPT_H #include using namespace std; #include class GMScript { public: GMScript(); ~GMScript(); VALUE scriptObj; }; #endif GMScript.cpp ^^^^^^^^^^^^ #include "GMScript.h" /*****************************************/ GMScript::GMScript() { cerr << "GMScript::GMScript\n"; } /*****************************************/ GMScript::~GMScript() { cerr << "GMScript::~GMScript\n"; } main.c ^^^^^^ int main() { GMScript *ptr = NULL; int state = 0; VALUE vTclass; VALUE tObj; vector stack; ruby_init(); ruby_script("embedded"); ruby_init_loadpath(); rb_require("gm.so"); for(;;) { rb_load_protect(rb_str_new2("Class.rb"),0,&state); vTclass = rb_const_get(rb_cObject, rb_intern("MyClass")); tObj = rb_funcall(vTclass, rb_intern("new"), 0); Data_Get_Struct(tObj,GMScript,ptr); ptr->scriptObj = tObj; // save on stack stack.push_back(ptr); // see what it does rb_gc(); sleep(1); cerr << "\n"; } return 0; } and I get the following out put GMScript::GMScript FREE GMScript::~GMScript GMScript::GMScript FREE GMScript::~GMScript GMScript::GMScript FREE GMScript::~GMScript GMScript::GMScript MARK GMScript::GMScript FREE GMScript::~GMScript FREE GMScript::~GMScript GMScript::GMScript MARK GMScript::GMScript MARK FREE GMScript::~GMScript .. .. .. So, the mark is called - but so is free. I did find that if I use a ruby array instead of vector, push tObj and call rb_global_variable on this array the free never gets called. This leads me to ask if the scriptObj returned from rb_funcall is the correct value to mark. If not, then how do I obtain the correct corresponding ruby VALUE for ptr . In fact, I need to do this to mark children held by GMScript::MyClass? Do I need to do both mark AND rb_global_variable? Cheers in advance Steve