mirror of https://github.com/KLayout/klayout.git
Merge branch 'pymod' of https://github.com/klayoutmatthias/klayout into pymod
This commit is contained in:
commit
c430c82744
|
|
@ -291,7 +291,7 @@ tl::Variant python2c_func<tl::Variant>::operator() (PyObject *rval)
|
|||
const gsi::ClassBase *cls = PythonModule::cls_for_type (Py_TYPE (rval));
|
||||
if (cls) {
|
||||
|
||||
PYAObjectBase *p = (PYAObjectBase *) rval;
|
||||
PYAObjectBase *p = PYAObjectBase::from_pyobject (rval);
|
||||
|
||||
// employ the tl::Variant binding capabilities of the Expression binding to derive the
|
||||
// variant value.
|
||||
|
|
@ -359,9 +359,8 @@ object_to_python (void *obj, PYAObjectBase *self, const gsi::ArgType &atype)
|
|||
* object turns into a non-const one. This may be confusing but provides a certain level
|
||||
* of "constness", at least until there is another non-const reference for that object.
|
||||
*/
|
||||
void correct_constness (PyObject *obj, bool const_required)
|
||||
void correct_constness (PYAObjectBase *p, bool const_required)
|
||||
{
|
||||
PYAObjectBase *p = (PYAObjectBase *) obj;
|
||||
if (p->const_ref () && ! const_required) {
|
||||
// promote to non-const object
|
||||
p->set_const_ref (false);
|
||||
|
|
@ -421,20 +420,21 @@ object_to_python (void *obj, PYAObjectBase *self, const gsi::ClassBase *cls, boo
|
|||
tl_assert (type != NULL);
|
||||
|
||||
// create a instance and copy the value
|
||||
PYAObjectBase *new_object = (PYAObjectBase *) type->tp_alloc (type, 0);
|
||||
new (new_object) PYAObjectBase (clsact);
|
||||
PyObject *new_pyobject = type->tp_alloc (type, 0);
|
||||
PYAObjectBase *new_object = PYAObjectBase::from_pyobject_unsafe (new_pyobject);
|
||||
new (new_object) PYAObjectBase (clsact, new_pyobject);
|
||||
clsact->assign (new_object->obj (), obj);
|
||||
return new_object;
|
||||
return new_pyobject;
|
||||
|
||||
} else if (pya_object) {
|
||||
|
||||
// we have a that is located in C++ space but is supposed to get attached
|
||||
// a Python object. If it already has, we simply return a reference to this
|
||||
Py_INCREF (pya_object);
|
||||
Py_INCREF (pya_object->py_object ());
|
||||
|
||||
correct_constness (pya_object, is_const);
|
||||
|
||||
return pya_object;
|
||||
return pya_object->py_object ();
|
||||
|
||||
} else {
|
||||
|
||||
|
|
@ -442,10 +442,11 @@ object_to_python (void *obj, PYAObjectBase *self, const gsi::ClassBase *cls, boo
|
|||
tl_assert (type != NULL);
|
||||
|
||||
// create a instance and copy the value
|
||||
PYAObjectBase *new_object = (PYAObjectBase *) type->tp_alloc (type, 0);
|
||||
new (new_object) PYAObjectBase (clsact);
|
||||
PyObject *new_pyobject = type->tp_alloc (type, 0);
|
||||
PYAObjectBase *new_object = PYAObjectBase::from_pyobject_unsafe (new_pyobject);
|
||||
new (new_object) PYAObjectBase (clsact, new_pyobject);
|
||||
new_object->set (obj, pass_obj, is_const, can_destroy);
|
||||
return new_object;
|
||||
return new_pyobject;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -352,7 +352,7 @@ template <class T> struct python2c_func<T &>
|
|||
tl_assert (cls_decl != 0);
|
||||
tl_assert (is_derived_from (cls_decl, typeid (T)));
|
||||
|
||||
PYAObjectBase *p = (PYAObjectBase *) (rval);
|
||||
PYAObjectBase *p = PYAObjectBase::from_pyobject (rval);
|
||||
return *((T *)p->obj ());
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -187,7 +187,7 @@ struct get_boxed_value_func
|
|||
throw tl::Exception (tl::sprintf (tl::to_string (tr ("Passing an object to pointer or reference requires a boxed type (pya.%s)")), bt->name ()));
|
||||
}
|
||||
|
||||
PYAObjectBase *p = (PYAObjectBase *) arg;
|
||||
PYAObjectBase *p = PYAObjectBase::from_pyobject (arg);
|
||||
gsi::Value *bo = reinterpret_cast<gsi::Value *> (p->obj ());
|
||||
if (bo) {
|
||||
*ret = bo->value ().template morph<R> ().native_ptr ();
|
||||
|
|
@ -389,7 +389,7 @@ struct writer<gsi::ObjectType>
|
|||
|
||||
if (cls_decl->is_derived_from (atype.cls ())) {
|
||||
|
||||
PYAObjectBase *p = (PYAObjectBase *) (arg);
|
||||
PYAObjectBase *p = PYAObjectBase::from_pyobject (arg);
|
||||
|
||||
if (cls_decl->adapted_type_info ()) {
|
||||
// resolved adapted type
|
||||
|
|
@ -400,7 +400,7 @@ struct writer<gsi::ObjectType>
|
|||
|
||||
} else if (cls_decl->can_convert_to (atype.cls ())) {
|
||||
|
||||
PYAObjectBase *p = (PYAObjectBase *) (arg);
|
||||
PYAObjectBase *p = PYAObjectBase::from_pyobject (arg);
|
||||
|
||||
// We can convert objects for cref and cptr, but ownership over these objects is not transferred.
|
||||
// Hence we have to keep them on the heap.
|
||||
|
|
@ -421,7 +421,7 @@ struct writer<gsi::ObjectType>
|
|||
|
||||
if (cls_decl->is_derived_from (atype.cls ())) {
|
||||
|
||||
PYAObjectBase *p = (PYAObjectBase *) (arg);
|
||||
PYAObjectBase *p = PYAObjectBase::from_pyobject (arg);
|
||||
|
||||
if (cls_decl->adapted_type_info ()) {
|
||||
// resolved adapted type
|
||||
|
|
@ -432,7 +432,7 @@ struct writer<gsi::ObjectType>
|
|||
|
||||
} else if (cls_decl->can_convert_to (atype.cls ())) {
|
||||
|
||||
PYAObjectBase *p = (PYAObjectBase *) (arg);
|
||||
PYAObjectBase *p = PYAObjectBase::from_pyobject (arg);
|
||||
aa->write<void *> (atype.cls ()->create_obj_from (cls_decl, p->obj ()));
|
||||
|
||||
} else {
|
||||
|
|
@ -471,7 +471,7 @@ push_arg (const gsi::ArgType &atype, gsi::SerialArgs &aserial, PyObject *arg, tl
|
|||
template <class R>
|
||||
struct reader
|
||||
{
|
||||
void operator() (gsi::SerialArgs *rr, PythonRef *ret, PyObject * /*self*/, const gsi::ArgType &arg, tl::Heap *heap)
|
||||
void operator() (gsi::SerialArgs *rr, PythonRef *ret, PYAObjectBase * /*self*/, const gsi::ArgType &arg, tl::Heap *heap)
|
||||
{
|
||||
if (arg.is_ref ()) {
|
||||
*ret = c2python (rr->template read<R &> (*heap));
|
||||
|
|
@ -506,7 +506,7 @@ struct reader
|
|||
template <>
|
||||
struct reader<void *>
|
||||
{
|
||||
void operator() (gsi::SerialArgs *rr, PythonRef *ret, PyObject * /*self*/, const gsi::ArgType &arg, tl::Heap *heap)
|
||||
void operator() (gsi::SerialArgs *rr, PythonRef *ret, PYAObjectBase * /*self*/, const gsi::ArgType &arg, tl::Heap *heap)
|
||||
{
|
||||
tl_assert (! arg.is_cref ());
|
||||
tl_assert (! arg.is_ref ());
|
||||
|
|
|
|||
|
|
@ -575,9 +575,9 @@ static std::string extract_python_name (const std::string &name)
|
|||
static void
|
||||
pya_object_deallocate (PyObject *self)
|
||||
{
|
||||
PYAObjectBase *p = (PYAObjectBase *) self;
|
||||
PYAObjectBase *p = PYAObjectBase::from_pyobject (self);
|
||||
p->~PYAObjectBase ();
|
||||
Py_TYPE (self)->tp_free ((PyObject*)self);
|
||||
Py_TYPE (self)->tp_free (self);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -602,9 +602,10 @@ static PyObject *
|
|||
pya_object_new (PyTypeObject *type, PyObject * /*args*/, PyObject * /*kwds*/)
|
||||
{
|
||||
// create the object
|
||||
PYAObjectBase *self = (PYAObjectBase *) type->tp_alloc (type, 0);
|
||||
new (self) PYAObjectBase (PythonModule::cls_for_type (type));
|
||||
return (PyObject *) self;
|
||||
PyObject *self_pyobject = type->tp_alloc (type, 0);
|
||||
PYAObjectBase *self = PYAObjectBase::from_pyobject_unsafe (self_pyobject);
|
||||
new (self) PYAObjectBase (PythonModule::cls_for_type (type), self_pyobject);
|
||||
return self_pyobject;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
|
@ -619,7 +620,7 @@ method_name_from_id (int mid, PyObject *self)
|
|||
const gsi::ClassBase *cls_decl = 0;
|
||||
|
||||
if (! PyType_Check (self)) {
|
||||
PYAObjectBase *p = (PYAObjectBase *) self;
|
||||
PYAObjectBase *p = PYAObjectBase::from_pyobject (self);
|
||||
cls_decl = p->cls_decl ();
|
||||
} else {
|
||||
cls_decl = PythonModule::cls_for_type ((PyTypeObject *) self);
|
||||
|
|
@ -652,7 +653,7 @@ property_name_from_id (int mid, PyObject *self)
|
|||
const gsi::ClassBase *cls_decl = 0;
|
||||
|
||||
if (! PyType_Check (self)) {
|
||||
PYAObjectBase *p = (PYAObjectBase *) self;
|
||||
PYAObjectBase *p = PYAObjectBase::from_pyobject (self);
|
||||
cls_decl = p->cls_decl ();
|
||||
} else {
|
||||
cls_decl = PythonModule::cls_for_type ((PyTypeObject *) self);
|
||||
|
|
@ -684,7 +685,7 @@ get_return_value (PYAObjectBase *self, gsi::SerialArgs &retlist, const gsi::Meth
|
|||
if (meth->ret_type ().is_iter ()) {
|
||||
|
||||
gsi::IterAdaptorAbstractBase *iter = (gsi::IterAdaptorAbstractBase *) retlist.read<gsi::IterAdaptorAbstractBase *> (heap);
|
||||
ret = (PyObject *) PYAIteratorObject::create (self, iter, &meth->ret_type ());
|
||||
ret = (PyObject *) PYAIteratorObject::create (self ? self->py_object () : 0, iter, &meth->ret_type ());
|
||||
|
||||
} else {
|
||||
|
||||
|
|
@ -702,7 +703,7 @@ match_method (int mid, PyObject *self, PyObject *args, bool strict)
|
|||
|
||||
PYAObjectBase *p = 0;
|
||||
if (! PyType_Check (self)) {
|
||||
p = (PYAObjectBase *) self;
|
||||
p = PYAObjectBase::from_pyobject (self);
|
||||
cls_decl = p->cls_decl ();
|
||||
} else {
|
||||
cls_decl = PythonModule::cls_for_type ((PyTypeObject *) self);
|
||||
|
|
@ -869,10 +870,11 @@ object_dup (PyObject *self, PyObject *args)
|
|||
throw tl::Exception (tl::to_string (tr ("No copy constructor provided for class '%s'")), cls_decl_self->name ());
|
||||
}
|
||||
|
||||
PYAObjectBase *new_object = (PYAObjectBase *) Py_TYPE (self)->tp_alloc (Py_TYPE (self), 0);
|
||||
PyObject *new_object = Py_TYPE (self)->tp_alloc (Py_TYPE (self), 0);
|
||||
PythonRef obj (new_object);
|
||||
new (new_object) PYAObjectBase (cls_decl_self);
|
||||
new_object->set (cls_decl_self->clone (((PYAObjectBase *) self)->obj ()), true, false, false);
|
||||
PYAObjectBase *new_pya_base = PYAObjectBase::from_pyobject_unsafe (new_object);
|
||||
new (new_pya_base) PYAObjectBase (cls_decl_self, new_object);
|
||||
new_pya_base->set (cls_decl_self->clone (PYAObjectBase::from_pyobject (self)->obj ()), true, false, false);
|
||||
|
||||
return obj.release ();
|
||||
}
|
||||
|
|
@ -901,7 +903,7 @@ object_assign (PyObject *self, PyObject *args)
|
|||
throw tl::Exception (tl::to_string (tr ("No assignment provided for class '%s'")), cls_decl_self->name ());
|
||||
}
|
||||
|
||||
cls_decl_self->assign (((PYAObjectBase *) self)->obj (), ((PYAObjectBase *) src)->obj ());
|
||||
cls_decl_self->assign ((PYAObjectBase::from_pyobject (self))->obj (), (PYAObjectBase::from_pyobject (src))->obj ());
|
||||
|
||||
Py_INCREF (self);
|
||||
return self;
|
||||
|
|
@ -997,7 +999,7 @@ object_create (PyObject *self, PyObject *args)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
((PYAObjectBase *) self)->obj ();
|
||||
(PYAObjectBase::from_pyobject (self))->obj ();
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
|
|
@ -1011,7 +1013,7 @@ object_release (PyObject *self, PyObject *args)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
((PYAObjectBase *) self)->release ();
|
||||
(PYAObjectBase::from_pyobject (self))->release ();
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
|
|
@ -1025,7 +1027,7 @@ object_keep (PyObject *self, PyObject *args)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
((PYAObjectBase *) self)->keep ();
|
||||
(PYAObjectBase::from_pyobject (self))->keep ();
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
|
|
@ -1039,7 +1041,7 @@ object_destroy (PyObject *self, PyObject *args)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
((PYAObjectBase *) self)->destroy ();
|
||||
(PYAObjectBase::from_pyobject (self))->destroy ();
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
|
|
@ -1053,7 +1055,7 @@ object_destroyed (PyObject *self, PyObject *args)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
return c2python (((PYAObjectBase *) self)->destroyed ());
|
||||
return c2python (PYAObjectBase::from_pyobject (self)->destroyed ());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1066,7 +1068,7 @@ object_is_const (PyObject *self, PyObject *args)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
return c2python (((PYAObjectBase *) self)->const_ref ());
|
||||
return c2python (PYAObjectBase::from_pyobject (self)->const_ref ());
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
|
|
@ -1112,7 +1114,7 @@ method_adaptor (int mid, PyObject *self, PyObject *args)
|
|||
PYAObjectBase *p = 0;
|
||||
if (! PyType_Check (self)) {
|
||||
// non-static method
|
||||
p = (PYAObjectBase *) self;
|
||||
p = PYAObjectBase::from_pyobject (self);
|
||||
}
|
||||
|
||||
tl::Heap heap;
|
||||
|
|
@ -1666,7 +1668,7 @@ method_init_adaptor (int mid, PyObject *self, PyObject *args)
|
|||
{
|
||||
PYA_TRY
|
||||
|
||||
PYAObjectBase *p = (PYAObjectBase *) self;
|
||||
PYAObjectBase *p = PYAObjectBase::from_pyobject (self);
|
||||
|
||||
// delete any object which we may have already
|
||||
if (p->is_attached ()) {
|
||||
|
|
@ -1888,7 +1890,7 @@ property_getter_impl (int mid, PyObject *self)
|
|||
|
||||
PYAObjectBase *p = 0;
|
||||
if (! PyType_Check (self)) {
|
||||
p = (PYAObjectBase *) self;
|
||||
p = PYAObjectBase::from_pyobject (self);
|
||||
cls_decl = p->cls_decl ();
|
||||
} else {
|
||||
cls_decl = PythonModule::cls_for_type ((PyTypeObject *) self);
|
||||
|
|
@ -1969,7 +1971,7 @@ property_setter_impl (int mid, PyObject *self, PyObject *value)
|
|||
|
||||
PYAObjectBase *p = 0;
|
||||
if (! PyType_Check (self)) {
|
||||
p = (PYAObjectBase *) self;
|
||||
p = PYAObjectBase::from_pyobject (self);
|
||||
cls_decl = p->cls_decl ();
|
||||
} else {
|
||||
cls_decl = PythonModule::cls_for_type ((PyTypeObject *) self);
|
||||
|
|
@ -2156,7 +2158,6 @@ PythonModule::~PythonModule ()
|
|||
// the Python objects were probably deleted by Python itself as it exited -
|
||||
// don't try to delete them again.
|
||||
mp_module.release ();
|
||||
mp_base_class.release ();
|
||||
|
||||
while (!m_methods_heap.empty ()) {
|
||||
delete m_methods_heap.back ();
|
||||
|
|
@ -2339,36 +2340,6 @@ PythonModule::make_classes (const char *mod_name)
|
|||
|
||||
PyObject_SetAttrString (module, "__doc__", PythonRef (c2python (m_mod_description)).get ());
|
||||
|
||||
// Create a (built-in) base class for all objects exposed by this module
|
||||
|
||||
m_base_class_name = m_mod_name + ".__Base";
|
||||
|
||||
PyTypeObject *base_class = (PyTypeObject *) PyType_Type.tp_alloc (&PyType_Type, 0);
|
||||
tl_assert (base_class != NULL);
|
||||
mp_base_class = PythonRef ((PyObject *) base_class);
|
||||
|
||||
base_class->tp_base = &PyBaseObject_Type;
|
||||
base_class->tp_name = m_base_class_name.c_str ();
|
||||
base_class->tp_basicsize = sizeof (PYAObjectBase);
|
||||
base_class->tp_init = &pya_object_init;
|
||||
base_class->tp_new = &pya_object_new;
|
||||
base_class->tp_dealloc = (destructor) &pya_object_deallocate;
|
||||
base_class->tp_setattro = PyObject_GenericSetAttr;
|
||||
base_class->tp_getattro = PyObject_GenericGetAttr;
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
base_class->tp_flags = Py_TPFLAGS_HEAPTYPE | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_CHECKTYPES;
|
||||
#else
|
||||
base_class->tp_flags = Py_TPFLAGS_HEAPTYPE | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE;
|
||||
#endif
|
||||
|
||||
if (PyType_Ready (base_class) < 0) {
|
||||
check_error ();
|
||||
return;
|
||||
}
|
||||
|
||||
PyModule_AddObject (module, "__Base", (PyObject *) base_class);
|
||||
|
||||
|
||||
// Build a class for descriptors for static attributes
|
||||
PYAStaticAttributeDescriptorObject::make_class (module);
|
||||
|
||||
|
|
@ -2434,15 +2405,17 @@ PythonModule::make_classes (const char *mod_name)
|
|||
|
||||
m_classes.push_back (c.operator-> ());
|
||||
|
||||
PythonRef bases (PyTuple_New (1));
|
||||
PyObject *base = mp_base_class.get ();
|
||||
PythonRef bases;
|
||||
if (c->base () != 0) {
|
||||
bases = PythonRef (PyTuple_New (1));
|
||||
PyTypeObject *pt = PythonClassClientData::py_type (*c->base ());
|
||||
tl_assert (pt != 0);
|
||||
base = (PyObject *) pt;
|
||||
PyObject *base = (PyObject *) pt;
|
||||
Py_INCREF (base);
|
||||
PyTuple_SetItem (bases.get (), 0, base);
|
||||
} else {
|
||||
bases = PythonRef (PyTuple_New (0));
|
||||
}
|
||||
Py_INCREF (base);
|
||||
PyTuple_SetItem (bases.get (), 0, base);
|
||||
|
||||
PythonRef dict (PyDict_New ());
|
||||
PyDict_SetItemString (dict.get (), "__module__", PythonRef (c2python (m_mod_name)).get ());
|
||||
|
|
@ -2459,9 +2432,18 @@ PythonModule::make_classes (const char *mod_name)
|
|||
check_error ();
|
||||
tl_assert (false);
|
||||
}
|
||||
|
||||
// Customize
|
||||
type->tp_basicsize += sizeof (PYAObjectBase);
|
||||
type->tp_init = &pya_object_init;
|
||||
type->tp_new = &pya_object_new;
|
||||
type->tp_dealloc = (destructor) &pya_object_deallocate;
|
||||
type->tp_setattro = PyObject_GenericSetAttr;
|
||||
type->tp_getattro = PyObject_GenericGetAttr;
|
||||
|
||||
PythonClassClientData::initialize (*c, type);
|
||||
|
||||
tl_assert (cls_for_type (type) == c.operator-> ()); // @@@
|
||||
tl_assert (cls_for_type (type) == c.operator-> ());
|
||||
|
||||
PyList_Append (all_list.get (), PythonRef (c2python (c->name ())).get ());
|
||||
PyModule_AddObject (module, c->name ().c_str (), (PyObject *) type);
|
||||
|
|
|
|||
|
|
@ -120,9 +120,7 @@ private:
|
|||
std::vector<PyGetSetDef *> m_getseters_heap;
|
||||
|
||||
std::string m_mod_name, m_mod_description;
|
||||
std::string m_base_class_name;
|
||||
PythonRef mp_module;
|
||||
PythonRef mp_base_class;
|
||||
char *mp_mod_def;
|
||||
|
||||
static std::map<const gsi::MethodBase *, std::string> m_python_doc;
|
||||
|
|
|
|||
|
|
@ -129,8 +129,8 @@ Callee::call (int id, gsi::SerialArgs &args, gsi::SerialArgs &ret) const
|
|||
PythonRef argv (PyTuple_New (arg4self + std::distance (meth->begin_arguments (), meth->end_arguments ())));
|
||||
|
||||
// Put self into first argument
|
||||
PyTuple_SetItem (argv.get (), 0, mp_obj);
|
||||
Py_INCREF (mp_obj);
|
||||
PyTuple_SetItem (argv.get (), 0, mp_obj->py_object ());
|
||||
Py_INCREF (mp_obj->py_object ());
|
||||
|
||||
// TODO: callbacks with default arguments?
|
||||
for (gsi::MethodBase::argument_iterator a = meth->begin_arguments (); args && a != meth->end_arguments (); ++a) {
|
||||
|
|
@ -169,8 +169,9 @@ Callee::call (int id, gsi::SerialArgs &args, gsi::SerialArgs &ret) const
|
|||
// --------------------------------------------------------------------------
|
||||
// Implementation of PYAObjectBase
|
||||
|
||||
PYAObjectBase::PYAObjectBase(const gsi::ClassBase *_cls_decl)
|
||||
: m_listener (new pya::StatusChangedListener (this)),
|
||||
PYAObjectBase::PYAObjectBase(const gsi::ClassBase *_cls_decl, PyObject *py_object)
|
||||
: mp_py_object (py_object),
|
||||
m_listener (new pya::StatusChangedListener (this)),
|
||||
m_callee (new pya::Callee (this)),
|
||||
m_cls_decl (_cls_decl),
|
||||
m_obj (0),
|
||||
|
|
@ -179,6 +180,7 @@ PYAObjectBase::PYAObjectBase(const gsi::ClassBase *_cls_decl)
|
|||
m_destroyed (false),
|
||||
m_can_destroy (false)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
PYAObjectBase::~PYAObjectBase ()
|
||||
|
|
@ -223,7 +225,7 @@ PYAObjectBase::object_destroyed ()
|
|||
|
||||
// NOTE: this may delete "this"!
|
||||
if (!prev_owner) {
|
||||
Py_DECREF (this);
|
||||
Py_DECREF (py_object ());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -246,7 +248,7 @@ PYAObjectBase::release ()
|
|||
if (!m_owned) {
|
||||
m_owned = true;
|
||||
// NOTE: this may delete "this"! TODO: this should not happen. Can we assert that somehow?
|
||||
Py_DECREF (this);
|
||||
Py_DECREF (py_object ());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -254,7 +256,7 @@ void
|
|||
PYAObjectBase::keep_internal ()
|
||||
{
|
||||
if (m_owned) {
|
||||
Py_INCREF (this);
|
||||
Py_INCREF (py_object ());
|
||||
m_owned = false;
|
||||
}
|
||||
}
|
||||
|
|
@ -328,7 +330,7 @@ PYAObjectBase::set (void *obj, bool owned, bool const_ref, bool can_destroy)
|
|||
}
|
||||
|
||||
if (!m_owned) {
|
||||
Py_INCREF (this);
|
||||
Py_INCREF (py_object ());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -353,7 +355,7 @@ PYAObjectBase::initialize_callbacks ()
|
|||
// TODO: caching appears to create some leaks ...
|
||||
#if 1
|
||||
|
||||
PythonRef type_ref ((PyObject *) Py_TYPE (this), false /*borrowed*/);
|
||||
PythonRef type_ref ((PyObject *) Py_TYPE (py_object ()), false /*borrowed*/);
|
||||
|
||||
// Locate the callback-enabled methods set by Python tpye object (pointer)
|
||||
// NOTE: I'm not quite sure whether the type object pointer is a good key
|
||||
|
|
@ -391,7 +393,7 @@ PYAObjectBase::initialize_callbacks ()
|
|||
// TOOD: That may happen too often, i.e. if the Python class does not reimplement the virtual
|
||||
// method, but the C++ class defines a method hook that the reimplementation can call.
|
||||
// We don't want to produce a lot of overhead for the Qt classes here.
|
||||
PythonRef py_attr = PyObject_GetAttrString ((PyObject *) Py_TYPE (this), nstr);
|
||||
PythonRef py_attr = PyObject_GetAttrString ((PyObject *) Py_TYPE (py_object ()), nstr);
|
||||
if (! py_attr) {
|
||||
|
||||
// because PyObject_GetAttrString left an error
|
||||
|
|
@ -423,7 +425,7 @@ PYAObjectBase::initialize_callbacks ()
|
|||
|
||||
PythonRef py_attr;
|
||||
const char *nstr = (*m)->primary_name ().c_str ();
|
||||
py_attr = PyObject_GetAttrString ((PyObject *) Py_TYPE (this), nstr);
|
||||
py_attr = PyObject_GetAttrString ((PyObject *) Py_TYPE (py_object ()), nstr);
|
||||
|
||||
int id = m_callee->add_callback (CallbackFunction (py_attr, *m));
|
||||
(*m)->set_callback (m_obj, gsi::Callback (id, m_callee.get (), (*m)->argsize (), (*m)->retsize ()));
|
||||
|
|
@ -458,7 +460,7 @@ PYAObjectBase::initialize_callbacks ()
|
|||
// TOOD: That may happen too often, i.e. if the Python class does not reimplement the virtual
|
||||
// method, but the C++ class defines a method hook that the reimplementation can call.
|
||||
// We don't want to produce a lot of overhead for the Qt classes here.
|
||||
PythonRef py_attr = PyObject_GetAttrString ((PyObject *) Py_TYPE (this), nstr);
|
||||
PythonRef py_attr = PyObject_GetAttrString ((PyObject *) Py_TYPE (py_object ()), nstr);
|
||||
if (! py_attr) {
|
||||
|
||||
// because PyObject_GetAttrString left an error
|
||||
|
|
@ -471,7 +473,7 @@ PYAObjectBase::initialize_callbacks ()
|
|||
// may create issues with callbacks during destruction (i.e. QWidget-destroyed signal)
|
||||
if (! PyCFunction_Check (py_attr.get ())) {
|
||||
|
||||
PyObject *py_attr = PyObject_GetAttrString ((PyObject *) Py_TYPE (this), nstr);
|
||||
PyObject *py_attr = PyObject_GetAttrString ((PyObject *) Py_TYPE (py_object ()), nstr);
|
||||
tl_assert (py_attr != NULL);
|
||||
int id = m_callee.add_callback (CallbackFunction (py_attr, *m));
|
||||
(*m)->set_callback (m_obj, gsi::Callback (id, &m_callee, (*m)->argsize (), (*m)->retsize ()));
|
||||
|
|
@ -501,7 +503,7 @@ PYAObjectBase::clear_callbacks_cache ()
|
|||
void
|
||||
PYAObjectBase::detach_callbacks ()
|
||||
{
|
||||
PythonRef type_ref ((PyObject *) Py_TYPE (this), false /*borrowed*/);
|
||||
PythonRef type_ref ((PyObject *) Py_TYPE (py_object ()), false /*borrowed*/);
|
||||
|
||||
callbacks_cache::iterator cb = s_callbacks_cache.find (type_ref);
|
||||
if (cb != s_callbacks_cache.end ()) {
|
||||
|
|
|
|||
|
|
@ -29,6 +29,8 @@
|
|||
#include "pyaRefs.h"
|
||||
#include "pyaCommon.h"
|
||||
|
||||
#include "tlAssert.h"
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
|
@ -50,23 +52,43 @@ class StatusChangedListener;
|
|||
/**
|
||||
* @brief The Python object representing a GSI object
|
||||
*
|
||||
* Note: the PYAObjectBase must be directly derived from PyObject so that
|
||||
* a PyObject pointer can be cast to a PYAObjectBase pointer.
|
||||
* NOTE: this memory block is attached to the actual structure
|
||||
* and obtained by taking the last sizeof(PYAObjectBase) bytes.
|
||||
* It's basically a connector between GSI objects and the Python
|
||||
* objects.
|
||||
*/
|
||||
class PYA_PUBLIC PYAObjectBase
|
||||
: public PyObject
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor - creates a new object for the given GSI class
|
||||
*/
|
||||
PYAObjectBase (const gsi::ClassBase *_cls_decl);
|
||||
PYAObjectBase (const gsi::ClassBase *_cls_decl, PyObject *py_object);
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
~PYAObjectBase ();
|
||||
|
||||
/**
|
||||
* @brief Gets the PYAObjectBase pointer from a PyObject pointer
|
||||
*/
|
||||
static PYAObjectBase *from_pyobject (PyObject *py_object)
|
||||
{
|
||||
PYAObjectBase *pya_object = (PYAObjectBase *)((char *) py_object + Py_TYPE (py_object)->tp_basicsize - sizeof (PYAObjectBase));
|
||||
tl_assert (pya_object->py_object () == py_object);
|
||||
return pya_object;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the PYAObjectBase pointer from a PyObject pointer
|
||||
* This version doesn't check anything.
|
||||
*/
|
||||
static PYAObjectBase *from_pyobject_unsafe (PyObject *py_object)
|
||||
{
|
||||
return (PYAObjectBase *)((char *) py_object + Py_TYPE (py_object)->tp_basicsize - sizeof (PYAObjectBase));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Indicates that a C++ object is present
|
||||
*/
|
||||
|
|
@ -142,6 +164,14 @@ public:
|
|||
m_const_ref = c;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the Python object for this bridge object
|
||||
*/
|
||||
PyObject *py_object () const
|
||||
{
|
||||
return mp_py_object;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the C++ object reference
|
||||
*/
|
||||
|
|
@ -189,6 +219,7 @@ private:
|
|||
void object_destroyed ();
|
||||
void keep_internal ();
|
||||
|
||||
PyObject *mp_py_object;
|
||||
std::auto_ptr<StatusChangedListener> m_listener;
|
||||
std::auto_ptr<Callee> m_callee;
|
||||
const gsi::ClassBase *m_cls_decl;
|
||||
|
|
|
|||
|
|
@ -2718,6 +2718,7 @@ class BasicTest(unittest.TestCase):
|
|||
go = None
|
||||
self.assertEqual(pya.GObject.g_inst_count(), gc)
|
||||
|
||||
|
||||
# run unit tests
|
||||
if __name__ == '__main__':
|
||||
suite = unittest.TestSuite()
|
||||
|
|
|
|||
Loading…
Reference in New Issue