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));
|
const gsi::ClassBase *cls = PythonModule::cls_for_type (Py_TYPE (rval));
|
||||||
if (cls) {
|
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
|
// employ the tl::Variant binding capabilities of the Expression binding to derive the
|
||||||
// variant value.
|
// 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
|
* 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.
|
* 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) {
|
if (p->const_ref () && ! const_required) {
|
||||||
// promote to non-const object
|
// promote to non-const object
|
||||||
p->set_const_ref (false);
|
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);
|
tl_assert (type != NULL);
|
||||||
|
|
||||||
// create a instance and copy the value
|
// create a instance and copy the value
|
||||||
PYAObjectBase *new_object = (PYAObjectBase *) type->tp_alloc (type, 0);
|
PyObject *new_pyobject = type->tp_alloc (type, 0);
|
||||||
new (new_object) PYAObjectBase (clsact);
|
PYAObjectBase *new_object = PYAObjectBase::from_pyobject_unsafe (new_pyobject);
|
||||||
|
new (new_object) PYAObjectBase (clsact, new_pyobject);
|
||||||
clsact->assign (new_object->obj (), obj);
|
clsact->assign (new_object->obj (), obj);
|
||||||
return new_object;
|
return new_pyobject;
|
||||||
|
|
||||||
} else if (pya_object) {
|
} else if (pya_object) {
|
||||||
|
|
||||||
// we have a that is located in C++ space but is supposed to get attached
|
// 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
|
// 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);
|
correct_constness (pya_object, is_const);
|
||||||
|
|
||||||
return pya_object;
|
return pya_object->py_object ();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
|
@ -442,10 +442,11 @@ object_to_python (void *obj, PYAObjectBase *self, const gsi::ClassBase *cls, boo
|
||||||
tl_assert (type != NULL);
|
tl_assert (type != NULL);
|
||||||
|
|
||||||
// create a instance and copy the value
|
// create a instance and copy the value
|
||||||
PYAObjectBase *new_object = (PYAObjectBase *) type->tp_alloc (type, 0);
|
PyObject *new_pyobject = type->tp_alloc (type, 0);
|
||||||
new (new_object) PYAObjectBase (clsact);
|
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);
|
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 (cls_decl != 0);
|
||||||
tl_assert (is_derived_from (cls_decl, typeid (T)));
|
tl_assert (is_derived_from (cls_decl, typeid (T)));
|
||||||
|
|
||||||
PYAObjectBase *p = (PYAObjectBase *) (rval);
|
PYAObjectBase *p = PYAObjectBase::from_pyobject (rval);
|
||||||
return *((T *)p->obj ());
|
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 ()));
|
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 ());
|
gsi::Value *bo = reinterpret_cast<gsi::Value *> (p->obj ());
|
||||||
if (bo) {
|
if (bo) {
|
||||||
*ret = bo->value ().template morph<R> ().native_ptr ();
|
*ret = bo->value ().template morph<R> ().native_ptr ();
|
||||||
|
|
@ -389,7 +389,7 @@ struct writer<gsi::ObjectType>
|
||||||
|
|
||||||
if (cls_decl->is_derived_from (atype.cls ())) {
|
if (cls_decl->is_derived_from (atype.cls ())) {
|
||||||
|
|
||||||
PYAObjectBase *p = (PYAObjectBase *) (arg);
|
PYAObjectBase *p = PYAObjectBase::from_pyobject (arg);
|
||||||
|
|
||||||
if (cls_decl->adapted_type_info ()) {
|
if (cls_decl->adapted_type_info ()) {
|
||||||
// resolved adapted type
|
// resolved adapted type
|
||||||
|
|
@ -400,7 +400,7 @@ struct writer<gsi::ObjectType>
|
||||||
|
|
||||||
} else if (cls_decl->can_convert_to (atype.cls ())) {
|
} 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.
|
// 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.
|
// 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 ())) {
|
if (cls_decl->is_derived_from (atype.cls ())) {
|
||||||
|
|
||||||
PYAObjectBase *p = (PYAObjectBase *) (arg);
|
PYAObjectBase *p = PYAObjectBase::from_pyobject (arg);
|
||||||
|
|
||||||
if (cls_decl->adapted_type_info ()) {
|
if (cls_decl->adapted_type_info ()) {
|
||||||
// resolved adapted type
|
// resolved adapted type
|
||||||
|
|
@ -432,7 +432,7 @@ struct writer<gsi::ObjectType>
|
||||||
|
|
||||||
} else if (cls_decl->can_convert_to (atype.cls ())) {
|
} 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 ()));
|
aa->write<void *> (atype.cls ()->create_obj_from (cls_decl, p->obj ()));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -471,7 +471,7 @@ push_arg (const gsi::ArgType &atype, gsi::SerialArgs &aserial, PyObject *arg, tl
|
||||||
template <class R>
|
template <class R>
|
||||||
struct reader
|
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 ()) {
|
if (arg.is_ref ()) {
|
||||||
*ret = c2python (rr->template read<R &> (*heap));
|
*ret = c2python (rr->template read<R &> (*heap));
|
||||||
|
|
@ -506,7 +506,7 @@ struct reader
|
||||||
template <>
|
template <>
|
||||||
struct reader<void *>
|
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_cref ());
|
||||||
tl_assert (! arg.is_ref ());
|
tl_assert (! arg.is_ref ());
|
||||||
|
|
|
||||||
|
|
@ -575,9 +575,9 @@ static std::string extract_python_name (const std::string &name)
|
||||||
static void
|
static void
|
||||||
pya_object_deallocate (PyObject *self)
|
pya_object_deallocate (PyObject *self)
|
||||||
{
|
{
|
||||||
PYAObjectBase *p = (PYAObjectBase *) self;
|
PYAObjectBase *p = PYAObjectBase::from_pyobject (self);
|
||||||
p->~PYAObjectBase ();
|
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*/)
|
pya_object_new (PyTypeObject *type, PyObject * /*args*/, PyObject * /*kwds*/)
|
||||||
{
|
{
|
||||||
// create the object
|
// create the object
|
||||||
PYAObjectBase *self = (PYAObjectBase *) type->tp_alloc (type, 0);
|
PyObject *self_pyobject = type->tp_alloc (type, 0);
|
||||||
new (self) PYAObjectBase (PythonModule::cls_for_type (type));
|
PYAObjectBase *self = PYAObjectBase::from_pyobject_unsafe (self_pyobject);
|
||||||
return (PyObject *) self;
|
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;
|
const gsi::ClassBase *cls_decl = 0;
|
||||||
|
|
||||||
if (! PyType_Check (self)) {
|
if (! PyType_Check (self)) {
|
||||||
PYAObjectBase *p = (PYAObjectBase *) self;
|
PYAObjectBase *p = PYAObjectBase::from_pyobject (self);
|
||||||
cls_decl = p->cls_decl ();
|
cls_decl = p->cls_decl ();
|
||||||
} else {
|
} else {
|
||||||
cls_decl = PythonModule::cls_for_type ((PyTypeObject *) self);
|
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;
|
const gsi::ClassBase *cls_decl = 0;
|
||||||
|
|
||||||
if (! PyType_Check (self)) {
|
if (! PyType_Check (self)) {
|
||||||
PYAObjectBase *p = (PYAObjectBase *) self;
|
PYAObjectBase *p = PYAObjectBase::from_pyobject (self);
|
||||||
cls_decl = p->cls_decl ();
|
cls_decl = p->cls_decl ();
|
||||||
} else {
|
} else {
|
||||||
cls_decl = PythonModule::cls_for_type ((PyTypeObject *) self);
|
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 ()) {
|
if (meth->ret_type ().is_iter ()) {
|
||||||
|
|
||||||
gsi::IterAdaptorAbstractBase *iter = (gsi::IterAdaptorAbstractBase *) retlist.read<gsi::IterAdaptorAbstractBase *> (heap);
|
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 {
|
} else {
|
||||||
|
|
||||||
|
|
@ -702,7 +703,7 @@ match_method (int mid, PyObject *self, PyObject *args, bool strict)
|
||||||
|
|
||||||
PYAObjectBase *p = 0;
|
PYAObjectBase *p = 0;
|
||||||
if (! PyType_Check (self)) {
|
if (! PyType_Check (self)) {
|
||||||
p = (PYAObjectBase *) self;
|
p = PYAObjectBase::from_pyobject (self);
|
||||||
cls_decl = p->cls_decl ();
|
cls_decl = p->cls_decl ();
|
||||||
} else {
|
} else {
|
||||||
cls_decl = PythonModule::cls_for_type ((PyTypeObject *) self);
|
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 ());
|
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);
|
PythonRef obj (new_object);
|
||||||
new (new_object) PYAObjectBase (cls_decl_self);
|
PYAObjectBase *new_pya_base = PYAObjectBase::from_pyobject_unsafe (new_object);
|
||||||
new_object->set (cls_decl_self->clone (((PYAObjectBase *) self)->obj ()), true, false, false);
|
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 ();
|
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 ());
|
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);
|
Py_INCREF (self);
|
||||||
return self;
|
return self;
|
||||||
|
|
@ -997,7 +999,7 @@ object_create (PyObject *self, PyObject *args)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
((PYAObjectBase *) self)->obj ();
|
(PYAObjectBase::from_pyobject (self))->obj ();
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1011,7 +1013,7 @@ object_release (PyObject *self, PyObject *args)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
((PYAObjectBase *) self)->release ();
|
(PYAObjectBase::from_pyobject (self))->release ();
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1025,7 +1027,7 @@ object_keep (PyObject *self, PyObject *args)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
((PYAObjectBase *) self)->keep ();
|
(PYAObjectBase::from_pyobject (self))->keep ();
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1039,7 +1041,7 @@ object_destroy (PyObject *self, PyObject *args)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
((PYAObjectBase *) self)->destroy ();
|
(PYAObjectBase::from_pyobject (self))->destroy ();
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1053,7 +1055,7 @@ object_destroyed (PyObject *self, PyObject *args)
|
||||||
return NULL;
|
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 NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return c2python (((PYAObjectBase *) self)->const_ref ());
|
return c2python (PYAObjectBase::from_pyobject (self)->const_ref ());
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
|
|
@ -1112,7 +1114,7 @@ method_adaptor (int mid, PyObject *self, PyObject *args)
|
||||||
PYAObjectBase *p = 0;
|
PYAObjectBase *p = 0;
|
||||||
if (! PyType_Check (self)) {
|
if (! PyType_Check (self)) {
|
||||||
// non-static method
|
// non-static method
|
||||||
p = (PYAObjectBase *) self;
|
p = PYAObjectBase::from_pyobject (self);
|
||||||
}
|
}
|
||||||
|
|
||||||
tl::Heap heap;
|
tl::Heap heap;
|
||||||
|
|
@ -1666,7 +1668,7 @@ method_init_adaptor (int mid, PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
PYA_TRY
|
PYA_TRY
|
||||||
|
|
||||||
PYAObjectBase *p = (PYAObjectBase *) self;
|
PYAObjectBase *p = PYAObjectBase::from_pyobject (self);
|
||||||
|
|
||||||
// delete any object which we may have already
|
// delete any object which we may have already
|
||||||
if (p->is_attached ()) {
|
if (p->is_attached ()) {
|
||||||
|
|
@ -1888,7 +1890,7 @@ property_getter_impl (int mid, PyObject *self)
|
||||||
|
|
||||||
PYAObjectBase *p = 0;
|
PYAObjectBase *p = 0;
|
||||||
if (! PyType_Check (self)) {
|
if (! PyType_Check (self)) {
|
||||||
p = (PYAObjectBase *) self;
|
p = PYAObjectBase::from_pyobject (self);
|
||||||
cls_decl = p->cls_decl ();
|
cls_decl = p->cls_decl ();
|
||||||
} else {
|
} else {
|
||||||
cls_decl = PythonModule::cls_for_type ((PyTypeObject *) self);
|
cls_decl = PythonModule::cls_for_type ((PyTypeObject *) self);
|
||||||
|
|
@ -1969,7 +1971,7 @@ property_setter_impl (int mid, PyObject *self, PyObject *value)
|
||||||
|
|
||||||
PYAObjectBase *p = 0;
|
PYAObjectBase *p = 0;
|
||||||
if (! PyType_Check (self)) {
|
if (! PyType_Check (self)) {
|
||||||
p = (PYAObjectBase *) self;
|
p = PYAObjectBase::from_pyobject (self);
|
||||||
cls_decl = p->cls_decl ();
|
cls_decl = p->cls_decl ();
|
||||||
} else {
|
} else {
|
||||||
cls_decl = PythonModule::cls_for_type ((PyTypeObject *) self);
|
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 -
|
// the Python objects were probably deleted by Python itself as it exited -
|
||||||
// don't try to delete them again.
|
// don't try to delete them again.
|
||||||
mp_module.release ();
|
mp_module.release ();
|
||||||
mp_base_class.release ();
|
|
||||||
|
|
||||||
while (!m_methods_heap.empty ()) {
|
while (!m_methods_heap.empty ()) {
|
||||||
delete m_methods_heap.back ();
|
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 ());
|
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
|
// Build a class for descriptors for static attributes
|
||||||
PYAStaticAttributeDescriptorObject::make_class (module);
|
PYAStaticAttributeDescriptorObject::make_class (module);
|
||||||
|
|
||||||
|
|
@ -2434,15 +2405,17 @@ PythonModule::make_classes (const char *mod_name)
|
||||||
|
|
||||||
m_classes.push_back (c.operator-> ());
|
m_classes.push_back (c.operator-> ());
|
||||||
|
|
||||||
PythonRef bases (PyTuple_New (1));
|
PythonRef bases;
|
||||||
PyObject *base = mp_base_class.get ();
|
|
||||||
if (c->base () != 0) {
|
if (c->base () != 0) {
|
||||||
|
bases = PythonRef (PyTuple_New (1));
|
||||||
PyTypeObject *pt = PythonClassClientData::py_type (*c->base ());
|
PyTypeObject *pt = PythonClassClientData::py_type (*c->base ());
|
||||||
tl_assert (pt != 0);
|
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 ());
|
PythonRef dict (PyDict_New ());
|
||||||
PyDict_SetItemString (dict.get (), "__module__", PythonRef (c2python (m_mod_name)).get ());
|
PyDict_SetItemString (dict.get (), "__module__", PythonRef (c2python (m_mod_name)).get ());
|
||||||
|
|
@ -2459,9 +2432,18 @@ PythonModule::make_classes (const char *mod_name)
|
||||||
check_error ();
|
check_error ();
|
||||||
tl_assert (false);
|
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);
|
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 ());
|
PyList_Append (all_list.get (), PythonRef (c2python (c->name ())).get ());
|
||||||
PyModule_AddObject (module, c->name ().c_str (), (PyObject *) type);
|
PyModule_AddObject (module, c->name ().c_str (), (PyObject *) type);
|
||||||
|
|
|
||||||
|
|
@ -120,9 +120,7 @@ private:
|
||||||
std::vector<PyGetSetDef *> m_getseters_heap;
|
std::vector<PyGetSetDef *> m_getseters_heap;
|
||||||
|
|
||||||
std::string m_mod_name, m_mod_description;
|
std::string m_mod_name, m_mod_description;
|
||||||
std::string m_base_class_name;
|
|
||||||
PythonRef mp_module;
|
PythonRef mp_module;
|
||||||
PythonRef mp_base_class;
|
|
||||||
char *mp_mod_def;
|
char *mp_mod_def;
|
||||||
|
|
||||||
static std::map<const gsi::MethodBase *, std::string> m_python_doc;
|
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 ())));
|
PythonRef argv (PyTuple_New (arg4self + std::distance (meth->begin_arguments (), meth->end_arguments ())));
|
||||||
|
|
||||||
// Put self into first argument
|
// Put self into first argument
|
||||||
PyTuple_SetItem (argv.get (), 0, mp_obj);
|
PyTuple_SetItem (argv.get (), 0, mp_obj->py_object ());
|
||||||
Py_INCREF (mp_obj);
|
Py_INCREF (mp_obj->py_object ());
|
||||||
|
|
||||||
// TODO: callbacks with default arguments?
|
// TODO: callbacks with default arguments?
|
||||||
for (gsi::MethodBase::argument_iterator a = meth->begin_arguments (); args && a != meth->end_arguments (); ++a) {
|
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
|
// Implementation of PYAObjectBase
|
||||||
|
|
||||||
PYAObjectBase::PYAObjectBase(const gsi::ClassBase *_cls_decl)
|
PYAObjectBase::PYAObjectBase(const gsi::ClassBase *_cls_decl, PyObject *py_object)
|
||||||
: m_listener (new pya::StatusChangedListener (this)),
|
: mp_py_object (py_object),
|
||||||
|
m_listener (new pya::StatusChangedListener (this)),
|
||||||
m_callee (new pya::Callee (this)),
|
m_callee (new pya::Callee (this)),
|
||||||
m_cls_decl (_cls_decl),
|
m_cls_decl (_cls_decl),
|
||||||
m_obj (0),
|
m_obj (0),
|
||||||
|
|
@ -179,6 +180,7 @@ PYAObjectBase::PYAObjectBase(const gsi::ClassBase *_cls_decl)
|
||||||
m_destroyed (false),
|
m_destroyed (false),
|
||||||
m_can_destroy (false)
|
m_can_destroy (false)
|
||||||
{
|
{
|
||||||
|
// .. nothing yet ..
|
||||||
}
|
}
|
||||||
|
|
||||||
PYAObjectBase::~PYAObjectBase ()
|
PYAObjectBase::~PYAObjectBase ()
|
||||||
|
|
@ -223,7 +225,7 @@ PYAObjectBase::object_destroyed ()
|
||||||
|
|
||||||
// NOTE: this may delete "this"!
|
// NOTE: this may delete "this"!
|
||||||
if (!prev_owner) {
|
if (!prev_owner) {
|
||||||
Py_DECREF (this);
|
Py_DECREF (py_object ());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -246,7 +248,7 @@ PYAObjectBase::release ()
|
||||||
if (!m_owned) {
|
if (!m_owned) {
|
||||||
m_owned = true;
|
m_owned = true;
|
||||||
// NOTE: this may delete "this"! TODO: this should not happen. Can we assert that somehow?
|
// 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 ()
|
PYAObjectBase::keep_internal ()
|
||||||
{
|
{
|
||||||
if (m_owned) {
|
if (m_owned) {
|
||||||
Py_INCREF (this);
|
Py_INCREF (py_object ());
|
||||||
m_owned = false;
|
m_owned = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -328,7 +330,7 @@ PYAObjectBase::set (void *obj, bool owned, bool const_ref, bool can_destroy)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_owned) {
|
if (!m_owned) {
|
||||||
Py_INCREF (this);
|
Py_INCREF (py_object ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -353,7 +355,7 @@ PYAObjectBase::initialize_callbacks ()
|
||||||
// TODO: caching appears to create some leaks ...
|
// TODO: caching appears to create some leaks ...
|
||||||
#if 1
|
#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)
|
// 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
|
// 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
|
// 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.
|
// 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.
|
// 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) {
|
if (! py_attr) {
|
||||||
|
|
||||||
// because PyObject_GetAttrString left an error
|
// because PyObject_GetAttrString left an error
|
||||||
|
|
@ -423,7 +425,7 @@ PYAObjectBase::initialize_callbacks ()
|
||||||
|
|
||||||
PythonRef py_attr;
|
PythonRef py_attr;
|
||||||
const char *nstr = (*m)->primary_name ().c_str ();
|
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));
|
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 ()));
|
(*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
|
// 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.
|
// 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.
|
// 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) {
|
if (! py_attr) {
|
||||||
|
|
||||||
// because PyObject_GetAttrString left an error
|
// 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)
|
// may create issues with callbacks during destruction (i.e. QWidget-destroyed signal)
|
||||||
if (! PyCFunction_Check (py_attr.get ())) {
|
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);
|
tl_assert (py_attr != NULL);
|
||||||
int id = m_callee.add_callback (CallbackFunction (py_attr, *m));
|
int id = m_callee.add_callback (CallbackFunction (py_attr, *m));
|
||||||
(*m)->set_callback (m_obj, gsi::Callback (id, &m_callee, (*m)->argsize (), (*m)->retsize ()));
|
(*m)->set_callback (m_obj, gsi::Callback (id, &m_callee, (*m)->argsize (), (*m)->retsize ()));
|
||||||
|
|
@ -501,7 +503,7 @@ PYAObjectBase::clear_callbacks_cache ()
|
||||||
void
|
void
|
||||||
PYAObjectBase::detach_callbacks ()
|
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);
|
callbacks_cache::iterator cb = s_callbacks_cache.find (type_ref);
|
||||||
if (cb != s_callbacks_cache.end ()) {
|
if (cb != s_callbacks_cache.end ()) {
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,8 @@
|
||||||
#include "pyaRefs.h"
|
#include "pyaRefs.h"
|
||||||
#include "pyaCommon.h"
|
#include "pyaCommon.h"
|
||||||
|
|
||||||
|
#include "tlAssert.h"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
@ -50,23 +52,43 @@ class StatusChangedListener;
|
||||||
/**
|
/**
|
||||||
* @brief The Python object representing a GSI object
|
* @brief The Python object representing a GSI object
|
||||||
*
|
*
|
||||||
* Note: the PYAObjectBase must be directly derived from PyObject so that
|
* NOTE: this memory block is attached to the actual structure
|
||||||
* a PyObject pointer can be cast to a PYAObjectBase pointer.
|
* 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
|
class PYA_PUBLIC PYAObjectBase
|
||||||
: public PyObject
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @brief Constructor - creates a new object for the given GSI class
|
* @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
|
* @brief Destructor
|
||||||
*/
|
*/
|
||||||
~PYAObjectBase ();
|
~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
|
* @brief Indicates that a C++ object is present
|
||||||
*/
|
*/
|
||||||
|
|
@ -142,6 +164,14 @@ public:
|
||||||
m_const_ref = c;
|
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
|
* @brief Returns the C++ object reference
|
||||||
*/
|
*/
|
||||||
|
|
@ -189,6 +219,7 @@ private:
|
||||||
void object_destroyed ();
|
void object_destroyed ();
|
||||||
void keep_internal ();
|
void keep_internal ();
|
||||||
|
|
||||||
|
PyObject *mp_py_object;
|
||||||
std::auto_ptr<StatusChangedListener> m_listener;
|
std::auto_ptr<StatusChangedListener> m_listener;
|
||||||
std::auto_ptr<Callee> m_callee;
|
std::auto_ptr<Callee> m_callee;
|
||||||
const gsi::ClassBase *m_cls_decl;
|
const gsi::ClassBase *m_cls_decl;
|
||||||
|
|
|
||||||
|
|
@ -2718,6 +2718,7 @@ class BasicTest(unittest.TestCase):
|
||||||
go = None
|
go = None
|
||||||
self.assertEqual(pya.GObject.g_inst_count(), gc)
|
self.assertEqual(pya.GObject.g_inst_count(), gc)
|
||||||
|
|
||||||
|
|
||||||
# run unit tests
|
# run unit tests
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
suite = unittest.TestSuite()
|
suite = unittest.TestSuite()
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue