diff --git a/src/gsi/gsi/gsi.cc b/src/gsi/gsi/gsi.cc index 39a6bbe99..208a5c2f6 100644 --- a/src/gsi/gsi/gsi.cc +++ b/src/gsi/gsi/gsi.cc @@ -35,16 +35,15 @@ namespace gsi void GSI_PUBLIC initialize () { - // Allow duplicate initialization without any effect - static bool s_is_initialized = false; - if (s_is_initialized) { + // do something only if there are new classes + if (gsi::ClassBase::begin_new_classes () == gsi::ClassBase::end_new_classes ()) { return; } - s_is_initialized = true; tl::SelfTimer timer (tl::verbosity () >= 21, "Initializing script environment"); - for (gsi::ClassBase::class_iterator c = gsi::ClassBase::begin_classes (); c != gsi::ClassBase::end_classes (); ++c) { + // Do a first initialization of the new classes because they might add more classes + for (gsi::ClassBase::class_iterator c = gsi::ClassBase::begin_new_classes (); c != gsi::ClassBase::end_new_classes (); ++c) { // TODO: get rid of that const cast (const_cast (&*c))->initialize (); } @@ -52,6 +51,7 @@ initialize () // merge the extensions to the main declaration gsi::ClassBase::merge_declarations (); + // do a full re-initialization - maybe merge_declarations modified existing classes too for (gsi::ClassBase::class_iterator c = gsi::ClassBase::begin_classes (); c != gsi::ClassBase::end_classes (); ++c) { // Initialize the method table once again after we have merged the declarations // TODO: get rid of that const cast @@ -61,6 +61,9 @@ initialize () tl_assert (c->declaration () == &*c); } + // build or rebuild the variant user class table + // NOTE: as the variant classes are tied to the gsi::Class objects, we can rebuild the table + // and will get the same pointers for the classes that have been there before tl::VariantUserClassBase::clear_class_table (); for (gsi::ClassBase::class_iterator c = gsi::ClassBase::begin_classes (); c != gsi::ClassBase::end_classes (); ++c) { diff --git a/src/gsi/gsi/gsiClassBase.cc b/src/gsi/gsi/gsiClassBase.cc index 3fda17d5d..0b609f590 100644 --- a/src/gsi/gsi/gsiClassBase.cc +++ b/src/gsi/gsi/gsiClassBase.cc @@ -38,15 +38,36 @@ namespace gsi // ClassBase implementation ClassBase::class_collection *ClassBase::mp_class_collection = 0; +ClassBase::class_collection *ClassBase::mp_new_class_collection = 0; + +namespace { + struct type_info_compare + { + bool operator() (const std::type_info *a, const std::type_info *b) const + { + return a->before (*b); + } + }; +} + +// TODO: thread-safe? Unlikely that multiple threads access this member - +// we do a initial scan and after this no more write access here. +static std::map s_ti_to_class; ClassBase::ClassBase (const std::string &doc, const Methods &mm, bool do_register) : mp_base (0), mp_parent (0), m_doc (doc), m_methods (mm) { if (do_register) { - if (! mp_class_collection) { - mp_class_collection = new class_collection (); + + // enter the class into the "new" collection + if (! mp_new_class_collection) { + mp_new_class_collection = new class_collection (); } - mp_class_collection->push_back (this); + mp_new_class_collection->push_back (this); + + // invalidate the "typeinfo to class" map + s_ti_to_class.clear (); + } } @@ -186,6 +207,17 @@ ClassBase::collection () } } +const ClassBase::class_collection & +ClassBase::new_collection () +{ + if (!mp_new_class_collection) { + static const class_collection empty; + return empty; + } else { + return *mp_new_class_collection; + } +} + static SpecialMethod * sm_default_ctor (const char *name, const gsi::ClassBase *cls) { @@ -340,127 +372,132 @@ sm_assign (const char *name, const gsi::ClassBase *cls) void ClassBase::merge_declarations () { - tl_assert (mp_class_collection != 0); + if (gsi::ClassBase::begin_new_classes () == gsi::ClassBase::end_new_classes ()) { + // Nothing to do. + return; + } - // merge the extensions to the main declaration - static bool merged = false; - if (! merged) { - - // HINT: this code block must be called exactly ONCE! - merged = true; - - // Check for duplicate declarations - std::set types; - std::set names; - for (gsi::ClassBase::class_iterator c = gsi::ClassBase::begin_classes (); c != gsi::ClassBase::end_classes (); ++c) { - if (c->declaration () == &*c && !types.insert (&c->type ()).second) { - tl::warn << "Duplicate GSI declaration of type " << c->type ().name (); - } - if (c->declaration () == &*c && !names.insert (c->declaration ()->name ()).second) { - tl::warn << "Duplicate GSI declaration of name " << c->declaration ()->name (); - } + // Check for duplicate declarations + std::set types; + std::set names; + for (gsi::ClassBase::class_iterator c = gsi::ClassBase::begin_classes (); c != gsi::ClassBase::end_classes (); ++c) { + if (c->declaration () == &*c && !types.insert (&c->type ()).second) { + tl::warn << "Duplicate GSI declaration of type " << c->type ().name (); } - - std::vector to_remove; - - // Consolidate the classes (merge, remove etc.) - for (gsi::ClassBase::class_iterator c = gsi::ClassBase::begin_classes (); c != gsi::ClassBase::end_classes (); ++c) { - if (! c->consolidate()) { - to_remove.push_back (&*c); - } + if (c->declaration () == &*c && !names.insert (c->declaration ()->name ()).second) { + tl::warn << "Duplicate GSI declaration of name " << c->declaration ()->name (); } + } - // removed the classes which are no longer required - for (std::vector ::const_iterator ed = to_remove.begin (); ed != to_remove.end (); ++ed) { + std::vector to_remove; + + // Consolidate the classes (merge, remove etc.) + for (gsi::ClassBase::class_iterator c = gsi::ClassBase::begin_new_classes (); c != gsi::ClassBase::end_new_classes (); ++c) { + if (! c->consolidate()) { + to_remove.push_back (&*c); + } + } + + // removed the classes which are no longer required + for (std::vector ::const_iterator ed = to_remove.begin (); ed != to_remove.end (); ++ed) { + // TODO: ugly const_cast hack + mp_new_class_collection->erase (const_cast (*ed)); + } + + // collect the subclasses of a class + for (gsi::ClassBase::class_iterator c = gsi::ClassBase::begin_new_classes (); c != gsi::ClassBase::end_new_classes (); ++c) { + if (c->base ()) { // TODO: ugly const_cast hack - mp_class_collection->erase (const_cast (*ed)); + const_cast (c->base ())->m_subclasses.push_back (const_cast (c.operator-> ())); } + } - // collect the subclasses of a class - for (gsi::ClassBase::class_iterator c = gsi::ClassBase::begin_classes (); c != gsi::ClassBase::end_classes (); ++c) { - if (c->base ()) { - // TODO: ugly const_cast hack - const_cast (c->base ())->m_subclasses.push_back (const_cast (c.operator-> ())); + // Add to the classes the special methods and clean up the method table + for (gsi::ClassBase::class_iterator c = gsi::ClassBase::begin_new_classes (); c != gsi::ClassBase::end_new_classes (); ++c) { + + std::set > name_map; + for (gsi::ClassBase::method_iterator m = c->begin_methods (); m != c->end_methods (); ++m) { + for (gsi::MethodBase::synonym_iterator syn = (*m)->begin_synonyms (); syn != (*m)->end_synonyms (); ++syn) { + name_map.insert (std::make_pair (syn->name, (*m)->is_static ())); } } - // Add to the classes the special methods and clean up the method table - for (gsi::ClassBase::class_iterator c = gsi::ClassBase::begin_classes (); c != gsi::ClassBase::end_classes (); ++c) { + // We don't want the declaration object to be non-const except for this case. So + // we const_cast here. + gsi::ClassBase *non_const_decl = const_cast (c.operator-> ()); - std::set > name_map; - for (gsi::ClassBase::method_iterator m = c->begin_methods (); m != c->end_methods (); ++m) { - for (gsi::MethodBase::synonym_iterator syn = (*m)->begin_synonyms (); syn != (*m)->end_synonyms (); ++syn) { - name_map.insert (std::make_pair (syn->name, (*m)->is_static ())); - } - } + if (name_map.find (std::make_pair ("new", true)) == name_map.end ()) { + non_const_decl->add_method (sm_default_ctor ("new", &*c), false); + } - // We don't want the declaration object to be non-const except for this case. So - // we const_cast here. - gsi::ClassBase *non_const_decl = const_cast (&*c); + // Note: "unmanage" and "manage" is a better name ... + non_const_decl->add_method (sm_keep ("_unmanage")); + non_const_decl->add_method (sm_release ("_manage")); - if (name_map.find (std::make_pair ("new", true)) == name_map.end ()) { - non_const_decl->add_method (sm_default_ctor ("new", &*c), false); - } + if (name_map.find (std::make_pair ("create", false)) == name_map.end ()) { + // deprecate "create" + non_const_decl->add_method (sm_create ("_create|#create")); + } else { + // fallback name is "_create" to avoid conflicts + non_const_decl->add_method (sm_create ("_create")); + } - // Note: "unmanage" and "manage" is a better name ... - non_const_decl->add_method (sm_keep ("_unmanage")); - non_const_decl->add_method (sm_release ("_manage")); - - if (name_map.find (std::make_pair ("create", false)) == name_map.end ()) { - // deprecate "create" - non_const_decl->add_method (sm_create ("_create|#create")); + if (c->can_destroy ()) { + if (name_map.find (std::make_pair ("destroy", false)) == name_map.end ()) { + // deprecate "destroy" + non_const_decl->add_method (sm_destroy ("_destroy|#destroy")); } else { - // fallback name is "_create" to avoid conflicts - non_const_decl->add_method (sm_create ("_create")); + // fallback name is "_destroy" to avoid conflicts + non_const_decl->add_method (sm_destroy ("_destroy")); } + } - if (c->can_destroy ()) { - if (name_map.find (std::make_pair ("destroy", false)) == name_map.end ()) { - // deprecate "destroy" - non_const_decl->add_method (sm_destroy ("_destroy|#destroy")); - } else { - // fallback name is "_destroy" to avoid conflicts - non_const_decl->add_method (sm_destroy ("_destroy")); - } - } + if (c->can_copy ()) { - if (c->can_copy ()) { - - if (name_map.find (std::make_pair ("dup", false)) == name_map.end ()) { - non_const_decl->add_method (sm_dup ("dup", &*c)); - } else { - // fallback name is "_dup" to avoid conflicts - non_const_decl->add_method (sm_dup ("_dup", &*c)); - } - - if (name_map.find (std::make_pair ("assign", false)) == name_map.end ()) { - non_const_decl->add_method (sm_assign ("assign", &*c)); - } else { - // fallback name is "_assign" to avoid conflicts - non_const_decl->add_method (sm_assign ("_assign", &*c)); - } - - } - - if (name_map.find (std::make_pair ("destroyed", false)) == name_map.end ()) { - // deprecate "destroyed" - non_const_decl->add_method (sm_destroyed ("_destroyed?|#destroyed?")); + if (name_map.find (std::make_pair ("dup", false)) == name_map.end ()) { + non_const_decl->add_method (sm_dup ("dup", &*c)); } else { - // fallback name is "_destroyed" to avoid conflicts - non_const_decl->add_method (sm_destroyed ("_destroyed?")); + // fallback name is "_dup" to avoid conflicts + non_const_decl->add_method (sm_dup ("_dup", &*c)); } - if (name_map.find (std::make_pair ("is_const_object", false)) == name_map.end ()) { - // deprecate "is_const" - non_const_decl->add_method (sm_is_const ("_is_const_object?|#is_const_object?")); + if (name_map.find (std::make_pair ("assign", false)) == name_map.end ()) { + non_const_decl->add_method (sm_assign ("assign", &*c)); } else { - // fallback name is "_is_const" to avoid conflicts - non_const_decl->add_method (sm_is_const ("_is_const_object?")); + // fallback name is "_assign" to avoid conflicts + non_const_decl->add_method (sm_assign ("_assign", &*c)); } } + if (name_map.find (std::make_pair ("destroyed", false)) == name_map.end ()) { + // deprecate "destroyed" + non_const_decl->add_method (sm_destroyed ("_destroyed?|#destroyed?")); + } else { + // fallback name is "_destroyed" to avoid conflicts + non_const_decl->add_method (sm_destroyed ("_destroyed?")); + } + + if (name_map.find (std::make_pair ("is_const_object", false)) == name_map.end ()) { + // deprecate "is_const" + non_const_decl->add_method (sm_is_const ("_is_const_object?|#is_const_object?")); + } else { + // fallback name is "_is_const" to avoid conflicts + non_const_decl->add_method (sm_is_const ("_is_const_object?")); + } + } + + // finally merge the new classes into the existing ones + if (! mp_class_collection) { + mp_class_collection = new class_collection (); + } + for (gsi::ClassBase::class_iterator c = gsi::ClassBase::begin_new_classes (); c != gsi::ClassBase::end_new_classes (); ++c) { + gsi::ClassBase *non_const_decl = const_cast (c.operator-> ()); + mp_class_collection->push_back (non_const_decl); + } + mp_new_class_collection->clear (); + } void @@ -536,45 +573,33 @@ bool has_class (const std::string &name) return class_by_name_no_assert (name) != 0; } -namespace +static void add_class_to_map (const gsi::ClassBase *c) { - -struct type_info_compare -{ - bool operator() (const std::type_info *a, const std::type_info *b) const - { - return a->before (*b); + if (c->declaration () != c) { + // only consider non-extensions + return; } -}; + const std::type_info *ti = c->adapted_type_info (); + if (! ti) { + ti = &c->type (); + } + if (ti && c->is_of_type (*ti) && !s_ti_to_class.insert (std::make_pair (ti, c)).second) { + // Duplicate registration of this class + tl::error << "Duplicate registration of class " << c->name () << " (type " << ti->name () << ")"; + tl_assert (false); + } } -// TODO: thread-safe? Unlikely that multiple threads access this member - -// we do a initial scan and after this no more write access here. -static std::map s_ti_to_class; - const ClassBase *class_by_typeinfo_no_assert (const std::type_info &ti) { if (s_ti_to_class.empty ()) { - for (gsi::ClassBase::class_iterator c = gsi::ClassBase::begin_classes (); c != gsi::ClassBase::end_classes (); ++c) { - - if (c->declaration () != c.operator-> ()) { - continue; - } - - const std::type_info *ti = c->adapted_type_info (); - if (! ti) { - ti = &c->type (); - } - if (ti && c->is_of_type (*ti) && !s_ti_to_class.insert (std::make_pair (ti, c.operator-> ())).second) { - // Duplicate registration of this class - tl::error << "Duplicate registration of class " << c->name () << " (type " << ti->name () << ")"; - tl_assert (false); - } - + add_class_to_map (c.operator-> ()); + } + for (gsi::ClassBase::class_iterator c = gsi::ClassBase::begin_new_classes (); c != gsi::ClassBase::end_new_classes (); ++c) { + add_class_to_map (c.operator-> ()); } - } std::map::const_iterator c = s_ti_to_class.find (&ti); diff --git a/src/gsi/gsi/gsiClassBase.h b/src/gsi/gsi/gsiClassBase.h index a1bdb3c90..544475a91 100644 --- a/src/gsi/gsi/gsiClassBase.h +++ b/src/gsi/gsi/gsiClassBase.h @@ -220,6 +220,23 @@ public: return collection ().end (); } + /** + * @brief Iterates all freshly registered classes (begin) + * This collection is emptied on "merge_declarations". + */ + static class_iterator begin_new_classes () + { + return new_collection ().begin (); + } + + /** + * @brief Iterates all freshly registered classes (begin) + */ + static class_iterator end_new_classes () + { + return new_collection ().end (); + } + /** * @brief Iterates the methods (begin) */ @@ -557,6 +574,7 @@ public: protected: static const class_collection &collection (); + static const class_collection &new_collection (); const tl::weak_collection &subclasses () const { @@ -587,7 +605,7 @@ private: mutable std::auto_ptr mp_data[ClientIndex::MaxClientIndex]; static class_collection *mp_class_collection; - static unsigned int m_class_count; + static class_collection *mp_new_class_collection; // No copying ClassBase (const ClassBase &other); diff --git a/src/gsi/gsi/gsiExpression.cc b/src/gsi/gsi/gsiExpression.cc index 616901ced..300376c64 100644 --- a/src/gsi/gsi/gsiExpression.cc +++ b/src/gsi/gsi/gsiExpression.cc @@ -1073,15 +1073,10 @@ private: void GSI_PUBLIC initialize_expressions () { - // Allow duplicate initialization without any effect - static bool s_is_initialized = false; - if (s_is_initialized) { - return; - } - s_is_initialized = true; - + // just in case this did not happen yet ... gsi::initialize (); + // Go through all classes (maybe again) for (gsi::ClassBase::class_iterator c = gsi::ClassBase::begin_classes (); c != gsi::ClassBase::end_classes (); ++c) { // install the method table: diff --git a/src/pya/pya/pya.cc b/src/pya/pya/pya.cc index a6c8dcc07..3da342664 100644 --- a/src/pya/pya/pya.cc +++ b/src/pya/pya/pya.cc @@ -2355,7 +2355,7 @@ PythonModule::python_doc (const gsi::MethodBase *method) } void -PythonModule::make_classes () +PythonModule::make_classes (const char *mod_name) { PyObject *module = mp_module.get (); @@ -2407,6 +2407,11 @@ PythonModule::make_classes () more_classes = false; for (gsi::ClassBase::class_iterator c = gsi::ClassBase::begin_classes (); c != gsi::ClassBase::end_classes (); ++c) { + if (mod_name && c->module () != mod_name) { + // don't handle classes outside this module + continue; + } + if (m_rev_cls_map.find (&*c) != m_rev_cls_map.end ()) { // don't handle classes twice continue; diff --git a/src/pya/pya/pya.h b/src/pya/pya/pya.h index 882e685ad..2561c3339 100644 --- a/src/pya/pya/pya.h +++ b/src/pya/pya/pya.h @@ -124,7 +124,7 @@ public: /** * @brief Creates the classes after init has been called */ - void make_classes (); + void make_classes (const char *mod_name = 0); /** * @brief Gets the GSI class for a Python class diff --git a/src/pymod/db/db.pro b/src/pymod/db/db.pro index c30b09565..3183483be 100644 --- a/src/pymod/db/db.pro +++ b/src/pymod/db/db.pro @@ -10,9 +10,9 @@ SOURCES = \ HEADERS += \ -INCLUDEPATH += $$PYTHONINCLUDE $$TL_INC $$GSI_INC $$DB_INC $$GSI_INC $$PYA_INC -DEPENDPATH += $$PYTHONINCLUDE $$TL_INC $$GSI_INC $$DB_INC $$GSI_INC $$PYA_INC -LIBS += $$PYTHONLIBFILE -L$$LIBDIR -lklayout_tl -lklayout_gsi -lklayout_db -lklayout_gsi -lklayout_pya +INCLUDEPATH += $$PYTHONINCLUDE $$TL_INC $$GSI_INC $$PYA_INC +DEPENDPATH += $$PYTHONINCLUDE $$TL_INC $$GSI_INC $$PYA_INC +LIBS += $$PYTHONLIBFILE -L$$LIBDIR -lklayout_tl -lklayout_gsi -lklayout_db -lklayout_pya # Python is somewhat sloppy and relies on the compiler initializing fields # of strucs to 0: diff --git a/src/pymod/db/dbMain.cc b/src/pymod/db/dbMain.cc index e0afef97f..a63d96da1 100644 --- a/src/pymod/db/dbMain.cc +++ b/src/pymod/db/dbMain.cc @@ -28,11 +28,13 @@ static PyObject *module_init () { gsi::initialize (); + + // required for the tiling processor for example gsi::initialize_expressions (); static pya::PythonModule module; module.init ("klayout.db", "KLayout core module (db)"); - module.make_classes (); + module.make_classes ("db"); return module.module (); } diff --git a/src/pymod/lay/lay.pro b/src/pymod/lay/lay.pro new file mode 100644 index 000000000..7173f42c9 --- /dev/null +++ b/src/pymod/lay/lay.pro @@ -0,0 +1,21 @@ + +LIBDIR = $$OUT_PWD/../.. +DESTDIR = $$LIBDIR/pymod +TARGET = lay + +include($$PWD/../../lib.pri) + +SOURCES = \ + layMain.cc \ + +HEADERS += \ + +INCLUDEPATH += $$PYTHONINCLUDE $$TL_INC $$GSI_INC $$PYA_INC +DEPENDPATH += $$PYTHONINCLUDE $$TL_INC $$GSI_INC $$PYA_INC +LIBS += $$PYTHONLIBFILE -L$$LIBDIR -lklayout_tl -lklayout_db -lklayout_gsi -lklayout_pya -lklayout_lay -lklayout_laybasic + +# Python is somewhat sloppy and relies on the compiler initializing fields +# of strucs to 0: +QMAKE_CXXFLAGS_WARN_ON += \ + -Wno-missing-field-initializers + diff --git a/src/pymod/lay/layMain.cc b/src/pymod/lay/layMain.cc new file mode 100644 index 000000000..4e313ee11 --- /dev/null +++ b/src/pymod/lay/layMain.cc @@ -0,0 +1,56 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2018 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include +#include "pya.h" +#include "gsi.h" +#include "gsiExpression.h" + +static PyObject *module_init () +{ + gsi::initialize (); + + // required for the tiling processor for example + gsi::initialize_expressions (); + + static pya::PythonModule module; + module.init ("klayout.lay", "KLayout core module (lay)"); + module.make_classes ("lay"); + + return module.module (); +} + +#if PY_MAJOR_VERSION < 3 +PyMODINIT_FUNC +DEF_INSIDE_PUBLIC +initlay () +{ + module_init (); +} +#else +PyMODINIT_FUNC +DEF_INSIDE_PUBLIC +PyInit_lay () +{ + return module_init(); +} +#endif diff --git a/src/pymod/pymod.pro b/src/pymod/pymod.pro index d5c55c1c5..a5c87b566 100644 --- a/src/pymod/pymod.pro +++ b/src/pymod/pymod.pro @@ -1,4 +1,7 @@ TEMPLATE = subdirs -SUBDIRS = db +SUBDIRS = \ + db \ + tl \ + lay \ diff --git a/src/pymod/tl/tl.pro b/src/pymod/tl/tl.pro new file mode 100644 index 000000000..1fa6dbbbc --- /dev/null +++ b/src/pymod/tl/tl.pro @@ -0,0 +1,21 @@ + +LIBDIR = $$OUT_PWD/../.. +DESTDIR = $$LIBDIR/pymod +TARGET = tl + +include($$PWD/../../lib.pri) + +SOURCES = \ + tlMain.cc \ + +HEADERS += \ + +INCLUDEPATH += $$PYTHONINCLUDE $$TL_INC $$GSI_INC $$PYA_INC +DEPENDPATH += $$PYTHONINCLUDE $$TL_INC $$GSI_INC $$PYA_INC +LIBS += $$PYTHONLIBFILE -L$$LIBDIR -lklayout_tl -lklayout_gsi -lklayout_pya + +# Python is somewhat sloppy and relies on the compiler initializing fields +# of strucs to 0: +QMAKE_CXXFLAGS_WARN_ON += \ + -Wno-missing-field-initializers + diff --git a/src/pymod/tl/tlMain.cc b/src/pymod/tl/tlMain.cc new file mode 100644 index 000000000..46b1666fa --- /dev/null +++ b/src/pymod/tl/tlMain.cc @@ -0,0 +1,56 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2018 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include +#include "pya.h" +#include "gsi.h" +#include "gsiExpression.h" + +static PyObject *module_init () +{ + gsi::initialize (); + + // required for the tiling processor for example + gsi::initialize_expressions (); + + static pya::PythonModule module; + module.init ("klayout.tl", "KLayout core module (tl)"); + module.make_classes ("tl"); + + return module.module (); +} + +#if PY_MAJOR_VERSION < 3 +PyMODINIT_FUNC +DEF_INSIDE_PUBLIC +inittl () +{ + module_init (); +} +#else +PyMODINIT_FUNC +DEF_INSIDE_PUBLIC +PyInit_tl () +{ + return module_init(); +} +#endif