|
Hi Ben,
Thank you for your last answer!
I will see if I get the SWIG::directors running.
I have downloaded libsbml2.3.4 some weeks ago, and now reconfigured it
with (so it is still the same version)
./configure --with-expat --with-python --with-swig
I observe that libsbml.py is now different in that all ..Ptr classes are missing?
I have attached the current libsbml.py and the old one, when running
./configure --with-expat --with-python
as libsbml.copy.py
Is there a way to get the ..Ptr classes back, as I make use of them?
olli
Oliver Ratmann
85 Burgoyne Road
London N41AB
+44 7956001378
-----Original Message-----
From: libsbml-discuss-bounces@caltech.edu on behalf of Ben Bornstein
Sent: Thu 4/20/2006 1:04 AM
To: LibSBML Discussion List
Subject: Re: [libsbml-discuss] how to obtain my subclass from ListOf
Hi Oliver,
> I have understood that the SWIG::director would allow me to override
> an existing libsbml method such as
> libsbml.SpeciesReference.getSpecies().
>
> This might indeed be helpful, thank you for the hint.
>
> However, my original problem is that I add an object whose class is
> derived from
> libsbml.SpeciesReference to the ListOfReactants in libsbml.Reactions.
Although it may not be immediately clear, SWIG directors will solve
your problem as well. They allow for Python subclasses to be
completely substitutable for their parent C++ classes.
> I do not want to change the sbml library for compatibility reasons
Right. I was suggesting that if you came-up with a decent solution
that required reasonable and modest modifications to libSBML, I would
be willing to fold those changes back into the library.
> I could only imagine that my object of my subclass must know the
> address of the C++ proxy which is generated from the
> SWIG::director. I could then override 'this' with that C++ address
> to track my subclass-object.
>
> However, this sounds very complicated.
>
> What do you think?
This will work in libSBML 2.3.x but not 3.0. It's not too
complicated. The example program at the end of this message uses a
customized Python dictionary (ObjectRegistry) to map subclassed
libSBML objects to their parent libSBML object based on SWIG 'this'
pointers. In libSBML 3.0, the problem is libSBML copies objects
passed to it rather than simply taking over ownership of the passed-
in object. Copying objects means the 'this' pointers will no longer
match. You could change my example program to use SBase ids (species
for SpeciesReferences) which *should* always be unique. This assumes
however that i) you have an id at the time of object construction,
ii) you don't change an object's id (otherwise, you would have to
update the registry), and iii) you don't store UnitDefinitions or
local Parameters in the registry as they are in separate namespaces
and their ids can legally "conflict" with SBML objects elsewhere.
Again, I think directors are the way to go. In the meantime, the
code below should provide a decent interim solution.
Thanks.
Ben
#!/usr/bin/env python
import libsbml
class ObjectRegistry (dict):
def add (self, obj):
self[obj] = obj
def getKey (self, obj):
if not hasattr(obj, 'this'): raise TypeError('Not a SWIG object')
return hex( obj.this )
def __contains__ (self, key):
return dict.__contains__(self, self.getKey(key))
def __getitem__ (self, key):
return dict.__getitem__(self, self.getKey(key))
def __setitem__ (self, key, value):
dict.__setitem__(self, self.getKey(key), value)
Registry = ObjectRegistry()
class MySpeciesReference (libsbml.SpeciesReference):
def __init__ (self):
libsbml.SpeciesReference.__init__(self)
Registry.add(self)
msr = MySpeciesReference()
r = libsbml.Reaction()
r.addReactant(msr)
sr = r.getReactant(0)
print type(sr)
print type(Registry[sr])
|