"add" function in swig and the ruby GC?

  • Thread starter Richard P. Groenewegen
  • Start date
R

Richard P. Groenewegen

Hi,

I'm trying to write an add-function in C++ with swig, but I think that
ruby does not Garbage collect my objects. Example:

class Thingy {
public:
Thingy() { }
~Thingy() { cout << "Thingy is destructed."; }

Thingy *add(const Thingy *other) const {
Thingy *result = new Thingy();
// ...
return result;
}
}

Using GC.start I can check that ruby does not destruct Thingies made
with "add". So, what is the correct way to do this? I could return a
Thingy instead of a Thingy*, but is this the preferred(TM) way?

best regards,
Richard
 
P

Paul Brannan

class Thingy {
public:
Thingy() { }
~Thingy() { cout << "Thingy is destructed."; }

Thingy *add(const Thingy *other) const {
Thingy *result = new Thingy();
// ...
return result;
}
}

First of all, Ruby will never collect result in the case that an
exception is thrown. Better would be to write:

Thingy *add(const Thingy *other) const {
std::auto_ptr<Thingy> result(new Thingy);
// ...
return result.release();
}

Secondly, because of Ruby's conservative GC, there is no guarantee that
the objects will ever be destroyed as long as your program is running.
If you need to be able to guarantee that a particular resource (e.g. a
socket or a lock) needs to be freed, you will be better off not relying
on the garbage collector but instead using a different mechanism, such
as blocks or an explicit method call to free the resource.

Now that we have that out of the way, you're probably still wondering
why your objects don't get cleaned up. Well, swig should clean up your
objects, but depending on how you've written your swig interface file
and/or your ruby script, that might not happen. Try to post the
smallest complete interface file and script that demonstrates the
problem, and then the answer may be more obvious.

Paul
 
R

Richard P. Groenewegen

Try to post the smallest complete interface file and script that
demonstrates the problem, and then the answer may be more obvious.

Thanks for the reply and the comment about auto_ptr. I'll be using
that. As for the smallest complete example:

//-------------------------------------------------------------------
// thingy.h
//-------------------------------------------------------------------
#include <iostream>
using namespace std;
class Thingy {
public:
Thingy() {
_number = ++number;
cout << "Thingy " << _number << " constructed.\n";
}
~Thingy() {
cout << "Thingy " << _number << " destructed.\n";
}
Thingy * add(Thingy *other) {
return new Thingy();
}
static int number;
protected:
int _number;
};

//-------------------------------------------------------------------
// thingy.cxx
//-------------------------------------------------------------------
#include "thingy.h"
int Thingy::number = 0;

//-------------------------------------------------------------------
// thingy.i
//-------------------------------------------------------------------
%module thingy

%{
#include "thingy.h"
%}

%include "thingy.h"

//-------------------------------------------------------------------
// irb output (slightly trimmed):
//-------------------------------------------------------------------
irb> require 'thingy.so'
irb> a = Thingy::Thingy.new
Thingy 1 constructed.

irb> b = Thingy::Thingy.new
Thingy 2 constructed.

irb> c = a.add(b)
Thingy 3 constructed.

irb(main):005:0> a,b,c, = 0,0,0

irb(main):006:0> GC.start
Thingy 2 destructed.
Thingy 1 destructed.

As you can see. Thingy 3 does not get destructed. I tried changing
the function add to

void add(Thingy *other, Thingy *OUTPUT) {
OUTPUT = new Thingy();
}

and include "typemaps.i" in the thingy.i file as (sort of) is
suggested in the swig documentation but that does not work.


best regards,
Richard
 
T

Tobias Peters

Richard said:
Hi,

I'm trying to write an add-function in C++ with swig, but I think that
ruby does not Garbage collect my objects. Example:

class Thingy {
public:
Thingy() { }
~Thingy() { cout << "Thingy is destructed."; }

Thingy *add(const Thingy *other) const {
Thingy *result = new Thingy();
// ...
return result;
}
}

Using GC.start I can check that ruby does not destruct Thingies made
with "add". So, what is the correct way to do this? I could return a
Thingy instead of a Thingy*, but is this the preferred(TM) way?

How could SWIG or Ruby possibly know that the pointer returned by your
add method points to a newly created object on the heap. Swig does not
interpret C++ Code, only types and signatures.

The solution to your problem is in the fine SWIG manual. Hint: %newobject

Tobias
 
A

Asbjørn Reglund Thorsen

There is some interessting reading about this quind of problem in the SWIG
manual page 398 chapter 27.8.5.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,160
Messages
2,570,889
Members
47,420
Latest member
ZitaVos505

Latest Threads

Top