/****************************************************************************** * * 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 * * Python argument wrappers and conversion tools * ******************************************************************************/ // ----------------------------------------------------------------- // NOTE: // Do not include this file in user code, include "manta.h" instead // ----------------------------------------------------------------- #ifdef _MANTA_H # ifndef _PCONVERT_H # define _PCONVERT_H # include # include # include namespace Manta { template class Grid; //! Locks the given PbClass Arguments until ArgLocker goes out of scope struct ArgLocker { void add(PbClass *p); ~ArgLocker(); std::vector locks; }; PyObject *getPyNone(); // for PbClass-derived classes template T *fromPyPtr(PyObject *obj, std::vector *tmp) { if (PbClass::isNullRef(obj) || PbClass::isNoneRef(obj)) return 0; PbClass *pbo = Pb::objFromPy(obj); const std::string &type = Namify::S; if (!pbo || !(pbo->canConvertTo(type))) throw Error("can't convert argument to " + type + "*"); return (T *)(pbo); } template<> float *fromPyPtr(PyObject *obj, std::vector *tmp); template<> double *fromPyPtr(PyObject *obj, std::vector *tmp); template<> int *fromPyPtr(PyObject *obj, std::vector *tmp); template<> std::string *fromPyPtr(PyObject *obj, std::vector *tmp); template<> bool *fromPyPtr(PyObject *obj, std::vector *tmp); template<> Vec3 *fromPyPtr(PyObject *obj, std::vector *tmp); template<> Vec3i *fromPyPtr(PyObject *obj, std::vector *tmp); template<> Vec4 *fromPyPtr(PyObject *obj, std::vector *tmp); template<> Vec4i *fromPyPtr(PyObject *obj, std::vector *tmp); template<> std::vector *fromPyPtr>(PyObject *obj, std::vector *tmp); template<> std::vector *fromPyPtr>(PyObject *obj, std::vector *tmp); PyObject *incref(PyObject *obj); template PyObject *toPy(const T &v) { PyObject *obj = v.getPyObject(); if (obj) { return incref(obj); } T *co = new T(v); const std::string &type = Namify::type>::S; return Pb::copyObject(co, type); } template bool isPy(PyObject *obj) { if (PbClass::isNullRef(obj) || PbClass::isNoneRef(obj)) return false; PbClass *pbo = Pb::objFromPy(obj); const std::string &type = Namify::type>::S; return pbo && pbo->canConvertTo(type); } template T fromPy(PyObject *obj) { throw Error( "Unknown type conversion. Did you pass a PbClass by value? Instead always pass " "grids/particlesystems/etc. by reference or using a pointer."); } // builtin types template<> float fromPy(PyObject *obj); template<> double fromPy(PyObject *obj); template<> int fromPy(PyObject *obj); template<> PyObject *fromPy(PyObject *obj); template<> std::string fromPy(PyObject *obj); template<> const char *fromPy(PyObject *obj); template<> bool fromPy(PyObject *obj); template<> Vec3 fromPy(PyObject *obj); template<> Vec3i fromPy(PyObject *obj); template<> Vec4 fromPy(PyObject *obj); template<> Vec4i fromPy(PyObject *obj); template<> PbType fromPy(PyObject *obj); template<> PbTypeVec fromPy(PyObject *obj); template<> PbClass *fromPy(PyObject *obj); template<> std::vector fromPy>(PyObject *obj); template<> std::vector fromPy>(PyObject *obj); template<> PyObject *toPy(const int &v); template<> PyObject *toPy(const std::string &val); template<> PyObject *toPy(const float &v); template<> PyObject *toPy(const double &v); template<> PyObject *toPy(const bool &v); template<> PyObject *toPy(const Vec3i &v); template<> PyObject *toPy(const Vec3 &v); template<> PyObject *toPy(const Vec4i &v); template<> PyObject *toPy(const Vec4 &v); typedef PbClass *PbClass_Ptr; template<> PyObject *toPy(const PbClass_Ptr &obj); template<> PyObject *toPy>(const std::vector &vec); template<> PyObject *toPy>(const std::vector &vec); template<> bool isPy(PyObject *obj); template<> bool isPy(PyObject *obj); template<> bool isPy(PyObject *obj); template<> bool isPy(PyObject *obj); template<> bool isPy(PyObject *obj); template<> bool isPy(PyObject *obj); template<> bool isPy(PyObject *obj); template<> bool isPy(PyObject *obj); template<> bool isPy(PyObject *obj); template<> bool isPy(PyObject *obj); template<> bool isPy(PyObject *obj); template<> bool isPy(PyObject *obj); template<> bool isPy>(PyObject *obj); template<> bool isPy>(PyObject *obj); //! Encapsulation of python arguments class PbArgs { public: PbArgs(PyObject *linargs = NULL, PyObject *dict = NULL); ~PbArgs(); void setup(PyObject *linargs = NULL, PyObject *dict = NULL); void check(); FluidSolver *obtainParent(); inline int numLinArgs() { return mLinData.size(); } inline bool has(const std::string &key) { return getItem(key, false) != NULL; } inline void deleteItem(const std::string &key) { if (mData.find(key) != mData.end()) mData.erase(mData.find(key)); } inline PyObject *linArgs() { return mLinArgs; } inline PyObject *kwds() { return mKwds; } void addLinArg(PyObject *obj); template inline void add(const std::string &key, T arg) { DataElement el = {toPy(arg), false}; mData[key] = el; } template inline T get(const std::string &key, int number = -1, ArgLocker *lk = NULL) { visit(number, key); PyObject *o = getItem(key, false, lk); if (o) return fromPy(o); o = getItem(number, false, lk); if (o) return fromPy(o); errMsg("Argument '" + key + "' is not defined."); } template inline T getOpt(const std::string &key, int number, T defarg, ArgLocker *lk = NULL) { visit(number, key); PyObject *o = getItem(key, false, lk); if (o) return fromPy(o); if (number >= 0) o = getItem(number, false, lk); return (o) ? fromPy(o) : defarg; } template inline T *getPtrOpt(const std::string &key, int number, T *defarg, ArgLocker *lk = NULL) { visit(number, key); PyObject *o = getItem(key, false, lk); if (o) return fromPyPtr(o, &mTmpStorage); if (number >= 0) o = getItem(number, false, lk); return o ? fromPyPtr(o, &mTmpStorage) : defarg; } template inline T *getPtr(const std::string &key, int number = -1, ArgLocker *lk = NULL) { visit(number, key); PyObject *o = getItem(key, false, lk); if (o) return fromPyPtr(o, &mTmpStorage); o = getItem(number, false, lk); if (o) return fromPyPtr(o, &mTmpStorage); errMsg("Argument '" + key + "' is not defined."); } // automatic template type deduction template bool typeCheck(int num, const std::string &name) { PyObject *o = getItem(name, false, 0); if (!o) o = getItem(num, false, 0); return o ? isPy::type>(o) : false; } PbArgs &operator=(const PbArgs &a); // dummy void copy(PbArgs &a); void clear(); void visit(int num, const std::string &key); static PbArgs EMPTY; protected: PyObject *getItem(const std::string &key, bool strict, ArgLocker *lk = NULL); PyObject *getItem(size_t number, bool strict, ArgLocker *lk = NULL); struct DataElement { PyObject *obj; bool visited; }; std::map mData; std::vector mLinData; PyObject *mLinArgs, *mKwds; std::vector mTmpStorage; }; } // namespace Manta # if NUMPY == 1 # include "numpyWrap.h" # endif # endif #endif