// IMP methods that return pointers to IMP objects (e.g. IMP::Particle) // always return 'weak' pointers (known to Python as "borrowed references"). // It is the responsibility of the caller to handle the reference count. // Thus, when we create a SWIG Python proxy of any such object, we should // make sure that we increase the reference count so that C++ does not // free the object while we have a Python reference to it. // There are two functions defined here which should be used for any IMP // refcounted type that is returned from IMP methods: // IMP_REFCOUNT_RETURN(TYPE) should be used for types that can be returned // either by regular methods or by iterators. Typically this is any type // that is used in an IMP_LIST or a std::vector (e.g. Particles, // Restraints, ScoreStates). If in doubt, use this function. // IMP_REFCOUNT_RETURN_SINGLE(TYPE) should be used for types that are never used // in an iterator. Use this if you tried IMP_REFCOUNT_RETURN(TYPE) and it // failed to compile with an error like // 'type_name' is not a member of 'swig::traits' %define IMP_REFCOUNT_RETURN_SINGLE(TYPE) // If a C++ method returns a pointer to TYPE, increase its reference count // so that the object is not deleted while Python holds a pointer to it. // Take ownership of the pointer (SWIG_POINTER_OWN) so that SWIG calls unref // on it when we are done. %typemap(out) TYPE * { if (!($owner & SWIG_POINTER_NEW)) { // out typemaps are also called for constructors, which already use %ref // to increase the reference count. So don't do it twice. IMP::internal::ref($1); } %set_output(SWIG_NewPointerObj(%as_voidptr($1), $descriptor(TYPE *), $owner | SWIG_POINTER_OWN)); } %enddef %define IMP_REFCOUNT_RETURN(TYPE) IMP_REFCOUNT_RETURN_SINGLE(TYPE) // Specialize the traits_from class to do the same thing as the out typemap. // This class is used by swig::from(), which is primarily used by SWIG // to return TYPE pointers from STL iterators. // In order to get this *after* the definition of the traits_from template, // we need to use insert(wrapper) below. But the wrapper code is extern C. // Ideally SWIG would also us to insert code after the C++ definitions and // before the C wrapper section. %insert(wrapper) %{ #ifdef __cplusplus } #endif namespace swig { template <> struct traits_from { static PyObject *from(TYPE *f) { IMP::internal::ref(f); return SWIG_NewPointerObj(SWIG_as_voidptr(f), type_info(), SWIG_POINTER_OWN); } }; } #ifdef __cplusplus extern "C" { #endif %} %enddef %ignore IMP::VectorOfRefCounted::operator[]; %extend IMP::VectorOfRefCounted { RC __getitem__(int index) const { if (index < 0) index= index+self->size(); if (index >= static_cast(self->size())) { throw IMP::IndexException("Index out of range in getitem"); } return self->get(index); } void __setitem__(int index, RC p) { if (index < 0) index= index+self->size(); if (index >= static_cast(self->size())) { throw IMP::IndexException("Index out of range in setitem"); } return self->set(index, p); } std::vector< RC > __list__() const { std::vector< RC > ret(self->begin(), self->end()); return ret; } int __len__() const { return self->size(); } int count(RC c) const { return std::count(self->begin(), self->end(), c); } void append(RC d) { self->push_back(d); } VectorOfRefCounted< RC, Policy > __add__(const VectorOfRefCounted &o) { IMP::VectorOfRefCounted< RC, Policy > ret(*self); ret.insert(ret.end(), o.begin(), o.end()); return ret; } VectorOfRefCounted< RC, Policy > __getslice__(int b, int e) const { if (e < 0) e= self->size()+e; if (b < 0) b= self->size()+b; IMP::VectorOfRefCounted< RC, Policy > ret; for ( int c=b; c!= e; ++c) { ret.push_back(self->operator[](c)); } return ret; } }