logo       

Re: how to prevent objects from being garbage collected.: msg#00142

programming.swig

Subject: Re: how to prevent objects from being garbage collected.

Ben Bornstein wrote:
On May 24, 2004 18:24, Luigi Ballabio wrote:

> I think the real question is: how can you prevent Ruby and C++ from thinking
> they both own the object.

Hi Meinrad, Henri, Luigi, All,

By its very nature this problem isn't specific to a particular language binding. We've run into the same issue with our Java and Python SWIG-generated APIs. It would be great if SWIG had something akin to %newobject, so that you could tag a particular function or method as taking over ownership of an object. Perhaps:

%releaseobject Foo::addBar (Bar* b)

If addBar() were to take multiple object arguments, I'm not sure the best way to indicate which object is to be released by SWIG (by "best" I mean in a manner most consistent with SWIG syntax). I bet the one-object addXXX() case would be sufficient in most cases.

Let me tell you how we solved this problem in Python and Java. Hopefully this will give you some ideas for Ruby. My co-worker and I are still SWIG newbies, so if anyone has a better way to do this, we'd be excited to learn.

The basic idea is rewrite each shadow/proxy class method that takes ownership of an object. Inside the method we set the object's ownership flag to false:

For Python, we used the SWIG shadow feature:

%feature("shadow") ListOf::append(SBase*) %{
def append(*args):
if args[1]: args[1].thisown = 0
return _libsbml.ListOf_append(*args)
%}

In Java we could not find the shadow feature or it's analog (SWIG 1.3.21), so our solution was a bit more laborious:

%javamethodmodifiers ListOf::append "private";
%rename(appendInternal) ListOf::append;

%typemap("javacode") ListOf
%{
public void append (SBase item)
{
libsbmlJNI.ListOf_appendInternal(swigCPtr, SBase.getCPtr(item));
if (item != null) item.swigCMemOwn = false;
}
%}

We rename the original append() method to appendInternal() and make it private so no one outside the class can call it. We then insert our own definition for append() that delegates to the real append() (now appendInternal()). At first we thought %ignore might work to turn-off automatic generation of the shadow class method, but it also turns off the lower-level static JNI function as well (obvious in retrospect).

As you can see, this can get a bit tedious, which is why we would like to have something like %releaseobject, mentioned above.

I hope this helps.


Some suggestions for the Java wrapping. The following will ensure SWIG disowns the memory pointed to SBase whenever SBase is used as a parameter.


%typemap(javain) SBase, SBase *, SBase &, SBase [] "SBase.getCPtrAndDisown($javainput)"

%typemap(javagetcptr) SBase %{
// protected static long getCPtr(SBase obj) {
// return (obj == null) ? 0 : obj.swigCPtr;
// }
protected static long getCPtrAndDisown(SBase obj) {
long ptr = 0;
if (obj != null) {
obj.swigCMemOwn = false;
ptr = obj.swigCPtr;
}
return ptr;
}
%}


If you want to limit it to just the ListOf::append method, then uncomment the original getCPtr method and change the javain typemap type to whatever the parameter is called in ListOf::append (which seems to be item in your example):

%typemap(javain) SBase *item "SBase.getCPtrAndDisown($javainput)"

This typemap will then only be used for parameters of type 'SBase *item'.

William

_______________________________________________
Swig maillist - Swig@xxxxxxxxxxxxxxx
http://mailman.cs.uchicago.edu/mailman/listinfo/swig



<Prev in Thread] Current Thread [Next in Thread>
Google Custom Search

News | FAQ | advertise