diff --git a/src/gsiqt/qt5/qt5.pro b/src/gsiqt/qt5/qt5.pro index bdc683f44..5a435a3b8 100644 --- a/src/gsiqt/qt5/qt5.pro +++ b/src/gsiqt/qt5/qt5.pro @@ -19,7 +19,7 @@ QtNetwork.depends += QtCore QtSql.depends += QtCore QtWidgets.depends += QtGui QtDesigner.depends += QtCore -QtMultimedia.depends += QtCore QtWidgets +QtMultimedia.depends += QtCore QtWidgets QtNetwork QtPrintSupport.depends += QtCore QtWidgets QtSvg.depends += QtCore QtWidgets QtXmlPatterns.depends += QtCore diff --git a/src/pya/pya/pya.cc b/src/pya/pya/pya.cc index 0690df78f..5cd104234 100644 --- a/src/pya/pya/pya.cc +++ b/src/pya/pya/pya.cc @@ -542,7 +542,7 @@ PythonInterpreter::define_variable (const std::string &name, const std::string & PythonPtr main_module (PyImport_AddModule ("__main__")); PythonPtr dict (PyModule_GetDict (main_module.get ())); if (dict) { - PythonRef v (c2python (value)); + PythonRef v (c2python (value)); PyDict_SetItemString (dict.get (), name.c_str (), v.get ()); } } diff --git a/src/pya/pya/pyaConvert.cc b/src/pya/pya/pyaConvert.cc index c560065b8..b99208f67 100644 --- a/src/pya/pya/pyaConvert.cc +++ b/src/pya/pya/pyaConvert.cc @@ -444,24 +444,24 @@ template <> PyObject *c2python_func::operator() (const tl::Variant &c) { if (c.is_double ()) { - return c2python (c.to_double ()); + return c2python (c.to_double ()); } else if (c.is_bool ()) { - return c2python (c.to_bool ()); + return c2python (c.to_bool ()); } else if (c.is_a_string ()) { - return c2python (c.to_string ()); + return c2python (c.to_string ()); } else if (c.is_long ()) { - return c2python (c.to_long ()); + return c2python (c.to_long ()); } else if (c.is_ulong ()) { - return c2python (c.to_ulong ()); + return c2python (c.to_ulong ()); } else if (c.is_longlong ()) { - return c2python (c.to_longlong ()); + return c2python (c.to_longlong ()); } else if (c.is_ulonglong ()) { - return c2python (c.to_ulonglong ()); + return c2python (c.to_ulonglong ()); } else if (c.is_array ()) { PyObject *ret = PyDict_New (); for (tl::Variant::const_array_iterator i = c.begin_array (); i != c.end_array (); ++i) { - PyDict_SetItem (ret, c2python (i->first), c2python (i->second)); + PyDict_SetItem (ret, c2python (i->first), c2python (i->second)); } return ret; @@ -470,7 +470,7 @@ PyObject *c2python_func::operator() (const tl::Variant &c) PyObject *ret = PyList_New (c.get_list ().size ()); size_t index = 0; for (tl::Variant::const_iterator i = c.begin (); i != c.end (); ++i, ++index) { - PyList_SetItem (ret, index, c2python (*i)); + PyList_SetItem (ret, index, c2python (*i)); } return ret; @@ -545,7 +545,7 @@ PyObject *c2python_func::operator() (const QString &qs) } else { // TODO: can be done more efficently std::string c (tl::to_string (qs)); - return c2python (c); + return c2python (c); } } diff --git a/src/pya/pya/pyaConvert.h b/src/pya/pya/pyaConvert.h index bd83d1724..ea1b0217d 100644 --- a/src/pya/pya/pyaConvert.h +++ b/src/pya/pya/pyaConvert.h @@ -24,8 +24,9 @@ #ifndef _HDR_pyaConvert #define _HDR_pyaConvert -#include "Python.h" +#include +#include "pyaCommon.h" #include "pyaModule.h" #include "pyaObject.h" #include "gsiClassBase.h" @@ -63,14 +64,14 @@ class PYAObjectBase; * @param can_destroy If true, the Python object can be destroyed explicitly * @return The Python object */ -PyObject * +PYA_PUBLIC PyObject * object_to_python (void *obj, PYAObjectBase *self, const gsi::ClassBase *cls, bool pass_obj, bool is_const, bool prefer_copy, bool can_destroy); /** * @brief Translates an object to a Python object (PyObject) * This version takes it's flags from the atype given. */ -PyObject * +PYA_PUBLIC PyObject * object_to_python (void *obj, PYAObjectBase *self, const gsi::ArgType &atype); // ------------------------------------------------------------------- @@ -239,7 +240,7 @@ struct test_type_func * @param loose If true, the type is checked more loosely. Use for second-pass matching. */ template -inline bool test_type (PyObject * rval, bool loose) +inline bool test_type (PyObject * rval, bool loose = false) { return test_type_func () (rval, loose); } @@ -248,7 +249,7 @@ inline bool test_type (PyObject * rval, bool loose) * @brief Test a PyObject *for compatibility with a vector of the given type R */ template -inline bool test_vector (PyObject *arr, bool loose) +inline bool test_vector (PyObject *arr, bool loose = false) { if (PyList_Check (arr)) { @@ -283,13 +284,16 @@ inline bool test_vector (PyObject *arr, bool loose) template struct python2c_func { - T operator() (PyObject *rval); + T operator() (PyObject * /*rval*/) + { + tl_assert (false); // type not bound + } }; -template <> long python2c_func::operator() (PyObject *rval); -template <> unsigned long python2c_func::operator() (PyObject *rval); -template <> bool python2c_func::operator() (PyObject *rval); -template <> char python2c_func::operator() (PyObject *rval); +template <> PYA_PUBLIC long python2c_func::operator() (PyObject *rval); +template <> PYA_PUBLIC unsigned long python2c_func::operator() (PyObject *rval); +template <> PYA_PUBLIC bool python2c_func::operator() (PyObject *rval); +template <> PYA_PUBLIC char python2c_func::operator() (PyObject *rval); template struct python2c_func_cast @@ -308,23 +312,23 @@ template <> struct python2c_func : public python2c_func_cast struct python2c_func : public python2c_func_cast { }; template <> struct python2c_func : public python2c_func_cast { }; -template <> long long python2c_func::operator() (PyObject *rval); -template <> unsigned long long python2c_func::operator() (PyObject *rval); +template <> PYA_PUBLIC long long python2c_func::operator() (PyObject *rval); +template <> PYA_PUBLIC unsigned long long python2c_func::operator() (PyObject *rval); #if defined(HAVE_64BIT_COORD) template <> __int128 python2c_func<__int128>::operator() (PyObject *rval); #endif -template <> double python2c_func::operator() (PyObject *rval); +template <> PYA_PUBLIC double python2c_func::operator() (PyObject *rval); template <> struct python2c_func : public python2c_func_cast { }; -template <> std::string python2c_func::operator() (PyObject *rval); -template <> QByteArray python2c_func::operator() (PyObject *rval); -template <> QString python2c_func::operator() (PyObject *rval); +template <> PYA_PUBLIC std::string python2c_func::operator() (PyObject *rval); +template <> PYA_PUBLIC QByteArray python2c_func::operator() (PyObject *rval); +template <> PYA_PUBLIC QString python2c_func::operator() (PyObject *rval); template <> struct python2c_func : public python2c_func_cast { }; -template <> tl::Variant python2c_func::operator() (PyObject *rval); +template <> PYA_PUBLIC tl::Variant python2c_func::operator() (PyObject *rval); template struct python2c_func { @@ -593,10 +597,14 @@ struct c2python_func } }; -template <> PyObject *c2python_func::operator() (const char *); -template <> PyObject *c2python_func::operator() (const QString &c); -template <> PyObject *c2python_func::operator() (const QByteArray &c); -template <> PyObject *c2python_func::operator() (const std::string &c); +template <> PYA_PUBLIC PyObject *c2python_func::operator() (const char *); + +template <> PYA_PUBLIC PyObject *c2python_func::operator() (const QString &c); +template <> struct c2python_func : public c2python_func { }; +template <> PYA_PUBLIC PyObject *c2python_func::operator() (const QByteArray &c); +template <> struct c2python_func : public c2python_func { }; +template <> PYA_PUBLIC PyObject *c2python_func::operator() (const std::string &c); +template <> struct c2python_func : public c2python_func { }; template <> struct c2python_func @@ -608,7 +616,8 @@ struct c2python_func } }; -template <> PyObject *c2python_func::operator() (const tl::Variant &c); +template <> PYA_PUBLIC PyObject *c2python_func::operator() (const tl::Variant &c); +template <> struct c2python_func : public c2python_func { }; /** * @brief Converts the Python object to the given type diff --git a/src/pya/pya/pyaMarshal.cc b/src/pya/pya/pyaMarshal.cc index 497f7763d..8a15730ef 100644 --- a/src/pya/pya/pyaMarshal.cc +++ b/src/pya/pya/pyaMarshal.cc @@ -474,25 +474,25 @@ struct reader void operator() (gsi::SerialArgs *rr, PythonRef *ret, PyObject * /*self*/, const gsi::ArgType &arg, tl::Heap *heap) { if (arg.is_ref ()) { - *ret = c2python (rr->template read (*heap)); + *ret = c2python (rr->template read (*heap)); } else if (arg.is_cref ()) { - *ret = c2python (rr->template read (*heap)); + *ret = c2python (rr->template read (*heap)); } else if (arg.is_ptr ()) { R *p = rr->template read (*heap); if (p) { - *ret = c2python (*p); + *ret = c2python (*p); } else { *ret = PythonRef (Py_None, false /*borrowed*/); } } else if (arg.is_cptr ()) { const R *p = rr->template read (*heap); if (p) { - *ret = c2python (*p); + *ret = c2python (*p); } else { *ret = PythonRef (Py_None, false /*borrowed*/); } } else { - *ret = c2python (rr->template read (*heap)); + *ret = c2python (rr->template read (*heap)); } } }; @@ -512,7 +512,7 @@ struct reader tl_assert (! arg.is_ref ()); tl_assert (! arg.is_cptr ()); tl_assert (! arg.is_ptr ()); - *ret = c2python (rr->read (*heap)); + *ret = c2python (rr->read (*heap)); } }; @@ -528,7 +528,7 @@ struct reader if (!a.get ()) { *ret = PythonRef (Py_None, false /*borrowed*/); } else { - *ret = c2python (std::string (a->c_str (), a->size ())); + *ret = c2python (std::string (a->c_str (), a->size ())); } } }; @@ -582,7 +582,7 @@ PyObject *object_from_variant (const tl::Variant &var, PYAObjectBase *self, cons return object_to_python ((void *) var.to_user (), self, var.user_cls ()->gsi_cls (), pass_obj, is_const, prefer_copy, can_destroy); } else { - return c2python (var); + return c2python (var); } } diff --git a/src/pya/pya/pyaModule.cc b/src/pya/pya/pyaModule.cc index 0eb32b6c6..2b5f0f457 100644 --- a/src/pya/pya/pyaModule.cc +++ b/src/pya/pya/pyaModule.cc @@ -35,18 +35,6 @@ namespace pya { -// ------------------------------------------------------------------- -// A metatype object to identify the pya types - -struct PYAMetaType : public PyTypeObject { }; -static PYAMetaType PYA_MetaType; - -struct PYATypeObject - : public PyTypeObject -{ - const gsi::ClassBase *cls; -}; - // ------------------------------------------------------------------- // The lookup table for the method overload resolution @@ -930,7 +918,7 @@ object_default_ne_impl (PyObject *self, PyObject *args) if (! res) { return NULL; } else { - return c2python (! python2c (res.get ())); + return c2python (! python2c (res.get ())); } } @@ -947,7 +935,7 @@ object_default_ge_impl (PyObject *self, PyObject *args) if (! res) { return NULL; } else { - return c2python (! python2c (res.get ())); + return c2python (! python2c (res.get ())); } } @@ -971,7 +959,7 @@ object_default_le_impl (PyObject *self, PyObject *args) if (! lt_res) { return NULL; } - return c2python (python2c (eq_res.get ()) || python2c (lt_res.get ())); + return c2python (python2c (eq_res.get ()) || python2c (lt_res.get ())); } /** @@ -994,7 +982,7 @@ object_default_gt_impl (PyObject *self, PyObject *args) if (! lt_res) { return NULL; } - return c2python (! (python2c (eq_res.get ()) || python2c (lt_res.get ()))); + return c2python (! (python2c (eq_res.get ()) || python2c (lt_res.get ()))); } /** @@ -1063,7 +1051,7 @@ object_destroyed (PyObject *self, PyObject *args) return NULL; } - return c2python (((PYAObjectBase *) self)->destroyed ()); + return c2python (((PYAObjectBase *) self)->destroyed ()); } /** @@ -1076,7 +1064,7 @@ object_is_const (PyObject *self, PyObject *args) return NULL; } - return c2python (((PYAObjectBase *) self)->const_ref ()); + return c2python (((PYAObjectBase *) self)->const_ref ()); } static PyObject * @@ -2149,6 +2137,7 @@ property_setter_func (PyObject *self, PyObject *value, void *closure) // The PythonModule implementation std::map PythonModule::m_python_doc; +std::vector PythonModule::m_classes; const std::string pymod_name ("pykl"); @@ -2350,16 +2339,10 @@ PythonModule::make_classes (const char *mod_name) m_base_class_name = m_mod_name + ".__Base"; - // Late-initialize PYA_MetaType (we can do this multiple times as the initialization does not - // change anything). PYATypeObject adds one pointer member at the end. - memcpy(&PYA_MetaType, &PyType_Type, sizeof (PyType_Type)); - PYA_MetaType.tp_basicsize += sizeof (void *); - - PYATypeObject *base_class = (PYATypeObject *) PyType_Type.tp_alloc (&PYA_MetaType, sizeof (PYATypeObject)); + 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->cls = 0; // base class base_class->tp_base = &PyBaseObject_Type; base_class->tp_name = m_base_class_name.c_str (); base_class->tp_basicsize = sizeof (PYAObjectBase); @@ -2442,6 +2425,11 @@ PythonModule::make_classes (const char *mod_name) any = true; + + // Create the actual class + + m_classes.push_back (c.operator-> ()); + PythonRef bases (PyTuple_New (1)); PyObject *base = mp_base_class.get (); if (c->base () != 0) { @@ -2455,16 +2443,21 @@ PythonModule::make_classes (const char *mod_name) PythonRef dict (PyDict_New ()); PyDict_SetItemString (dict.get (), "__module__", PythonRef (c2python (m_mod_name)).get ()); PyDict_SetItemString (dict.get (), "__doc__", PythonRef (c2python (c->doc ())).get ()); + PyDict_SetItemString (dict.get (), "__gsi_id__", PythonRef (c2python (m_classes.size () - 1)).get ()); PythonRef args (PyTuple_New (3)); PyTuple_SetItem (args.get (), 0, c2python (c->name ())); PyTuple_SetItem (args.get (), 1, bases.release ()); PyTuple_SetItem (args.get (), 2, dict.release ()); - PYATypeObject *type = (PYATypeObject *) PyObject_Call ((PyObject *) &PYA_MetaType, args.get (), NULL); - type->cls = c.operator-> (); + PyTypeObject *type = (PyTypeObject *) PyObject_Call ((PyObject *) &PyType_Type, args.get (), NULL); + if (type == NULL) { + check_error (); + tl_assert (false); + } PythonClassClientData::initialize (*c, type); - tl_assert (type != NULL); + + 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); @@ -2888,7 +2881,7 @@ PythonModule::make_classes (const char *mod_name) } else { PyObject *desc = PYAAmbiguousMethodDispatcher::create (attr_inst, attr_class); - PythonRef name (c2python (*a)); + PythonRef name (c2python (*a)); // Note: we use GenericSetAttr since that one allows us setting attributes on built-in types PyObject_GenericSetAttr ((PyObject *) type, name.get (), desc); @@ -2910,14 +2903,19 @@ PythonModule::make_classes (const char *mod_name) const gsi::ClassBase *PythonModule::cls_for_type (PyTypeObject *type) { - while (type) { - // all pya class use our own metatype - if (type->ob_type == &PYA_MetaType) { - return ((PYATypeObject *)type)->cls; + // GSI classes store their class index inside the __gsi_id__ attribute + if (PyObject_HasAttrString ((PyObject *) type, "__gsi_id__")) { + + PyObject *cls_id = PyObject_GetAttrString ((PyObject *) type, "__gsi_id__"); + if (cls_id != NULL && pya::test_type (cls_id)) { + size_t i = pya::python2c (cls_id); + if (i < m_classes.size ()) { + return m_classes [i]; + } } - // not found - try base class - type = type->tp_base; + } + return 0; } diff --git a/src/pya/pya/pyaModule.h b/src/pya/pya/pyaModule.h index 2bccf50ee..d68093d85 100644 --- a/src/pya/pya/pyaModule.h +++ b/src/pya/pya/pyaModule.h @@ -112,6 +112,7 @@ private: char *mp_mod_def; static std::map m_python_doc; + static std::vector m_classes; }; } diff --git a/src/pya/pya/pyaObject.h b/src/pya/pya/pyaObject.h index e786ecf41..78904abd8 100644 --- a/src/pya/pya/pyaObject.h +++ b/src/pya/pya/pyaObject.h @@ -32,6 +32,7 @@ #include "tlObject.h" #include "pyaRefs.h" +#include "pyaCommon.h" namespace pya { @@ -176,7 +177,7 @@ private: * Note: the PYAObjectBase must be directly derived from PyObject so that * a PyObject pointer can be cast to a PYAObjectBase pointer. */ -class PYAObjectBase +class PYA_PUBLIC PYAObjectBase : public PyObject { public: diff --git a/src/pya/pya/pyaRefs.cc b/src/pya/pya/pyaRefs.cc index a44a870ec..bc134d84b 100644 --- a/src/pya/pya/pyaRefs.cc +++ b/src/pya/pya/pyaRefs.cc @@ -114,13 +114,13 @@ PyObject *PythonRef::release () PythonPtr::PythonPtr () : mp_obj (NULL) -{ +{ // .. nothing yet .. } PythonPtr::PythonPtr (PyObject *obj) : mp_obj (obj) -{ +{ Py_XINCREF (obj); } diff --git a/src/pya/pya/pyaRefs.h b/src/pya/pya/pyaRefs.h index fe3a1f5aa..e1265b5aa 100644 --- a/src/pya/pya/pyaRefs.h +++ b/src/pya/pya/pyaRefs.h @@ -24,6 +24,8 @@ #ifndef _HDR_pyaRefs #define _HDR_pyaRefs +#include "pyaCommon.h" + struct _object; typedef _object PyObject; @@ -41,7 +43,7 @@ class PythonPtr; * borrowed references too. * PythonRef will basically become the owner of the referred object. */ -class PythonRef +class PYA_PUBLIC PythonRef { public: /** @@ -140,7 +142,7 @@ private: * This reference represents borrowed references. Upon construction and destruction, this * object will automatically increment and decrement the reference count. */ -class PythonPtr +class PYA_PUBLIC PythonPtr { public: /** diff --git a/src/pymod/QtMultimedia/QtMultimedia.pro b/src/pymod/QtMultimedia/QtMultimedia.pro index e0c6ec121..07bb11055 100644 --- a/src/pymod/QtMultimedia/QtMultimedia.pro +++ b/src/pymod/QtMultimedia/QtMultimedia.pro @@ -8,4 +8,4 @@ SOURCES = \ HEADERS += \ -LIBS += -lklayout_QtMultimedia +LIBS += -lklayout_QtMultimedia -lklayout_QtNetwork diff --git a/src/pymod/QtMultimedia/QtMultimediaMain.cc b/src/pymod/QtMultimedia/QtMultimediaMain.cc index ebf03244d..321dbd69d 100644 --- a/src/pymod/QtMultimedia/QtMultimediaMain.cc +++ b/src/pymod/QtMultimedia/QtMultimediaMain.cc @@ -26,4 +26,9 @@ #include "../../gsiqt/qtbasic/gsiQtMultimediaExternals.h" FORCE_LINK_GSI_QTMULTIMEDIA +// This is required because QAction and QWidget are used are arguments in QtGui, but are +// defined in QtWidgets +#include "../../gsiqt/qtbasic/gsiQtNetworkExternals.h" +FORCE_LINK_GSI_QTNETWORK + DEFINE_PYMOD(QtMultimedia, "QtMultimedia", "KLayout/Qt module 'QtMultimedia'") diff --git a/src/pymod/pymod.pri b/src/pymod/pymod.pri index f4dcc6155..9f6ab1953 100644 --- a/src/pymod/pymod.pri +++ b/src/pymod/pymod.pri @@ -3,7 +3,9 @@ DESTDIR = $$OUT_PWD/.. LIBDIR = $$OUT_PWD/../.. DESTDIR_PYMOD = $$LIBDIR/pykl -include($$PWD/../lib.pri) +TEMPLATE = lib + +include($$PWD/../klayout.pri) INCLUDEPATH += $$PYTHONINCLUDE $$TL_INC $$GSI_INC $$PYA_INC DEPENDPATH += $$PYTHONINCLUDE $$TL_INC $$GSI_INC $$PYA_INC diff --git a/src/pymod/pymod.pro b/src/pymod/pymod.pro index 42dcaf917..ef24ef8d8 100644 --- a/src/pymod/pymod.pro +++ b/src/pymod/pymod.pro @@ -35,5 +35,8 @@ equals(HAVE_QTBINDINGS, "1") { } ALL_DIRS = $$SUBDIRS + SUBDIRS += unit_tests -unit_tests.depends += $$ALL_DIRS +SUBDIRS += bridge_sample + +unit_tests.depends += $$ALL_DIRS bridge_sample