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