/****************************************************************************** * * MantaFlow fluid solver framework * Copyright 2011 Tobias Pfaff, Nils Thuerey * * This program is free software, distributed under the terms of the * Apache License, Version 2.0 * http://www.apache.org/licenses/LICENSE-2.0 * * Functions for property setting/getting via python * ******************************************************************************/ #include "pythonInclude.h" #include "structmember.h" #include "manta.h" #include "general.h" #include "timing.h" #ifdef GUI # include #else class QMutex { public: void lock(){}; void unlock(){}; bool tryLock() { return true; }; }; #endif using namespace std; namespace Manta { //****************************************************************************** // Free functions void pbPreparePlugin(FluidSolver *parent, const string &name, bool doTime) { if (doTime) TimingData::instance().start(parent, name); } void pbFinalizePlugin(FluidSolver *parent, const string &name, bool doTime) { if (doTime) TimingData::instance().stop(parent, name); // GUI update, also print name of parent if there's more than one std::ostringstream msg; if (name != "FluidSolver::step") { if (parent && (parent->getNumInstances() > 0)) msg << parent->getName() << string("."); msg << name; } updateQtGui(false, 0, 0., msg.str()); debMsg(name << " done", 3); // name unnamed PbClass Objects from var name PbClass::renameObjects(); } void pbSetError(const string &fn, const string &ex) { debMsg("Error in " << fn, 1); if (!ex.empty()) PyErr_SetString(PyExc_RuntimeError, ex.c_str()); } //****************************************************************************** // Helpers string PbTypeVec::str() const { if (T.empty()) return ""; string s = "<"; for (int i = 0; i < (int)T.size(); i++) { s += T[i].str(); s += (i != (int)T.size() - 1) ? ',' : '>'; } return s; } string PbType::str() const { if (S == "float") return "Real"; if (S == "manta.vec3") return "Vec3"; return S; } //****************************************************************************** // PbClass vector PbClass::mInstances; PbClass::PbClass(FluidSolver *parent, const string &name, PyObject *obj) : mMutex(NULL), mParent(parent), mPyObject(obj), mName(name), mHidden(false) { mMutex = new QMutex(); } PbClass::PbClass(const PbClass &a) : mMutex(NULL), mParent(a.mParent), mPyObject(0), mName("_unnamed"), mHidden(false) { mMutex = new QMutex(); } PbClass::~PbClass() { for (vector::iterator it = mInstances.begin(); it != mInstances.end(); ++it) { if (*it == this) { mInstances.erase(it); break; } } delete mMutex; } void PbClass::lock() { mMutex->lock(); } void PbClass::unlock() { mMutex->unlock(); } bool PbClass::tryLock() { return mMutex->tryLock(); } PbClass *PbClass::getInstance(int idx) { if (idx < 0 || idx > (int)mInstances.size()) errMsg("PbClass::getInstance(): invalid index"); return mInstances[idx]; } int PbClass::getNumInstances() { return mInstances.size(); } bool PbClass::isNullRef(PyObject *obj) { return PyLong_Check(obj) && PyLong_AsDouble(obj) == 0; } bool PbClass::isNoneRef(PyObject *obj) { return (obj == Py_None); } void PbClass::registerObject(PyObject *obj, PbArgs *args) { // cross link Pb::setReference(this, obj); mPyObject = obj; mInstances.push_back(this); if (args) { string _name = args->getOpt("name", -1, ""); if (!_name.empty()) setName(_name); } } PbClass *PbClass::createPyObject(const string &classname, const string &name, PbArgs &args, PbClass *parent) { return Pb::createPy(classname, name, args, parent); } void PbClass::checkParent() { if (getParent() == NULL) { errMsg("New class " + mName + ": no parent given -- specify using parent=xxx !"); } } //! Assign unnamed PbClass objects their Python variable name void PbClass::renameObjects() { PyObject *sys_mod_dict = PyImport_GetModuleDict(); PyObject *loc_mod = PyMapping_GetItemString(sys_mod_dict, (char *)"__main__"); if (!loc_mod) return; PyObject *locdict = PyObject_GetAttrString(loc_mod, "__dict__"); if (!locdict) return; // iterate all PbClass instances for (size_t i = 0; i < mInstances.size(); i++) { PbClass *obj = mInstances[i]; if (obj->getName().empty()) { // empty, try to find instance in module local dictionary PyObject *lkey, *lvalue; Py_ssize_t lpos = 0; while (PyDict_Next(locdict, &lpos, &lkey, &lvalue)) { if (lvalue == obj->mPyObject) { string varName = fromPy(PyObject_Str(lkey)); obj->setName(varName); // cout << "assigning variable name '" << varName << "' to unnamed instance" << endl; break; } } } } Py_DECREF(locdict); Py_DECREF(loc_mod); } } // namespace Manta