662 lines
17 KiB
C++
662 lines
17 KiB
C++
/******************************************************************************
|
|
*
|
|
* 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
|
|
*
|
|
******************************************************************************/
|
|
|
|
#include "pythonInclude.h"
|
|
#include <sstream>
|
|
#include <algorithm>
|
|
#include "vectorbase.h"
|
|
#include "manta.h"
|
|
|
|
using namespace std;
|
|
|
|
//******************************************************************************
|
|
// Explicit definition and instantiation of python object converters
|
|
|
|
namespace Manta {
|
|
|
|
extern PyTypeObject PbVec3Type;
|
|
extern PyTypeObject PbVec4Type;
|
|
|
|
struct PbVec3 {
|
|
PyObject_HEAD float data[3];
|
|
};
|
|
|
|
struct PbVec4 {
|
|
PyObject_HEAD float data[4];
|
|
};
|
|
|
|
PyObject *getPyNone()
|
|
{
|
|
Py_INCREF(Py_None);
|
|
return Py_None;
|
|
}
|
|
PyObject *incref(PyObject *obj)
|
|
{
|
|
Py_INCREF(obj);
|
|
return obj;
|
|
}
|
|
|
|
/*template<> PyObject* toPy<PyObject*>(PyObject* obj) {
|
|
return obj;
|
|
}*/
|
|
template<> PyObject *toPy<int>(const int &v)
|
|
{
|
|
return PyLong_FromLong(v);
|
|
}
|
|
/*template<> PyObject* toPy<char*>(const (char*) & val) {
|
|
return PyUnicode_DecodeLatin1(val,strlen(val),"replace");
|
|
}*/
|
|
template<> PyObject *toPy<string>(const string &val)
|
|
{
|
|
return PyUnicode_DecodeLatin1(val.c_str(), val.length(), "replace");
|
|
}
|
|
template<> PyObject *toPy<float>(const float &v)
|
|
{
|
|
return PyFloat_FromDouble(v);
|
|
}
|
|
template<> PyObject *toPy<double>(const double &v)
|
|
{
|
|
return PyFloat_FromDouble(v);
|
|
}
|
|
template<> PyObject *toPy<bool>(const bool &v)
|
|
{
|
|
return PyBool_FromLong(v);
|
|
}
|
|
template<> PyObject *toPy<Vec3i>(const Vec3i &v)
|
|
{
|
|
float x = (float)v.x, y = (float)v.y, z = (float)v.z;
|
|
return PyObject_CallFunction((PyObject *)&PbVec3Type, (char *)"fff", x, y, z);
|
|
}
|
|
template<> PyObject *toPy<Vec3>(const Vec3 &v)
|
|
{
|
|
float x = (float)v.x, y = (float)v.y, z = (float)v.z;
|
|
return PyObject_CallFunction((PyObject *)&PbVec3Type, (char *)"fff", x, y, z);
|
|
}
|
|
template<> PyObject *toPy<Vec4i>(const Vec4i &v)
|
|
{
|
|
float x = (float)v.x, y = (float)v.y, z = (float)v.z;
|
|
return PyObject_CallFunction((PyObject *)&PbVec4Type, (char *)"ffff", x, y, z);
|
|
}
|
|
template<> PyObject *toPy<Vec4>(const Vec4 &v)
|
|
{
|
|
float x = (float)v.x, y = (float)v.y, z = (float)v.z;
|
|
return PyObject_CallFunction((PyObject *)&PbVec4Type, (char *)"ffff", x, y, z);
|
|
}
|
|
template<> PyObject *toPy<PbClass *>(const PbClass_Ptr &obj)
|
|
{
|
|
return obj->getPyObject();
|
|
}
|
|
template<> PyObject *toPy<std::vector<PbClass *>>(const std::vector<PbClass *> &vec)
|
|
{
|
|
PyObject *listObj = PyList_New(vec.size());
|
|
if (!listObj)
|
|
throw logic_error("Unable to allocate memory for Python list");
|
|
for (unsigned int i = 0; i < vec.size(); i++) {
|
|
PbClass *pb = vec[i];
|
|
PyObject *item = pb->getPyObject();
|
|
if (!item) {
|
|
Py_DECREF(listObj);
|
|
throw logic_error("Unable to allocate memory for Python list");
|
|
}
|
|
PyList_SET_ITEM(listObj, i, item);
|
|
}
|
|
return listObj;
|
|
}
|
|
template<> PyObject *toPy<std::vector<float>>(const std::vector<float> &vec)
|
|
{
|
|
PyObject *listObj = PyList_New(vec.size());
|
|
if (!listObj)
|
|
throw logic_error("Unable to allocate memory for Python list");
|
|
for (unsigned int i = 0; i < vec.size(); i++) {
|
|
PyObject *item = toPy<float>(vec[i]);
|
|
if (!item) {
|
|
Py_DECREF(listObj);
|
|
throw logic_error("Unable to allocate memory for Python list");
|
|
}
|
|
PyList_SET_ITEM(listObj, i, item);
|
|
}
|
|
return listObj;
|
|
}
|
|
|
|
template<> float fromPy<float>(PyObject *obj)
|
|
{
|
|
#if PY_MAJOR_VERSION <= 2
|
|
if (PyInt_Check(obj))
|
|
return PyInt_AsLong(obj);
|
|
#endif
|
|
if (PyFloat_Check(obj))
|
|
return PyFloat_AsDouble(obj);
|
|
if (PyLong_Check(obj))
|
|
return PyLong_AsDouble(obj);
|
|
errMsg("argument is not a float");
|
|
}
|
|
template<> double fromPy<double>(PyObject *obj)
|
|
{
|
|
#if PY_MAJOR_VERSION <= 2
|
|
if (PyInt_Check(obj))
|
|
return PyInt_AsLong(obj);
|
|
#endif
|
|
if (PyFloat_Check(obj))
|
|
return PyFloat_AsDouble(obj);
|
|
if (PyLong_Check(obj))
|
|
return PyLong_AsDouble(obj);
|
|
errMsg("argument is not a double");
|
|
}
|
|
template<> PyObject *fromPy<PyObject *>(PyObject *obj)
|
|
{
|
|
return obj;
|
|
}
|
|
template<> PbClass *fromPy<PbClass *>(PyObject *obj)
|
|
{
|
|
PbClass *pbo = Pb::objFromPy(obj);
|
|
|
|
if (!PyType_Check(obj))
|
|
return pbo;
|
|
|
|
const char *tname = ((PyTypeObject *)obj)->tp_name;
|
|
pbo->setName(tname);
|
|
|
|
return pbo;
|
|
}
|
|
template<> std::vector<PbClass *> fromPy<std::vector<PbClass *>>(PyObject *obj)
|
|
{
|
|
std::vector<PbClass *> vec;
|
|
if (PyList_Check(obj)) {
|
|
int sz = PyList_Size(obj);
|
|
for (int i = 0; i < sz; ++i) {
|
|
PyObject *lobj = PyList_GetItem(obj, i);
|
|
vec.push_back(fromPy<PbClass *>(lobj));
|
|
}
|
|
}
|
|
return vec;
|
|
}
|
|
template<> std::vector<float> fromPy<std::vector<float>>(PyObject *obj)
|
|
{
|
|
std::vector<float> vec;
|
|
if (PyList_Check(obj)) {
|
|
int sz = PyList_Size(obj);
|
|
for (int i = 0; i < sz; ++i) {
|
|
PyObject *lobj = PyList_GetItem(obj, i);
|
|
vec.push_back(fromPy<float>(lobj));
|
|
}
|
|
}
|
|
return vec;
|
|
}
|
|
template<> int fromPy<int>(PyObject *obj)
|
|
{
|
|
#if PY_MAJOR_VERSION <= 2
|
|
if (PyInt_Check(obj))
|
|
return PyInt_AsLong(obj);
|
|
#endif
|
|
if (PyLong_Check(obj))
|
|
return PyLong_AsDouble(obj);
|
|
if (PyFloat_Check(obj)) {
|
|
double a = PyFloat_AsDouble(obj);
|
|
if (fabs(a - floor(a + 0.5)) > 1e-5)
|
|
errMsg("argument is not an int");
|
|
return (int)(a + 0.5);
|
|
}
|
|
errMsg("argument is not an int");
|
|
}
|
|
template<> string fromPy<string>(PyObject *obj)
|
|
{
|
|
if (PyUnicode_Check(obj))
|
|
#ifdef BLENDER
|
|
// Blender is completely UTF-8 based
|
|
return PyBytes_AsString(PyUnicode_AsUTF8String(obj));
|
|
#else
|
|
return PyBytes_AsString(PyUnicode_AsLatin1String(obj));
|
|
#endif
|
|
#if PY_MAJOR_VERSION <= 2
|
|
else if (PyString_Check(obj))
|
|
return PyString_AsString(obj);
|
|
#endif
|
|
else
|
|
errMsg("argument is not a string");
|
|
}
|
|
template<> const char *fromPy<const char *>(PyObject *obj)
|
|
{
|
|
if (PyUnicode_Check(obj))
|
|
#ifdef BLENDER
|
|
// Blender is completely UTF-8 based
|
|
return PyBytes_AsString(PyUnicode_AsUTF8String(obj));
|
|
#else
|
|
return PyBytes_AsString(PyUnicode_AsLatin1String(obj));
|
|
#endif
|
|
#if PY_MAJOR_VERSION <= 2
|
|
else if (PyString_Check(obj))
|
|
return PyString_AsString(obj);
|
|
#endif
|
|
else
|
|
errMsg("argument is not a string");
|
|
}
|
|
template<> bool fromPy<bool>(PyObject *obj)
|
|
{
|
|
if (!PyBool_Check(obj))
|
|
errMsg("argument is not a boolean");
|
|
return PyLong_AsLong(obj) != 0;
|
|
}
|
|
template<> Vec3 fromPy<Vec3>(PyObject *obj)
|
|
{
|
|
if (PyObject_IsInstance(obj, (PyObject *)&PbVec3Type)) {
|
|
return Vec3(((PbVec3 *)obj)->data);
|
|
}
|
|
else if (PyTuple_Check(obj) && PyTuple_Size(obj) == 3) {
|
|
return Vec3(fromPy<Real>(PyTuple_GetItem(obj, 0)),
|
|
fromPy<Real>(PyTuple_GetItem(obj, 1)),
|
|
fromPy<Real>(PyTuple_GetItem(obj, 2)));
|
|
}
|
|
errMsg("argument is not a Vec3");
|
|
}
|
|
template<> Vec3i fromPy<Vec3i>(PyObject *obj)
|
|
{
|
|
if (PyObject_IsInstance(obj, (PyObject *)&PbVec3Type)) {
|
|
return toVec3iChecked(((PbVec3 *)obj)->data);
|
|
}
|
|
else if (PyTuple_Check(obj) && PyTuple_Size(obj) == 3) {
|
|
return Vec3i(fromPy<int>(PyTuple_GetItem(obj, 0)),
|
|
fromPy<int>(PyTuple_GetItem(obj, 1)),
|
|
fromPy<int>(PyTuple_GetItem(obj, 2)));
|
|
}
|
|
errMsg("argument is not a Vec3i");
|
|
}
|
|
template<> Vec4 fromPy<Vec4>(PyObject *obj)
|
|
{
|
|
if (PyObject_IsInstance(obj, (PyObject *)&PbVec4Type)) {
|
|
return Vec4(((PbVec4 *)obj)->data);
|
|
}
|
|
else if (PyTuple_Check(obj) && PyTuple_Size(obj) == 4) {
|
|
return Vec4(fromPy<Real>(PyTuple_GetItem(obj, 0)),
|
|
fromPy<Real>(PyTuple_GetItem(obj, 1)),
|
|
fromPy<Real>(PyTuple_GetItem(obj, 2)),
|
|
fromPy<Real>(PyTuple_GetItem(obj, 3)));
|
|
}
|
|
errMsg("argument is not a Vec4");
|
|
}
|
|
template<> Vec4i fromPy<Vec4i>(PyObject *obj)
|
|
{
|
|
if (PyObject_IsInstance(obj, (PyObject *)&PbVec4Type)) {
|
|
return toVec4i(((PbVec4 *)obj)->data);
|
|
}
|
|
else if (PyTuple_Check(obj) && PyTuple_Size(obj) == 4) {
|
|
return Vec4i(fromPy<int>(PyTuple_GetItem(obj, 0)),
|
|
fromPy<int>(PyTuple_GetItem(obj, 1)),
|
|
fromPy<int>(PyTuple_GetItem(obj, 2)),
|
|
fromPy<int>(PyTuple_GetItem(obj, 3)));
|
|
}
|
|
errMsg("argument is not a Vec4i");
|
|
}
|
|
template<> PbType fromPy<PbType>(PyObject *obj)
|
|
{
|
|
PbType pb = {""};
|
|
if (!PyType_Check(obj))
|
|
return pb;
|
|
|
|
const char *tname = ((PyTypeObject *)obj)->tp_name;
|
|
pb.S = tname;
|
|
return pb;
|
|
}
|
|
template<> PbTypeVec fromPy<PbTypeVec>(PyObject *obj)
|
|
{
|
|
PbTypeVec vec;
|
|
if (PyType_Check(obj)) {
|
|
vec.T.push_back(fromPy<PbType>(obj));
|
|
}
|
|
else if (PyTuple_Check(obj)) {
|
|
int sz = PyTuple_Size(obj);
|
|
for (int i = 0; i < sz; i++)
|
|
vec.T.push_back(fromPy<PbType>(PyTuple_GetItem(obj, i)));
|
|
}
|
|
else
|
|
errMsg("argument is not a type tuple");
|
|
return vec;
|
|
}
|
|
|
|
template<class T> T *tmpAlloc(PyObject *obj, std::vector<void *> *tmp)
|
|
{
|
|
if (!tmp)
|
|
throw Error("dynamic de-ref not supported for this type");
|
|
|
|
T *ptr = new T(fromPy<T>(obj));
|
|
tmp->push_back(ptr);
|
|
return ptr;
|
|
}
|
|
template<> float *fromPyPtr<float>(PyObject *obj, std::vector<void *> *tmp)
|
|
{
|
|
return tmpAlloc<float>(obj, tmp);
|
|
}
|
|
template<> double *fromPyPtr<double>(PyObject *obj, std::vector<void *> *tmp)
|
|
{
|
|
return tmpAlloc<double>(obj, tmp);
|
|
}
|
|
template<> int *fromPyPtr<int>(PyObject *obj, std::vector<void *> *tmp)
|
|
{
|
|
return tmpAlloc<int>(obj, tmp);
|
|
}
|
|
template<> std::string *fromPyPtr<std::string>(PyObject *obj, std::vector<void *> *tmp)
|
|
{
|
|
return tmpAlloc<std::string>(obj, tmp);
|
|
}
|
|
template<> bool *fromPyPtr<bool>(PyObject *obj, std::vector<void *> *tmp)
|
|
{
|
|
return tmpAlloc<bool>(obj, tmp);
|
|
}
|
|
template<> Vec3 *fromPyPtr<Vec3>(PyObject *obj, std::vector<void *> *tmp)
|
|
{
|
|
return tmpAlloc<Vec3>(obj, tmp);
|
|
}
|
|
template<> Vec3i *fromPyPtr<Vec3i>(PyObject *obj, std::vector<void *> *tmp)
|
|
{
|
|
return tmpAlloc<Vec3i>(obj, tmp);
|
|
}
|
|
template<> Vec4 *fromPyPtr<Vec4>(PyObject *obj, std::vector<void *> *tmp)
|
|
{
|
|
return tmpAlloc<Vec4>(obj, tmp);
|
|
}
|
|
template<> Vec4i *fromPyPtr<Vec4i>(PyObject *obj, std::vector<void *> *tmp)
|
|
{
|
|
return tmpAlloc<Vec4i>(obj, tmp);
|
|
}
|
|
template<>
|
|
std::vector<PbClass *> *fromPyPtr<std::vector<PbClass *>>(PyObject *obj, std::vector<void *> *tmp)
|
|
{
|
|
return tmpAlloc<std::vector<PbClass *>>(obj, tmp);
|
|
}
|
|
|
|
template<> bool isPy<float>(PyObject *obj)
|
|
{
|
|
#if PY_MAJOR_VERSION <= 2
|
|
if (PyInt_Check(obj))
|
|
return true;
|
|
#endif
|
|
return PyFloat_Check(obj) || PyLong_Check(obj);
|
|
}
|
|
template<> bool isPy<double>(PyObject *obj)
|
|
{
|
|
#if PY_MAJOR_VERSION <= 2
|
|
if (PyInt_Check(obj))
|
|
return true;
|
|
#endif
|
|
return PyFloat_Check(obj) || PyLong_Check(obj);
|
|
}
|
|
template<> bool isPy<PyObject *>(PyObject *obj)
|
|
{
|
|
return true;
|
|
}
|
|
template<> bool isPy<int>(PyObject *obj)
|
|
{
|
|
#if PY_MAJOR_VERSION <= 2
|
|
if (PyInt_Check(obj))
|
|
return true;
|
|
#endif
|
|
if (PyLong_Check(obj))
|
|
return true;
|
|
if (PyFloat_Check(obj)) {
|
|
double a = PyFloat_AsDouble(obj);
|
|
return fabs(a - floor(a + 0.5)) < 1e-5;
|
|
}
|
|
return false;
|
|
}
|
|
template<> bool isPy<string>(PyObject *obj)
|
|
{
|
|
if (PyUnicode_Check(obj))
|
|
return true;
|
|
#if PY_MAJOR_VERSION <= 2
|
|
if (PyString_Check(obj))
|
|
return true;
|
|
#endif
|
|
return false;
|
|
}
|
|
template<> bool isPy<const char *>(PyObject *obj)
|
|
{
|
|
if (PyUnicode_Check(obj))
|
|
return true;
|
|
#if PY_MAJOR_VERSION <= 2
|
|
if (PyString_Check(obj))
|
|
return true;
|
|
#endif
|
|
return false;
|
|
}
|
|
template<> bool isPy<bool>(PyObject *obj)
|
|
{
|
|
return PyBool_Check(obj);
|
|
}
|
|
template<> bool isPy<Vec3>(PyObject *obj)
|
|
{
|
|
if (PyObject_IsInstance(obj, (PyObject *)&PbVec3Type))
|
|
return true;
|
|
if (PyTuple_Check(obj) && PyTuple_Size(obj) == 3) {
|
|
return isPy<Real>(PyTuple_GetItem(obj, 0)) && isPy<Real>(PyTuple_GetItem(obj, 1)) &&
|
|
isPy<Real>(PyTuple_GetItem(obj, 2));
|
|
}
|
|
return false;
|
|
}
|
|
template<> bool isPy<Vec3i>(PyObject *obj)
|
|
{
|
|
if (PyObject_IsInstance(obj, (PyObject *)&PbVec3Type))
|
|
return true;
|
|
if (PyTuple_Check(obj) && PyTuple_Size(obj) == 3) {
|
|
return isPy<int>(PyTuple_GetItem(obj, 0)) && isPy<int>(PyTuple_GetItem(obj, 1)) &&
|
|
isPy<int>(PyTuple_GetItem(obj, 2));
|
|
}
|
|
return false;
|
|
}
|
|
template<> bool isPy<Vec4>(PyObject *obj)
|
|
{
|
|
if (PyObject_IsInstance(obj, (PyObject *)&PbVec4Type))
|
|
return true;
|
|
if (PyTuple_Check(obj) && PyTuple_Size(obj) == 4) {
|
|
return isPy<Real>(PyTuple_GetItem(obj, 0)) && isPy<Real>(PyTuple_GetItem(obj, 1)) &&
|
|
isPy<Real>(PyTuple_GetItem(obj, 2)) && isPy<Real>(PyTuple_GetItem(obj, 3));
|
|
}
|
|
return false;
|
|
}
|
|
template<> bool isPy<Vec4i>(PyObject *obj)
|
|
{
|
|
if (PyObject_IsInstance(obj, (PyObject *)&PbVec4Type))
|
|
return true;
|
|
if (PyTuple_Check(obj) && PyTuple_Size(obj) == 4) {
|
|
return isPy<int>(PyTuple_GetItem(obj, 0)) && isPy<int>(PyTuple_GetItem(obj, 1)) &&
|
|
isPy<int>(PyTuple_GetItem(obj, 2)) && isPy<int>(PyTuple_GetItem(obj, 3));
|
|
}
|
|
return false;
|
|
}
|
|
template<> bool isPy<PbType>(PyObject *obj)
|
|
{
|
|
return PyType_Check(obj);
|
|
}
|
|
template<> bool isPy<std::vector<PbClass *>>(PyObject *obj)
|
|
{
|
|
if (PyList_Check(obj))
|
|
return true;
|
|
return false;
|
|
}
|
|
template<> bool isPy<std::vector<float>>(PyObject *obj)
|
|
{
|
|
if (PyList_Check(obj))
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
//******************************************************************************
|
|
// PbArgs class defs
|
|
|
|
PbArgs PbArgs::EMPTY(nullptr, nullptr);
|
|
|
|
PbArgs::PbArgs(PyObject *linarg, PyObject *dict) : mLinArgs(0), mKwds(0)
|
|
{
|
|
setup(linarg, dict);
|
|
}
|
|
PbArgs::~PbArgs()
|
|
{
|
|
for (int i = 0; i < (int)mTmpStorage.size(); i++)
|
|
operator delete(mTmpStorage[i]);
|
|
mTmpStorage.clear();
|
|
}
|
|
|
|
void PbArgs::copy(PbArgs &a)
|
|
{
|
|
mKwds = a.mKwds;
|
|
mData = a.mData;
|
|
mLinData = a.mLinData;
|
|
mLinArgs = a.mLinArgs;
|
|
}
|
|
void PbArgs::clear()
|
|
{
|
|
mLinArgs = 0;
|
|
mKwds = 0;
|
|
mData.clear();
|
|
mLinData.clear();
|
|
}
|
|
|
|
PbArgs &PbArgs::operator=(const PbArgs &a)
|
|
{
|
|
// mLinArgs = 0;
|
|
// mKwds = 0;
|
|
return *this;
|
|
}
|
|
|
|
void PbArgs::setup(PyObject *linarg, PyObject *dict)
|
|
{
|
|
if (dict) {
|
|
PyObject *key, *value;
|
|
Py_ssize_t pos = 0;
|
|
while (PyDict_Next(dict, &pos, &key, &value)) {
|
|
DataElement el;
|
|
el.obj = value;
|
|
el.visited = false;
|
|
mData[fromPy<string>(key)] = el;
|
|
}
|
|
mKwds = dict;
|
|
}
|
|
if (linarg) {
|
|
size_t len = PyTuple_Size(linarg);
|
|
for (size_t i = 0; i < len; i++) {
|
|
DataElement el;
|
|
el.obj = PyTuple_GetItem(linarg, i);
|
|
el.visited = false;
|
|
mLinData.push_back(el);
|
|
}
|
|
mLinArgs = linarg;
|
|
}
|
|
}
|
|
|
|
void PbArgs::addLinArg(PyObject *obj)
|
|
{
|
|
DataElement el = {obj, false};
|
|
mLinData.push_back(el);
|
|
}
|
|
|
|
void PbArgs::check()
|
|
{
|
|
if (has("nocheck"))
|
|
return;
|
|
|
|
for (map<string, DataElement>::iterator it = mData.begin(); it != mData.end(); it++) {
|
|
if (!it->second.visited)
|
|
errMsg("Argument '" + it->first + "' unknown");
|
|
}
|
|
for (size_t i = 0; i < mLinData.size(); i++) {
|
|
if (!mLinData[i].visited) {
|
|
stringstream s;
|
|
s << "Function does not read argument number #" << i;
|
|
errMsg(s.str());
|
|
}
|
|
}
|
|
}
|
|
|
|
FluidSolver *PbArgs::obtainParent()
|
|
{
|
|
FluidSolver *solver = getPtrOpt<FluidSolver>("solver", -1, nullptr);
|
|
if (solver != 0)
|
|
return solver;
|
|
|
|
for (map<string, DataElement>::iterator it = mData.begin(); it != mData.end(); it++) {
|
|
PbClass *obj = Pb::objFromPy(it->second.obj);
|
|
|
|
if (obj) {
|
|
if (solver == nullptr)
|
|
solver = obj->getParent();
|
|
}
|
|
}
|
|
for (vector<DataElement>::iterator it = mLinData.begin(); it != mLinData.end(); it++) {
|
|
PbClass *obj = Pb::objFromPy(it->obj);
|
|
|
|
if (obj) {
|
|
if (solver == nullptr)
|
|
solver = obj->getParent();
|
|
}
|
|
}
|
|
|
|
return solver;
|
|
}
|
|
|
|
void PbArgs::visit(int number, const string &key)
|
|
{
|
|
if (number >= 0 && number < (int)mLinData.size())
|
|
mLinData[number].visited = true;
|
|
map<string, DataElement>::iterator lu = mData.find(key);
|
|
if (lu != mData.end())
|
|
lu->second.visited = true;
|
|
}
|
|
|
|
PyObject *PbArgs::getItem(const std::string &key, bool strict, ArgLocker *lk)
|
|
{
|
|
map<string, DataElement>::iterator lu = mData.find(key);
|
|
if (lu == mData.end()) {
|
|
if (strict)
|
|
errMsg("Argument '" + key + "' is not defined.");
|
|
return nullptr;
|
|
}
|
|
PbClass *pbo = Pb::objFromPy(lu->second.obj);
|
|
// try to lock
|
|
if (pbo && lk)
|
|
lk->add(pbo);
|
|
return lu->second.obj;
|
|
}
|
|
|
|
PyObject *PbArgs::getItem(size_t number, bool strict, ArgLocker *lk)
|
|
{
|
|
if (number >= mLinData.size()) {
|
|
if (!strict)
|
|
return nullptr;
|
|
stringstream s;
|
|
s << "Argument number #" << number << " not specified.";
|
|
errMsg(s.str());
|
|
}
|
|
PbClass *pbo = Pb::objFromPy(mLinData[number].obj);
|
|
// try to lock
|
|
if (pbo && lk)
|
|
lk->add(pbo);
|
|
return mLinData[number].obj;
|
|
}
|
|
|
|
//******************************************************************************
|
|
// ArgLocker class defs
|
|
|
|
void ArgLocker::add(PbClass *p)
|
|
{
|
|
if (find(locks.begin(), locks.end(), p) == locks.end()) {
|
|
locks.push_back(p);
|
|
p->lock();
|
|
}
|
|
}
|
|
ArgLocker::~ArgLocker()
|
|
{
|
|
for (size_t i = 0; i < locks.size(); i++)
|
|
locks[i]->unlock();
|
|
locks.clear();
|
|
}
|
|
|
|
} // namespace Manta
|