Embedding ruby

Please forgive the following if answers appear elsewhere but I have
been trawling docs and news group for the last 2 days and I’m totally
confused

I am writing an OpenGL scenegrapher that uses Ruby scripts to create
nodes within the Scenegraph
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

in c++ I call at start

    ruby_init();
    ruby_init_loadpath();
    ruby_script("embedded");
    rb_require("gm.so");            - swigged up wrapper lib

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;

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. 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. 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:

/home/steve/TEST/GMScript/Menu/News24/Test1.rb:103: [BUG]
rb_gc_mark(): unknown data type 0x28(0xbfffed78) non object

PS In posting this I have just seen a thread detailing
rb_gc_register_address/rb_gc_unregister_address. I have tried this but
it also fails

I am Using :
ruby 1.8.0
Swig 1.3.19
linux 2.4.18-14smp

I’m sure I’m doing something wrong or have missed something but cannot
work out
what Any help gratefully recieved
Cheers
Steve Hart

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 :slight_smile:
http://metaeditor.sourceforge.net/embed/

···

On Tue, 08 Apr 2003 19:56:33 +0000, Steve Hart wrote:


Simon Strandgaard

“Simon Strandgaard” 0bz63fz3m1qt3001@sneakemail.com wrote in message news:pan.2003.04.09.11.06.37.642046@sneakemail.com

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 :slight_smile:
ruby embedded into c++

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 <ruby.h>

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<GMScript *> 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

···

On Tue, 08 Apr 2003 19:56:33 +0000, Steve Hart wrote:

“Simon Strandgaard” 0bz63fz3m1qt3001@sneakemail.com wrote in message news:pan.2003.04.09.11.06.37.642046@sneakemail.com

···

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 :slight_smile:
ruby embedded into c++
this thread carries on in ‘embedding ruby with swig’

Sorry for denseness but what does bootstrapping swig class mean?

bootstrapping… I choose a bad word for this :slight_smile:
Its how to transfer information about the parent class to
the ruby-instanse. See my tutorial the section “Cheating = Success”
for further details.
Anyway… You have no c++callbacks, so you doesn’t need it :slight_smile:

and why is it bad. ?

Its not bad… its just a bit dirty.

I will reply on your remaining questions … soon :slight_smile:

···

On Wed, 09 Apr 2003 17:56:52 +0000, Steve Hart wrote:

Simon Strandgaard

static void GMScript_freefunc(void *ptr)
{
cerr << “FREE\n”;
GMScript *script = (GMScript *) ptr;
delete script;
}

I think its overkill to have your own freefunc when SWIG
can generate one for you for free.
If you want to output some debug information when the
instance gets destroyed (swept by GC), you can do it from
your destructor.

GMScript::~GMScript() {
cerr << “FREE\n”;
}

static void GMScript_markfunc(void *ptr)
{
cerr << “MARK\n”;
GMScript *script = (GMScript *) ptr;
rb_gc_mark(reinterpret_cast((script->scriptObj)));
}

Yes, its correct that “scriptObj” needs to be marked during GC.
No, you cannot cast the argument like that. Try:

VALUE GMScript_markfunc(VALUE self) {
GMScript *p;
Data_Get_Struct(self, GMScript, p);
rb_gc_mark(reinterpret_cast((p->scriptObj)));
return self;
}

GMScript.h
GMScript.cpp

Looks fine… to me :slight_smile:

main.c

maybe rename it into main.cpp ?
hmmm… lets take than in another posting :slight_smile:

···

On Wed, 09 Apr 2003 17:56:52 +0000, Steve Hart wrote:


Simon Strandgaard

int main()
{
GMScript *ptr = NULL;
int state = 0;
VALUE vTclass;
VALUE tObj;
vector<GMScript *> stack;

Suggestion for improving your code-readability:
Move your variable-declaration down to where they are
being used for the first time.

    ruby_init();
    ruby_script("embedded");
    ruby_init_loadpath();
    rb_require("gm.so");

Looks fine.

    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);

Looks fine.
The next 2 lines look interesting…

            Data_Get_Struct(tObj,GMScript,ptr);
            ptr->scriptObj = tObj;

There is something odd about them… try

tObj = new GMScript;
tObj->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
[snip output]

Sorry I don’t understand your output.

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?

I am very sleepy right now… maybe I understand tomorrow :slight_smile:

Do I need to do both mark AND rb_global_variable?

No. They are mutual exlusive

···

On Wed, 09 Apr 2003 17:56:52 +0000, Steve Hart wrote:


Simon Strandgaard

Damn… I am wrong here… sorry

You don’t need to do any marking at all.

The instance-owner of GMScript is main.c, thus its not
an instance which is being managed by ruby, therefore no
rb_mark should be done.

Instead you must keep track of your “scriptObj”'s, either by
doing rb_gc_registister_adress/rb_gc_unregister_adress or by
putting them in a global array/hash.

···

On Thu, 10 Apr 2003 05:43:26 +0200, Simon Strandgaard wrote:

On Wed, 09 Apr 2003 17:56:52 +0000, Steve Hart wrote:

Yes, its correct that “scriptObj” needs to be marked during GC.


Simon Strandgaard

“Simon Strandgaard” 0bz63fz3m1qt3001@sneakemail.com wrote in message news:pan.2003.04.10.03.26.14.705399@sneakemail.com

int main()
{
GMScript *ptr = NULL;
int state = 0;
VALUE vTclass;
VALUE tObj;
vector<GMScript *> stack;

Suggestion for improving your code-readability:
Move your variable-declaration down to where they are
being used for the first time.

    ruby_init();
    ruby_script("embedded");
    ruby_init_loadpath();
    rb_require("gm.so");

Looks fine.

    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);

Looks fine.
The next 2 lines look interesting…

            Data_Get_Struct(tObj,GMScript,ptr);
            ptr->scriptObj = tObj;

There is something odd about them… try

tObj = new GMScript;
tObj->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
[snip output]

Sorry I don’t understand your output.

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?

I am very sleepy right now… maybe I understand tomorrow :slight_smile:

Do I need to do both mark AND rb_global_variable?

No. They are mutual exlusive

Hi Simon
Thanks for the reply - sorry if I kept you up!
I think I’ve sussed the problem and oh dear, how stupid could I be!
The problem I had was that even though the mark function gets called
so does free immediately afterwards. This is because i declare tObj
once, pass a reference to rb_gc_register_address and then next time
round the loop just overwrite it. If I change main.cpp(!) to

    for(;;)
    {
            rb_load_protect(rb_str_new2("Class.rb"),0,&state);
            VALUE vTclass = rb_const_get(rb_cObject,

rb_intern(“MyClass”));
VALUE *tObj = (VALUE *)malloc(sizeof(VALUE));

            *tObj = rb_funcall(vTclass, rb_intern("new"), 0);
            rb_gc_register_address(tObj);

            // store the value
            Data_Get_Struct(*tObj,GMScript,ptr);
            ptr->scriptObj = tObj;

            // see what it does
            cerr << "\n";
            rb_gc();
            sleep(1);
            rb_gc_unregister_address(tObj);
    }

I’m a bit doubtful about the malloc - should I do something different
here?
It all works though
I also had to change the mark and free functions in swig to:

%{
static void GMScript_freefunc(void *ptr)
{
cerr << “FREE\n”;
GMScript *script = static_cast<GMScript *>(ptr);
free(script->scriptObj);
delete script;
}

%}

%{
static void GMScript_markfunc(void *ptr)
{
cerr << “MARK\n”;
GMScript *script = static_cast<GMScript *>(ptr);
rb_gc_mark(*script->scriptObj);
}
%}

I’m also unsure regarding the static_cast. I’ve seen examples using
static_cast,dynamic_cast,reinterpret_cast and no cast at all.
I’m still unclear on one issue though. I supply a mark function for
swig and
sure enough this gets called now, so why do I have to register the
object (tObj) on the c++ side?
Cheers for the response and keep up the good work on the tutorial!

···

On Wed, 09 Apr 2003 17:56:52 +0000, Steve Hart wrote:

“Simon Strandgaard” 0bz63fz3m1qt3001@sneakemail.com wrote in message news:pan.2003.04.10.03.26.14.705399@sneakemail.com

int main()
{
GMScript *ptr = NULL;
int state = 0;
VALUE vTclass;
VALUE tObj;
vector<GMScript *> stack;

Suggestion for improving your code-readability:
Move your variable-declaration down to where they are
being used for the first time.

    ruby_init();
    ruby_script("embedded");
    ruby_init_loadpath();
    rb_require("gm.so");

Looks fine.

    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);

Looks fine.
The next 2 lines look interesting…

            Data_Get_Struct(tObj,GMScript,ptr);
            ptr->scriptObj = tObj;

There is something odd about them… try

tObj = new GMScript;
tObj->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
[snip output]

Sorry I don’t understand your output.

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?

I am very sleepy right now… maybe I understand tomorrow :slight_smile:

Do I need to do both mark AND rb_global_variable?

No. They are mutual exlusive

My previous post has not appeared yet but I have a better solution
now. Forget the malloc - that was silly. If I now do the following in
the for loop

            rb_load_protect(rb_str_new2("Class.rb"),0,&state);
            VALUE vTclass = rb_const_get(rb_cObject,

rb_intern(“MyClass”));
VALUE tObj = rb_funcall(vTclass, rb_intern(“new”), 0);
Data_Get_Struct(tObj,GMScript,ptr);
ptr->scriptObj = tObj;
rb_gc_register_address(&(ptr->scriptObj));

            // see what it does
            cerr << "\n";
            sleep(1);
            rb_gc();

Its OK and I get:

GMScript::GMScript

MARK
GMScript::GMScript

MARK
MARK
GMScript::GMScript

MARK
MARK
MARK
GMScript::GMScript

which makes sense - each subsequent rb_funcall creates a new object
and the number of marks increase accordingly. But if I omit the call
to

  rb_gc_register_address(&(ptr->scriptObj));

I get:

GMScript::GMScript

FREE
GMScript::~GMScript
GMScript::GMScript

FREE
GMScript::~GMScript
GMScript::GMScript

The mark function in swig is never called. Why?. If I follow the code
through
rb_funcall → _wrap_GMScript_allocate → SWIG_NewClassInstance →
Data_Wrap…
→ rb_obj_call_init →
initialize()
self <—

So, does this mean that the only reference held to this ruby instance
is the one returned from rb_funcall and if I don’t tell gc it can’t
call the mark. And the only reason the free can be called is because
it exists in main’s stack frame?

Sorry for being a bit anal here, I’m just trying to get my head round
what’s going on.
If the above is true, then great. I would be happy to call
rb_gc_register_address when I create the instance, use the swig mark
func for any persistant children i create within MyClass, and then
call rb_gc_unregister_address when I’m done with it. I think I read
somewhere that there is no harm in marking an object twice so if child
objects created within GMScript are shared with other instances of
GMScript and they both mark the chhildren I can select which ones I
need to delete when I destroy an instance to GMScript.

Am I correct here?

I did read the Swig doc on this - could do with a bit more explaining
here, in particular sec 20.8.5 which refers to the imaginary
SWIG_RubyInstanceFor. any chance anyone might implement it!

···

On Wed, 09 Apr 2003 17:56:52 +0000, Steve Hart wrote:

Thanks for the reply - sorry if I kept you up!

The hardest part of my day is when I have to move myself from
the computer over to my bed (2 meters). I hate sleeping :slight_smile:

I think I’ve sussed the problem and oh dear, how stupid could I be!
The problem I had was that even though the mark function gets called
so does free immediately afterwards. This is because i declare tObj
once, pass a reference to rb_gc_register_address and then next time
round the loop just overwrite it.

I am not sure about the purpose of your code.
guess: an experiment to see what happens when GC kicks in.
Thats a rather complicated proof of concept you have.

I have done some experiments too, try

maybe I should add it to the tutorial ???

[snip maip.cpp]

variable-declarations = street-respect :slight_smile:

I think you have gotton out on a off-track. Both malloc/free and
marking is unnecessary. I know you really want to use rb_gc_mark(), but
you are not in the situation where its necessary to mark your children.
You are using it to mark non-children…mark is not supposed to be used
in that way.

I’m a bit doubtful about the malloc - should I do something different
here?
It all works though
I also had to change the mark and free functions in swig to:

[snip swig.i]

I’m also unsure regarding the static_cast. I’ve seen examples using
static_cast,dynamic_cast,reinterpret_cast and no cast at all.

http://cpptips.hyperformix.com/cpptips/cast_overview

I’m still unclear on one issue though. I supply a mark function for
swig and
sure enough this gets called now, so why do I have to register the
object (tObj) on the c++ side?

I think you should see the example that mentioned earlier, this should
hopefully make it a bit more clear for you.

···

On Thu, 10 Apr 2003 08:33:10 +0000, Steve Hart wrote:


Simon Strandgaard

My previous post has not appeared yet but I have a better solution
now. Forget the malloc - that was silly.

Agree :slight_smile:

[snip code]

which makes sense - each subsequent rb_funcall creates a new object
and the number of marks increase accordingly. But if I omit the call
to

  rb_gc_register_address(&(ptr->scriptObj));

I get:

GMScript::GMScript

FREE
GMScript::~GMScript
GMScript::GMScript

FREE
GMScript::~GMScript
GMScript::GMScript

The mark function in swig is never called. Why?.

If you omit telling GC that the instance is busy. Then when GC is done
with its mark phase and starts sweeping, then ptr->scriptObj will appear
to be unmark and get destroyed. Thats the reason why ptr->scriptObj’s
markfunc is never invoked.

If I follow the code through
rb_funcall → _wrap_GMScript_allocate → SWIG_NewClassInstance →
Data_Wrap…
→ rb_obj_call_init →
initialize()
self <—

Sorry… me don’t understand.

So, does this mean that the only reference held to this ruby instance
is the one returned from rb_funcall and if I don’t tell gc it can’t
call the mark. And the only reason the free can be called is because
it exists in main’s stack frame?

Sorry… again not understanding.

Sorry for being a bit anal here, I’m just trying to get my head round
what’s going on.
If the above is true, then great. I would be happy to call
rb_gc_register_address when I create the instance, use the swig mark
func for any persistant children i create within MyClass, and then
call rb_gc_unregister_address when I’m done with it. I think I read

Yes you got it right :slight_smile:

somewhere that there is no harm in marking an object twice so if child
objects created within GMScript are shared with other instances of
GMScript and they both mark the chhildren I can select which ones I
need to delete when I destroy an instance to GMScript.

Am I correct here?

Marking an instance multiple times… I don’t think it
will result in segfaults :slight_smile:

I did read the Swig doc on this - could do with a bit more explaining
here, in particular sec 20.8.5 which refers to the imaginary
SWIG_RubyInstanceFor. any chance anyone might implement it!

Don’t know ???

···

On Thu, 10 Apr 2003 10:10:54 +0000, Steve Hart wrote:


Simon Strandgaard

“Simon Strandgaard” 0bz63fz3m1qt3001@sneakemail.com wrote in message news:pan.2003.04.10.20.41.24.442608@sneakemail.com

My previous post has not appeared yet but I have a better solution
now. Forget the malloc - that was silly.

Agree :slight_smile:

[snip code]

which makes sense - each subsequent rb_funcall creates a new object
and the number of marks increase accordingly. But if I omit the call
to

  rb_gc_register_address(&(ptr->scriptObj));

I get:

GMScript::GMScript

FREE
GMScript::~GMScript
GMScript::GMScript

FREE
GMScript::~GMScript
GMScript::GMScript

The mark function in swig is never called. Why?.

If you omit telling GC that the instance is busy. Then when GC is done
with its mark phase and starts sweeping, then ptr->scriptObj will appear
to be unmark and get destroyed. Thats the reason why ptr->scriptObj’s
markfunc is never invoked.

If I follow the code through
rb_funcall → _wrap_GMScript_allocate → SWIG_NewClassInstance →
Data_Wrap…
→ rb_obj_call_init →
initialize()
self <—

Sorry… me don’t understand.

This got garbled in post - I just tried to follow through from
rb_funcall thru swig and back out again

So, does this mean that the only reference held to this ruby instance
is the one returned from rb_funcall and if I don’t tell gc it can’t
call the mark. And the only reason the free can be called is because
it exists in main’s stack frame?

Sorry… again not understanding.

Sorry for being a bit anal here, I’m just trying to get my head round
what’s going on.
If the above is true, then great. I would be happy to call
rb_gc_register_address when I create the instance, use the swig mark
func for any persistant children i create within MyClass, and then
call rb_gc_unregister_address when I’m done with it. I think I read

Yes you got it right :slight_smile:

somewhere that there is no harm in marking an object twice so if child
objects created within GMScript are shared with other instances of
GMScript and they both mark the chhildren I can select which ones I
need to delete when I destroy an instance to GMScript.

Am I correct here?

Marking an instance multiple times… I don’t think it
will result in segfaults :slight_smile:

I did read the Swig doc on this - could do with a bit more explaining
here, in particular sec 20.8.5 which refers to the imaginary
SWIG_RubyInstanceFor. any chance anyone might implement it!

Don’t know ???

Sorry for all this I’ve had 2 days off and it’s all a bit clearer. I
don’t know why, but I had thought that the object instance (tObj)
returned from rb_funcall was also ‘held’ withing the interpreter. As
such, I assumed that the MARK would be called even though tObj had
gone out of scope.

I had some more thoughts on the tutorial (if you’re interested). It
would make it clearer to seperate the swig and non swig version
completely (even sperate directories). People new to both swig and
ruby (like me) may find it easier to compare. Just a thought.

rubycpp.cpp is excellent though - I did’nt know you could obtain a
backtrace for error output
Cheers

···

On Thu, 10 Apr 2003 10:10:54 +0000, Steve Hart wrote: