Add Chromium-only Blender WebEngine parity work
This commit is contained in:
31
blender-5.2.0/extern/mantaflow/helper/pwrapper/manta.h
vendored
Normal file
31
blender-5.2.0/extern/mantaflow/helper/pwrapper/manta.h
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* MantaFlow fluid solver framework
|
||||
* Copyright 2011-2014 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
|
||||
*
|
||||
* Include pwrapper headers
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef _MANTA_H
|
||||
#define _MANTA_H
|
||||
|
||||
// Remove preprocessor keywords, so there won't infere with autocompletion etc.
|
||||
#define KERNEL(...) extern int i, j, k, idx, X, Y, Z;
|
||||
#define PYTHON(...)
|
||||
#define returns(X) extern X;
|
||||
#define alias typedef
|
||||
|
||||
#include "general.h"
|
||||
#include "vectorbase.h"
|
||||
#include "vector4d.h"
|
||||
#include "registry.h"
|
||||
#include "pclass.h"
|
||||
#include "pconvert.h"
|
||||
#include "fluidsolver.h"
|
||||
|
||||
#endif
|
||||
132
blender-5.2.0/extern/mantaflow/helper/pwrapper/numpyWrap.cpp
vendored
Normal file
132
blender-5.2.0/extern/mantaflow/helper/pwrapper/numpyWrap.cpp
vendored
Normal file
@@ -0,0 +1,132 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* MantaFlow fluid solver framework
|
||||
* Copyright 2017-2018 Steffen Wiewel, Moritz Becher, Rachel Chu
|
||||
*
|
||||
* This program is free software, distributed under the terms of the
|
||||
* Apache License, Version 2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Convert mantaflow grids to/from numpy arrays
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#include "manta.h"
|
||||
#include "pythonInclude.h"
|
||||
|
||||
#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
|
||||
#include "numpy/arrayobject.h"
|
||||
|
||||
namespace Manta {
|
||||
|
||||
#if PY_VERSION_HEX < 0x03000000
|
||||
PyMODINIT_FUNC initNumpy()
|
||||
{
|
||||
import_array();
|
||||
}
|
||||
#endif
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Class Functions
|
||||
// ------------------------------------------------------------------------
|
||||
PyArrayContainer::PyArrayContainer(void *_pParentPyArray) : pParentPyArray(_pParentPyArray)
|
||||
{
|
||||
ExtractData(pParentPyArray);
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
PyArrayContainer::PyArrayContainer(const PyArrayContainer &_Other)
|
||||
: pParentPyArray(_Other.pParentPyArray)
|
||||
{
|
||||
ExtractData(pParentPyArray);
|
||||
Py_INCREF(pParentPyArray);
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
PyArrayContainer::~PyArrayContainer()
|
||||
{
|
||||
Py_DECREF(pParentPyArray);
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
PyArrayContainer &PyArrayContainer::operator=(const PyArrayContainer &_Other)
|
||||
{
|
||||
if (this != &_Other) {
|
||||
// DecRef the existing resource
|
||||
Py_DECREF(pParentPyArray);
|
||||
|
||||
// Relink new data
|
||||
pParentPyArray = _Other.pParentPyArray;
|
||||
ExtractData(pParentPyArray);
|
||||
Py_INCREF(pParentPyArray);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
void PyArrayContainer::ExtractData(void *_pParentPyArray)
|
||||
{
|
||||
PyArrayObject *pParent = reinterpret_cast<PyArrayObject *>(pParentPyArray);
|
||||
|
||||
int numDims = PyArray_NDIM(pParent);
|
||||
long *pDims = (long *)PyArray_DIMS(pParent);
|
||||
|
||||
pData = PyArray_DATA(pParent);
|
||||
TotalSize = PyArray_SIZE(pParent);
|
||||
Dims = std::vector<long>(&pDims[0], &pDims[numDims]);
|
||||
|
||||
int iDataType = PyArray_TYPE(pParent);
|
||||
switch (iDataType) {
|
||||
case NPY_FLOAT:
|
||||
DataType = N_FLOAT;
|
||||
break;
|
||||
case NPY_DOUBLE:
|
||||
DataType = N_DOUBLE;
|
||||
break;
|
||||
case NPY_INT:
|
||||
DataType = N_INT;
|
||||
break;
|
||||
default:
|
||||
errMsg("unknown type of Numpy array");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Conversion Functions
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
template<> PyArrayContainer fromPy<PyArrayContainer>(PyObject *obj)
|
||||
{
|
||||
if (PyArray_API == nullptr) {
|
||||
// python 3 uses the return value
|
||||
#if PY_VERSION_HEX >= 0x03000000
|
||||
import_array();
|
||||
#else
|
||||
initNumpy();
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!PyArray_Check(obj)) {
|
||||
errMsg("argument is not an numpy array");
|
||||
}
|
||||
|
||||
PyArrayObject *obj_p = reinterpret_cast<PyArrayObject *>(
|
||||
PyArray_CheckFromAny(obj,
|
||||
nullptr,
|
||||
0,
|
||||
0,
|
||||
/*NPY_ARRAY_ENSURECOPY*/ NPY_ARRAY_C_CONTIGUOUS |
|
||||
NPY_ARRAY_ENSUREARRAY | NPY_ARRAY_NOTSWAPPED,
|
||||
nullptr));
|
||||
PyArrayContainer container = PyArrayContainer(obj_p);
|
||||
|
||||
return container;
|
||||
}
|
||||
|
||||
// template<> PyArrayContainer* fromPyPtr<PyArrayContainer>(PyObject* obj, std::vector<void*>* tmp)
|
||||
// {
|
||||
// if (!tmp) throw Error("dynamic de-ref not supported for this type");
|
||||
// void* ptr = malloc(sizeof(PyArrayContainer));
|
||||
// tmp->push_back(ptr);
|
||||
|
||||
// *((PyArrayContainer*) ptr) = fromPy<PyArrayContainer>(obj);
|
||||
// return (PyArrayContainer*) ptr;
|
||||
// }
|
||||
} // namespace Manta
|
||||
86
blender-5.2.0/extern/mantaflow/helper/pwrapper/numpyWrap.h
vendored
Normal file
86
blender-5.2.0/extern/mantaflow/helper/pwrapper/numpyWrap.h
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* MantaFlow fluid solver framework
|
||||
* Copyright 2017 Steffen Wiewel, Moritz Baecher, Rachel Chu
|
||||
*
|
||||
* This program is free software, distributed under the terms of the
|
||||
* Apache License, Version 2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Convert mantaflow grids to/from numpy arrays
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifdef _PCONVERT_H
|
||||
# ifndef _NUMPYCONVERT_H
|
||||
# define _NUMPYCONVERT_H
|
||||
|
||||
enum NumpyTypes {
|
||||
N_BOOL = 0,
|
||||
N_BYTE,
|
||||
N_UBYTE,
|
||||
N_SHORT,
|
||||
N_USHORT,
|
||||
N_INT,
|
||||
N_UINT,
|
||||
N_LONG,
|
||||
N_ULONG,
|
||||
N_LONGLONG,
|
||||
N_ULONGLONG,
|
||||
N_FLOAT,
|
||||
N_DOUBLE,
|
||||
N_LONGDOUBLE,
|
||||
N_CFLOAT,
|
||||
N_CDOUBLE,
|
||||
N_CLONGDOUBLE,
|
||||
N_OBJECT = 17,
|
||||
N_STRING,
|
||||
N_UNICODE,
|
||||
N_VOID,
|
||||
/*
|
||||
* New 1.6 types appended, may be integrated
|
||||
* into the above in 2.0.
|
||||
*/
|
||||
N_DATETIME,
|
||||
N_TIMEDELTA,
|
||||
N_HALF,
|
||||
|
||||
N_NTYPES,
|
||||
N_NOTYPE,
|
||||
N_CHAR, /* special flag */
|
||||
N_USERDEF = 256, /* leave room for characters */
|
||||
|
||||
/* The number of types not including the new 1.6 types */
|
||||
N_NTYPES_ABI_COMPATIBLE = 21
|
||||
};
|
||||
|
||||
namespace Manta {
|
||||
class PyArrayContainer {
|
||||
public:
|
||||
/// Constructors
|
||||
PyArrayContainer(void *_pParentPyArray);
|
||||
PyArrayContainer(const PyArrayContainer &_Other);
|
||||
~PyArrayContainer();
|
||||
/// Operators
|
||||
PyArrayContainer &operator=(const PyArrayContainer &_Other);
|
||||
|
||||
private:
|
||||
void ExtractData(void *_pParentPyArray);
|
||||
|
||||
public:
|
||||
void *pData;
|
||||
NumpyTypes DataType;
|
||||
unsigned int TotalSize;
|
||||
std::vector<long> Dims;
|
||||
|
||||
private:
|
||||
void *pParentPyArray;
|
||||
};
|
||||
|
||||
// template<> PyArrayContainer* fromPyPtr<PyArrayContainer>(PyObject* obj, std::vector<void*>*
|
||||
// tmp);
|
||||
template<> PyArrayContainer fromPy<PyArrayContainer>(PyObject *obj);
|
||||
} // namespace Manta
|
||||
|
||||
# endif
|
||||
#endif
|
||||
220
blender-5.2.0/extern/mantaflow/helper/pwrapper/pclass.cpp
vendored
Normal file
220
blender-5.2.0/extern/mantaflow/helper/pwrapper/pclass.cpp
vendored
Normal file
@@ -0,0 +1,220 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* 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 <QMutex>
|
||||
#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 *> PbClass::mInstances;
|
||||
|
||||
PbClass::PbClass(FluidSolver *parent, const string &name, PyObject *obj)
|
||||
: mMutex(nullptr), mParent(parent), mPyObject(obj), mName(name), mHidden(false)
|
||||
{
|
||||
mMutex = new QMutex();
|
||||
}
|
||||
|
||||
PbClass::PbClass(const PbClass &a)
|
||||
: mMutex(nullptr), mParent(a.mParent), mPyObject(0), mName("_unnamed"), mHidden(false)
|
||||
{
|
||||
mMutex = new QMutex();
|
||||
}
|
||||
|
||||
PbClass::~PbClass()
|
||||
{
|
||||
for (vector<PbClass *>::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<std::string>("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() == nullptr) {
|
||||
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<string>(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
|
||||
126
blender-5.2.0/extern/mantaflow/helper/pwrapper/pclass.h
vendored
Normal file
126
blender-5.2.0/extern/mantaflow/helper/pwrapper/pclass.h
vendored
Normal file
@@ -0,0 +1,126 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* MantaFlow fluid solver framework
|
||||
* Copyright 2011-2014 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
|
||||
*
|
||||
* Base class for all Python-exposed classes
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// NOTE:
|
||||
// Do not include this file in user code, include "manta.h" instead
|
||||
// -----------------------------------------------------------------
|
||||
|
||||
#ifdef _MANTA_H
|
||||
# ifndef _PTYPE_H
|
||||
# define _PTYPE_H
|
||||
|
||||
# include <string>
|
||||
# include <vector>
|
||||
# include <map>
|
||||
|
||||
class QMutex;
|
||||
|
||||
namespace Manta {
|
||||
struct PbClassData;
|
||||
class FluidSolver;
|
||||
class PbArgs;
|
||||
|
||||
struct PbType {
|
||||
std::string S;
|
||||
std::string str() const;
|
||||
};
|
||||
struct PbTypeVec {
|
||||
std::vector<PbType> T;
|
||||
std::string str() const;
|
||||
};
|
||||
|
||||
//! Base class for all classes exposed to Python
|
||||
class PbClass {
|
||||
public:
|
||||
PbClass(FluidSolver *parent, const std::string &name = "", PyObject *obj = nullptr);
|
||||
PbClass(const PbClass &a);
|
||||
virtual ~PbClass();
|
||||
|
||||
// basic property setter/getters
|
||||
void setName(const std::string &name)
|
||||
{
|
||||
mName = name;
|
||||
}
|
||||
std::string getName() const
|
||||
{
|
||||
return mName;
|
||||
}
|
||||
PyObject *getPyObject() const
|
||||
{
|
||||
return mPyObject;
|
||||
}
|
||||
void registerObject(PyObject *obj, PbArgs *args);
|
||||
FluidSolver *getParent() const
|
||||
{
|
||||
return mParent;
|
||||
}
|
||||
void setParent(FluidSolver *v)
|
||||
{
|
||||
mParent = v;
|
||||
}
|
||||
void checkParent();
|
||||
|
||||
// hidden flag for GUI, debug output
|
||||
inline bool isHidden()
|
||||
{
|
||||
return mHidden;
|
||||
}
|
||||
inline void setHidden(bool v)
|
||||
{
|
||||
mHidden = v;
|
||||
}
|
||||
|
||||
void lock();
|
||||
void unlock();
|
||||
bool tryLock();
|
||||
|
||||
// PbClass instance registry
|
||||
static int getNumInstances();
|
||||
static PbClass *getInstance(int index);
|
||||
static void renameObjects();
|
||||
|
||||
// converters
|
||||
static bool isNullRef(PyObject *o);
|
||||
static bool isNoneRef(PyObject *o);
|
||||
static PbClass *createPyObject(const std::string &classname,
|
||||
const std::string &name,
|
||||
PbArgs &args,
|
||||
PbClass *parent);
|
||||
inline bool canConvertTo(const std::string &classname)
|
||||
{
|
||||
return Pb::canConvert(mPyObject, classname);
|
||||
}
|
||||
|
||||
protected:
|
||||
QMutex *mMutex;
|
||||
FluidSolver *mParent;
|
||||
PyObject *mPyObject;
|
||||
std::string mName;
|
||||
bool mHidden;
|
||||
|
||||
static std::vector<PbClass *> mInstances;
|
||||
};
|
||||
|
||||
//!\cond Register
|
||||
|
||||
void pbFinalizePlugin(FluidSolver *parent, const std::string &name, bool doTime = true);
|
||||
void pbPreparePlugin(FluidSolver *parent, const std::string &name, bool doTime = true);
|
||||
void pbSetError(const std::string &fn, const std::string &ex);
|
||||
|
||||
//!\endcond
|
||||
|
||||
} // namespace Manta
|
||||
|
||||
# endif
|
||||
#endif
|
||||
663
blender-5.2.0/extern/mantaflow/helper/pwrapper/pconvert.cpp
vendored
Normal file
663
blender-5.2.0/extern/mantaflow/helper/pwrapper/pconvert.cpp
vendored
Normal file
@@ -0,0 +1,663 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* 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<TmpCleanupFn> *tmp)
|
||||
{
|
||||
if (!tmp)
|
||||
throw Error("dynamic de-ref not supported for this type");
|
||||
|
||||
T *ptr = new T(fromPy<T>(obj));
|
||||
tmp->push_back([ptr]() { delete ptr; });
|
||||
return ptr;
|
||||
}
|
||||
template<> float *fromPyPtr<float>(PyObject *obj, std::vector<TmpCleanupFn> *tmp)
|
||||
{
|
||||
return tmpAlloc<float>(obj, tmp);
|
||||
}
|
||||
template<> double *fromPyPtr<double>(PyObject *obj, std::vector<TmpCleanupFn> *tmp)
|
||||
{
|
||||
return tmpAlloc<double>(obj, tmp);
|
||||
}
|
||||
template<> int *fromPyPtr<int>(PyObject *obj, std::vector<TmpCleanupFn> *tmp)
|
||||
{
|
||||
return tmpAlloc<int>(obj, tmp);
|
||||
}
|
||||
template<> std::string *fromPyPtr<std::string>(PyObject *obj, std::vector<TmpCleanupFn> *tmp)
|
||||
{
|
||||
return tmpAlloc<std::string>(obj, tmp);
|
||||
}
|
||||
template<> bool *fromPyPtr<bool>(PyObject *obj, std::vector<TmpCleanupFn> *tmp)
|
||||
{
|
||||
return tmpAlloc<bool>(obj, tmp);
|
||||
}
|
||||
template<> Vec3 *fromPyPtr<Vec3>(PyObject *obj, std::vector<TmpCleanupFn> *tmp)
|
||||
{
|
||||
return tmpAlloc<Vec3>(obj, tmp);
|
||||
}
|
||||
template<> Vec3i *fromPyPtr<Vec3i>(PyObject *obj, std::vector<TmpCleanupFn> *tmp)
|
||||
{
|
||||
return tmpAlloc<Vec3i>(obj, tmp);
|
||||
}
|
||||
template<> Vec4 *fromPyPtr<Vec4>(PyObject *obj, std::vector<TmpCleanupFn> *tmp)
|
||||
{
|
||||
return tmpAlloc<Vec4>(obj, tmp);
|
||||
}
|
||||
template<> Vec4i *fromPyPtr<Vec4i>(PyObject *obj, std::vector<TmpCleanupFn> *tmp)
|
||||
{
|
||||
return tmpAlloc<Vec4i>(obj, tmp);
|
||||
}
|
||||
template<>
|
||||
std::vector<PbClass *> *fromPyPtr<std::vector<PbClass *>>(PyObject *obj, std::vector<TmpCleanupFn> *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 (auto &fn : mTmpStorageCleanup)
|
||||
fn();
|
||||
mTmpStorageCleanup.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
|
||||
266
blender-5.2.0/extern/mantaflow/helper/pwrapper/pconvert.h
vendored
Normal file
266
blender-5.2.0/extern/mantaflow/helper/pwrapper/pconvert.h
vendored
Normal file
@@ -0,0 +1,266 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* 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 <functional>
|
||||
# include <string>
|
||||
# include <map>
|
||||
# include <vector>
|
||||
|
||||
namespace Manta {
|
||||
template<class T> class Grid;
|
||||
|
||||
//! Locks the given PbClass Arguments until ArgLocker goes out of scope
|
||||
struct ArgLocker {
|
||||
void add(PbClass *p);
|
||||
~ArgLocker();
|
||||
std::vector<PbClass *> locks;
|
||||
};
|
||||
|
||||
PyObject *getPyNone();
|
||||
|
||||
using TmpCleanupFn = std::function<void()>;
|
||||
|
||||
// for PbClass-derived classes
|
||||
template<class T> T *fromPyPtr(PyObject *obj, std::vector<TmpCleanupFn> *tmp)
|
||||
{
|
||||
if (PbClass::isNullRef(obj) || PbClass::isNoneRef(obj))
|
||||
return 0;
|
||||
PbClass *pbo = Pb::objFromPy(obj);
|
||||
const std::string &type = Namify<T>::S;
|
||||
if (!pbo || !(pbo->canConvertTo(type)))
|
||||
throw Error("can't convert argument to " + type + "*");
|
||||
return (T *)(pbo);
|
||||
}
|
||||
|
||||
template<> float *fromPyPtr<float>(PyObject *obj, std::vector<TmpCleanupFn> *tmp);
|
||||
template<> double *fromPyPtr<double>(PyObject *obj, std::vector<TmpCleanupFn> *tmp);
|
||||
template<> int *fromPyPtr<int>(PyObject *obj, std::vector<TmpCleanupFn> *tmp);
|
||||
template<> std::string *fromPyPtr<std::string>(PyObject *obj, std::vector<TmpCleanupFn> *tmp);
|
||||
template<> bool *fromPyPtr<bool>(PyObject *obj, std::vector<TmpCleanupFn> *tmp);
|
||||
template<> Vec3 *fromPyPtr<Vec3>(PyObject *obj, std::vector<TmpCleanupFn> *tmp);
|
||||
template<> Vec3i *fromPyPtr<Vec3i>(PyObject *obj, std::vector<TmpCleanupFn> *tmp);
|
||||
template<> Vec4 *fromPyPtr<Vec4>(PyObject *obj, std::vector<TmpCleanupFn> *tmp);
|
||||
template<> Vec4i *fromPyPtr<Vec4i>(PyObject *obj, std::vector<TmpCleanupFn> *tmp);
|
||||
template<>
|
||||
std::vector<PbClass *> *fromPyPtr<std::vector<PbClass *>>(PyObject *obj, std::vector<TmpCleanupFn> *tmp);
|
||||
template<>
|
||||
std::vector<float> *fromPyPtr<std::vector<float>>(PyObject *obj, std::vector<TmpCleanupFn> *tmp);
|
||||
|
||||
PyObject *incref(PyObject *obj);
|
||||
template<class T> PyObject *toPy(const T &v)
|
||||
{
|
||||
PyObject *obj = v.getPyObject();
|
||||
if (obj) {
|
||||
return incref(obj);
|
||||
}
|
||||
T *co = new T(v);
|
||||
const std::string &type = Namify<typename remove_pointers<T>::type>::S;
|
||||
return Pb::copyObject(co, type);
|
||||
}
|
||||
template<class T> bool isPy(PyObject *obj)
|
||||
{
|
||||
if (PbClass::isNullRef(obj) || PbClass::isNoneRef(obj))
|
||||
return false;
|
||||
PbClass *pbo = Pb::objFromPy(obj);
|
||||
const std::string &type = Namify<typename remove_pointers<T>::type>::S;
|
||||
return pbo && pbo->canConvertTo(type);
|
||||
}
|
||||
|
||||
template<class T> 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<float>(PyObject *obj);
|
||||
template<> double fromPy<double>(PyObject *obj);
|
||||
template<> int fromPy<int>(PyObject *obj);
|
||||
template<> PyObject *fromPy<PyObject *>(PyObject *obj);
|
||||
template<> std::string fromPy<std::string>(PyObject *obj);
|
||||
template<> const char *fromPy<const char *>(PyObject *obj);
|
||||
template<> bool fromPy<bool>(PyObject *obj);
|
||||
template<> Vec3 fromPy<Vec3>(PyObject *obj);
|
||||
template<> Vec3i fromPy<Vec3i>(PyObject *obj);
|
||||
template<> Vec4 fromPy<Vec4>(PyObject *obj);
|
||||
template<> Vec4i fromPy<Vec4i>(PyObject *obj);
|
||||
template<> PbType fromPy<PbType>(PyObject *obj);
|
||||
template<> PbTypeVec fromPy<PbTypeVec>(PyObject *obj);
|
||||
template<> PbClass *fromPy<PbClass *>(PyObject *obj);
|
||||
template<> std::vector<PbClass *> fromPy<std::vector<PbClass *>>(PyObject *obj);
|
||||
template<> std::vector<float> fromPy<std::vector<float>>(PyObject *obj);
|
||||
|
||||
template<> PyObject *toPy<int>(const int &v);
|
||||
template<> PyObject *toPy<std::string>(const std::string &val);
|
||||
template<> PyObject *toPy<float>(const float &v);
|
||||
template<> PyObject *toPy<double>(const double &v);
|
||||
template<> PyObject *toPy<bool>(const bool &v);
|
||||
template<> PyObject *toPy<Vec3i>(const Vec3i &v);
|
||||
template<> PyObject *toPy<Vec3>(const Vec3 &v);
|
||||
template<> PyObject *toPy<Vec4i>(const Vec4i &v);
|
||||
template<> PyObject *toPy<Vec4>(const Vec4 &v);
|
||||
typedef PbClass *PbClass_Ptr;
|
||||
template<> PyObject *toPy<PbClass *>(const PbClass_Ptr &obj);
|
||||
template<> PyObject *toPy<std::vector<PbClass *>>(const std::vector<PbClass *> &vec);
|
||||
template<> PyObject *toPy<std::vector<float>>(const std::vector<float> &vec);
|
||||
|
||||
template<> bool isPy<float>(PyObject *obj);
|
||||
template<> bool isPy<double>(PyObject *obj);
|
||||
template<> bool isPy<int>(PyObject *obj);
|
||||
template<> bool isPy<PyObject *>(PyObject *obj);
|
||||
template<> bool isPy<std::string>(PyObject *obj);
|
||||
template<> bool isPy<const char *>(PyObject *obj);
|
||||
template<> bool isPy<bool>(PyObject *obj);
|
||||
template<> bool isPy<Vec3>(PyObject *obj);
|
||||
template<> bool isPy<Vec3i>(PyObject *obj);
|
||||
template<> bool isPy<Vec4>(PyObject *obj);
|
||||
template<> bool isPy<Vec4i>(PyObject *obj);
|
||||
template<> bool isPy<PbType>(PyObject *obj);
|
||||
template<> bool isPy<std::vector<PbClass *>>(PyObject *obj);
|
||||
template<> bool isPy<std::vector<float>>(PyObject *obj);
|
||||
|
||||
//! Encapsulation of python arguments
|
||||
class PbArgs {
|
||||
public:
|
||||
PbArgs(PyObject *linargs = nullptr, PyObject *dict = nullptr);
|
||||
~PbArgs();
|
||||
void setup(PyObject *linargs = nullptr, PyObject *dict = nullptr);
|
||||
|
||||
void check();
|
||||
FluidSolver *obtainParent();
|
||||
|
||||
inline int numLinArgs()
|
||||
{
|
||||
return mLinData.size();
|
||||
}
|
||||
|
||||
inline bool has(const std::string &key)
|
||||
{
|
||||
return getItem(key, false) != nullptr;
|
||||
}
|
||||
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<class T> inline void add(const std::string &key, T arg)
|
||||
{
|
||||
DataElement el = {toPy(arg), false};
|
||||
mData[key] = el;
|
||||
}
|
||||
template<class T> inline T get(const std::string &key, int number = -1, ArgLocker *lk = nullptr)
|
||||
{
|
||||
visit(number, key);
|
||||
PyObject *o = getItem(key, false, lk);
|
||||
if (o)
|
||||
return fromPy<T>(o);
|
||||
o = getItem(number, false, lk);
|
||||
if (o)
|
||||
return fromPy<T>(o);
|
||||
errMsg("Argument '" + key + "' is not defined.");
|
||||
}
|
||||
template<class T>
|
||||
inline T getOpt(const std::string &key, int number, T defarg, ArgLocker *lk = nullptr)
|
||||
{
|
||||
visit(number, key);
|
||||
PyObject *o = getItem(key, false, lk);
|
||||
if (o)
|
||||
return fromPy<T>(o);
|
||||
if (number >= 0)
|
||||
o = getItem(number, false, lk);
|
||||
return (o) ? fromPy<T>(o) : defarg;
|
||||
}
|
||||
template<class T>
|
||||
inline T *getPtrOpt(const std::string &key, int number, T *defarg, ArgLocker *lk = nullptr)
|
||||
{
|
||||
visit(number, key);
|
||||
PyObject *o = getItem(key, false, lk);
|
||||
if (o)
|
||||
return fromPyPtr<T>(o, &mTmpStorageCleanup);
|
||||
if (number >= 0)
|
||||
o = getItem(number, false, lk);
|
||||
return o ? fromPyPtr<T>(o, &mTmpStorageCleanup) : defarg;
|
||||
}
|
||||
template<class T>
|
||||
inline T *getPtr(const std::string &key, int number = -1, ArgLocker *lk = nullptr)
|
||||
{
|
||||
visit(number, key);
|
||||
PyObject *o = getItem(key, false, lk);
|
||||
if (o)
|
||||
return fromPyPtr<T>(o, &mTmpStorageCleanup);
|
||||
o = getItem(number, false, lk);
|
||||
if (o)
|
||||
return fromPyPtr<T>(o, &mTmpStorageCleanup);
|
||||
errMsg("Argument '" + key + "' is not defined.");
|
||||
}
|
||||
|
||||
// automatic template type deduction
|
||||
template<class T> bool typeCheck(int num, const std::string &name)
|
||||
{
|
||||
PyObject *o = getItem(name, false, 0);
|
||||
if (!o)
|
||||
o = getItem(num, false, 0);
|
||||
return o ? isPy<typename remove_pointers<T>::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 = nullptr);
|
||||
PyObject *getItem(size_t number, bool strict, ArgLocker *lk = nullptr);
|
||||
|
||||
struct DataElement {
|
||||
PyObject *obj;
|
||||
bool visited;
|
||||
};
|
||||
std::map<std::string, DataElement> mData;
|
||||
std::vector<DataElement> mLinData;
|
||||
PyObject *mLinArgs, *mKwds;
|
||||
std::vector<TmpCleanupFn> mTmpStorageCleanup;
|
||||
};
|
||||
|
||||
} // namespace Manta
|
||||
|
||||
# if NUMPY == 1
|
||||
# include "numpyWrap.h"
|
||||
# endif
|
||||
|
||||
# endif
|
||||
#endif
|
||||
416
blender-5.2.0/extern/mantaflow/helper/pwrapper/pvec3.cpp
vendored
Normal file
416
blender-5.2.0/extern/mantaflow/helper/pwrapper/pvec3.cpp
vendored
Normal file
@@ -0,0 +1,416 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* Vec3 class extension for python
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#include "pythonInclude.h"
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include "vectorbase.h"
|
||||
#include "structmember.h"
|
||||
#include "manta.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace Manta {
|
||||
|
||||
extern PyTypeObject PbVec3Type;
|
||||
|
||||
struct PbVec3 {
|
||||
PyObject_HEAD
|
||||
float data[3];
|
||||
};
|
||||
|
||||
static void PbVec3Dealloc(PbVec3 *self)
|
||||
{
|
||||
Py_TYPE(self)->tp_free((PyObject *)self);
|
||||
}
|
||||
|
||||
static PyObject *PbVec3New(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
return type->tp_alloc(type, 0);
|
||||
}
|
||||
|
||||
static int PbVec3Init(PbVec3 *self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
|
||||
float x1 = numeric_limits<float>::quiet_NaN(), x2 = x1, x3 = x1;
|
||||
if (!PyArg_ParseTuple(args, "|fff", &x1, &x2, &x3))
|
||||
return -1;
|
||||
|
||||
if (!c_isnan(x1)) {
|
||||
self->data[0] = x1;
|
||||
if (!c_isnan(x2) && !c_isnan(x3)) {
|
||||
self->data[1] = x2;
|
||||
self->data[2] = x3;
|
||||
}
|
||||
else {
|
||||
if (!c_isnan(x2) || !c_isnan(x3)) {
|
||||
errMsg("Invalid partial init of vec3");
|
||||
}
|
||||
self->data[1] = x1;
|
||||
self->data[2] = x1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
self->data[0] = 0;
|
||||
self->data[1] = 0;
|
||||
self->data[2] = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static PyObject *PbVec3Repr(PbVec3 *self)
|
||||
{
|
||||
Manta::Vec3 v(self->data[0], self->data[1], self->data[2]);
|
||||
return PyUnicode_FromFormat(v.toString().c_str());
|
||||
}
|
||||
|
||||
static PyMemberDef PbVec3Members[] = {
|
||||
{(char *)"x", T_FLOAT, offsetof(PbVec3, data), 0, (char *)"X"},
|
||||
{(char *)"y", T_FLOAT, offsetof(PbVec3, data) + sizeof(float), 0, (char *)"Y"},
|
||||
{(char *)"z", T_FLOAT, offsetof(PbVec3, data) + sizeof(float) * 2, 0, (char *)"Z"},
|
||||
{nullptr} // Sentinel
|
||||
};
|
||||
|
||||
static PyMethodDef PbVec3Methods[] = {
|
||||
//{"name", (PyCFunction)Noddy_name, METH_NOARGS, "Return the name, combining the first and last
|
||||
//name" },
|
||||
{nullptr} // Sentinel
|
||||
};
|
||||
|
||||
// operator overloads
|
||||
|
||||
inline PyObject *PbNew(const Vec3 &a)
|
||||
{
|
||||
PbVec3 *obj = (PbVec3 *)PbVec3New(&PbVec3Type, 0, 0);
|
||||
obj->data[0] = a.x;
|
||||
obj->data[1] = a.y;
|
||||
obj->data[2] = a.z;
|
||||
return (PyObject *)obj;
|
||||
}
|
||||
|
||||
#define CONVERTVEC(obj) \
|
||||
Vec3 v##obj; \
|
||||
if (PyObject_TypeCheck(obj, &PbVec3Type)) \
|
||||
v##obj = Vec3(&(((PbVec3 *)obj)->data[0])); \
|
||||
else if (PyFloat_Check(obj)) \
|
||||
v##obj = Vec3(PyFloat_AsDouble(obj)); \
|
||||
else if (PyLong_Check(obj)) \
|
||||
v##obj = Vec3(PyLong_AsDouble(obj)); \
|
||||
else { \
|
||||
Py_INCREF(Py_NotImplemented); \
|
||||
return Py_NotImplemented; \
|
||||
}
|
||||
|
||||
#define OPHEADER \
|
||||
if (!PyObject_TypeCheck(a, &PbVec3Type) && !PyObject_TypeCheck(b, &PbVec3Type)) { \
|
||||
Py_INCREF(Py_NotImplemented); \
|
||||
return Py_NotImplemented; \
|
||||
} \
|
||||
CONVERTVEC(a) \
|
||||
CONVERTVEC(b)
|
||||
|
||||
#define OPHEADER1 \
|
||||
if (!PyObject_TypeCheck(a, &PbVec3Type)) { \
|
||||
Py_INCREF(Py_NotImplemented); \
|
||||
return Py_NotImplemented; \
|
||||
} \
|
||||
CONVERTVEC(a)
|
||||
|
||||
PyObject *PbVec3Add(PyObject *a, PyObject *b)
|
||||
{
|
||||
OPHEADER
|
||||
return PbNew(va + vb);
|
||||
}
|
||||
|
||||
PyObject *PbVec3Sub(PyObject *a, PyObject *b)
|
||||
{
|
||||
OPHEADER
|
||||
return PbNew(va - vb);
|
||||
}
|
||||
|
||||
PyObject *PbVec3Mult(PyObject *a, PyObject *b)
|
||||
{
|
||||
OPHEADER
|
||||
return PbNew(va * vb);
|
||||
}
|
||||
|
||||
PyObject *PbVec3Div(PyObject *a, PyObject *b)
|
||||
{
|
||||
OPHEADER
|
||||
return PbNew(va / vb);
|
||||
}
|
||||
|
||||
PyObject *PbVec3Negative(PyObject *a)
|
||||
{
|
||||
OPHEADER1
|
||||
return PbNew(-va);
|
||||
}
|
||||
|
||||
// numbers are defined subtely different in Py3 (WTF?)
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
static PyNumberMethods PbVec3NumberMethods = {
|
||||
(binaryfunc)PbVec3Add, // binaryfunc nb_add;
|
||||
(binaryfunc)PbVec3Sub, // binaryfunc nb_sub;
|
||||
(binaryfunc)PbVec3Mult, // binaryfunc nb_mult;
|
||||
0, // binaryfunc nb_remainder;
|
||||
0, // binaryfunc nb_divmod;
|
||||
0, // ternaryfunc nb_power;
|
||||
(unaryfunc)PbVec3Negative, // unaryfunc nb_negative;
|
||||
0, // unaryfunc nb_positive;
|
||||
0, // unaryfunc nb_absolute;
|
||||
0, // inquiry nb_bool;
|
||||
0, // unaryfunc nb_invert;
|
||||
0, // binaryfunc nb_lshift;
|
||||
0, // binaryfunc nb_rshift;
|
||||
0, // binaryfunc nb_and;
|
||||
0, // binaryfunc nb_xor;
|
||||
0, // binaryfunc nb_or;
|
||||
0, // unaryfunc nb_int;
|
||||
0, // void *nb_reserved;
|
||||
0, // unaryfunc nb_float;
|
||||
0, // binaryfunc nb_inplace_add;
|
||||
0, // binaryfunc nb_inplace_subtract;
|
||||
0, // binaryfunc nb_inplace_multiply;
|
||||
0, // binaryfunc nb_inplace_remainder;
|
||||
0, // ternaryfunc nb_inplace_power;
|
||||
0, // binaryfunc nb_inplace_lshift;
|
||||
0, // binaryfunc nb_inplace_rshift;
|
||||
0, // binaryfunc nb_inplace_and;
|
||||
0, // binaryfunc nb_inplace_xor;
|
||||
0, // binaryfunc nb_inplace_or;
|
||||
|
||||
0, // binaryfunc nb_floor_divide;
|
||||
(binaryfunc)PbVec3Div, // binaryfunc nb_true_divide;
|
||||
0, // binaryfunc nb_inplace_floor_divide;
|
||||
0, // binaryfunc nb_inplace_true_divide;
|
||||
|
||||
0 // unaryfunc nb_index;
|
||||
};
|
||||
#else
|
||||
static PyNumberMethods PbVec3NumberMethods = {
|
||||
(binaryfunc)PbVec3Add, // binaryfunc nb_add;
|
||||
(binaryfunc)PbVec3Sub, // binaryfunc nb_sub;
|
||||
(binaryfunc)PbVec3Mult, // binaryfunc nb_mult;
|
||||
0, // binaryfunc nb_divide;
|
||||
0, // binaryfunc nb_remainder;
|
||||
0, // binaryfunc nb_divmod;
|
||||
0, // ternaryfunc nb_power;
|
||||
(unaryfunc)PbVec3Negative, // unaryfunc nb_negative;
|
||||
0, // unaryfunc nb_positive;
|
||||
0, // unaryfunc nb_absolute;
|
||||
0, // inquiry nb_nonzero;
|
||||
0, // unaryfunc nb_invert;
|
||||
0, // binaryfunc nb_lshift;
|
||||
0, // binaryfunc nb_rshift;
|
||||
0, // binaryfunc nb_and;
|
||||
0, // binaryfunc nb_xor;
|
||||
0, // binaryfunc nb_or;
|
||||
0, // coercion nb_coerce;
|
||||
0, // unaryfunc nb_int;
|
||||
0, // unaryfunc nb_long;
|
||||
0, // unaryfunc nb_float;
|
||||
0, // unaryfunc nb_oct;
|
||||
0, // unaryfunc nb_hex;
|
||||
0, // binaryfunc nb_inplace_add;
|
||||
0, // binaryfunc nb_inplace_subtract;
|
||||
0, // binaryfunc nb_inplace_multiply;
|
||||
0, // binaryfunc nb_inplace_divide;
|
||||
0, // binaryfunc nb_inplace_remainder;
|
||||
0, // ternaryfunc nb_inplace_power;
|
||||
0, // binaryfunc nb_inplace_lshift;
|
||||
0, // binaryfunc nb_inplace_rshift;
|
||||
0, // binaryfunc nb_inplace_and;
|
||||
0, // binaryfunc nb_inplace_xor;
|
||||
0, // binaryfunc nb_inplace_or;
|
||||
0, // binaryfunc nb_floor_divide;
|
||||
(binaryfunc)PbVec3Div, // binaryfunc nb_true_divide;
|
||||
0, // binaryfunc nb_inplace_floor_divide;
|
||||
0, // binaryfunc nb_inplace_true_divide;
|
||||
0, // unaryfunc nb_index;
|
||||
};
|
||||
#endif
|
||||
|
||||
PyTypeObject PbVec3Type = {
|
||||
PyVarObject_HEAD_INIT(nullptr, 0) "manta.vec3", /* tp_name */
|
||||
sizeof(PbVec3), /* tp_basicsize */
|
||||
0, /* tp_itemsize */
|
||||
(destructor)PbVec3Dealloc, /* tp_dealloc */
|
||||
0, /* tp_print */
|
||||
0, /* tp_getattr */
|
||||
0, /* tp_setattr */
|
||||
0, /* tp_reserved */
|
||||
(reprfunc)PbVec3Repr, /* tp_repr */
|
||||
&PbVec3NumberMethods, /* tp_as_number */
|
||||
0, /* tp_as_sequence */
|
||||
0, /* tp_as_mapping */
|
||||
0, /* tp_hash */
|
||||
0, /* tp_call */
|
||||
0, /* tp_str */
|
||||
0, /* tp_getattro */
|
||||
0, /* tp_setattro */
|
||||
0, /* tp_as_buffer */
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
|
||||
#else
|
||||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_CHECKTYPES, /* tp_flags */
|
||||
#endif
|
||||
"float vector type", /* tp_doc */
|
||||
0, /* tp_traverse */
|
||||
0, /* tp_clear */
|
||||
0, /* tp_richcompare */
|
||||
0, /* tp_weaklistoffset */
|
||||
0, /* tp_iter */
|
||||
0, /* tp_iternext */
|
||||
PbVec3Methods, /* tp_methods */
|
||||
PbVec3Members, /* tp_members */
|
||||
0, /* tp_getset */
|
||||
0, /* tp_base */
|
||||
0, /* tp_dict */
|
||||
0, /* tp_descr_get */
|
||||
0, /* tp_descr_set */
|
||||
0, /* tp_dictoffset */
|
||||
(initproc)PbVec3Init, /* tp_init */
|
||||
0, /* tp_alloc */
|
||||
PbVec3New, /* tp_new */
|
||||
};
|
||||
|
||||
inline PyObject *castPy(PyTypeObject *p)
|
||||
{
|
||||
return reinterpret_cast<PyObject *>(static_cast<void *>(p));
|
||||
}
|
||||
|
||||
// 4d vector
|
||||
|
||||
extern PyTypeObject PbVec4Type;
|
||||
|
||||
struct PbVec4 {
|
||||
PyObject_HEAD
|
||||
float data[4];
|
||||
};
|
||||
|
||||
static PyMethodDef PbVec4Methods[] = {
|
||||
{nullptr} // Sentinel
|
||||
};
|
||||
|
||||
static PyMemberDef PbVec4Members[] = {
|
||||
{(char *)"x", T_FLOAT, offsetof(PbVec4, data), 0, (char *)"X"},
|
||||
{(char *)"y", T_FLOAT, offsetof(PbVec4, data) + sizeof(float) * 1, 0, (char *)"Y"},
|
||||
{(char *)"z", T_FLOAT, offsetof(PbVec4, data) + sizeof(float) * 2, 0, (char *)"Z"},
|
||||
{(char *)"t", T_FLOAT, offsetof(PbVec4, data) + sizeof(float) * 3, 0, (char *)"T"},
|
||||
{nullptr} // Sentinel
|
||||
};
|
||||
|
||||
static void PbVec4Dealloc(PbVec4 *self)
|
||||
{
|
||||
Py_TYPE(self)->tp_free((PyObject *)self);
|
||||
}
|
||||
|
||||
static PyObject *PbVec4New(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
return type->tp_alloc(type, 0);
|
||||
}
|
||||
|
||||
static int PbVec4Init(PbVec4 *self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
|
||||
float x1 = numeric_limits<float>::quiet_NaN(), x2 = x1, x3 = x1, x4 = x1;
|
||||
if (!PyArg_ParseTuple(args, "|ffff", &x1, &x2, &x3, &x4))
|
||||
return -1;
|
||||
|
||||
if (!c_isnan(x1)) {
|
||||
self->data[0] = x1;
|
||||
if (!c_isnan(x2) && !c_isnan(x3) && !c_isnan(x4)) {
|
||||
self->data[1] = x2;
|
||||
self->data[2] = x3;
|
||||
self->data[3] = x4;
|
||||
}
|
||||
else {
|
||||
if (!c_isnan(x2) || !c_isnan(x3) || !c_isnan(x4)) {
|
||||
errMsg("Invalid partial init of vec4");
|
||||
}
|
||||
self->data[1] = self->data[2] = self->data[3] = x1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
self->data[0] = self->data[1] = self->data[2] = self->data[3] = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static PyObject *PbVec4Repr(PbVec4 *self)
|
||||
{
|
||||
Manta::Vec4 v(self->data[0], self->data[1], self->data[2], self->data[3]);
|
||||
return PyUnicode_FromFormat(v.toString().c_str());
|
||||
}
|
||||
|
||||
PyTypeObject PbVec4Type = {
|
||||
PyVarObject_HEAD_INIT(nullptr, 0) "manta.vec4", /* tp_name */
|
||||
sizeof(PbVec4), /* tp_basicsize */
|
||||
0, /* tp_itemsize */
|
||||
(destructor)PbVec4Dealloc, /* tp_dealloc */
|
||||
0, /* tp_print */
|
||||
0, /* tp_getattr */
|
||||
0, /* tp_setattr */
|
||||
0, /* tp_reserved */
|
||||
(reprfunc)PbVec4Repr, /* tp_repr */
|
||||
nullptr, // &PbVec4NumberMethods, /* tp_as_number */
|
||||
0, /* tp_as_sequence */
|
||||
0, /* tp_as_mapping */
|
||||
0, /* tp_hash */
|
||||
0, /* tp_call */
|
||||
0, /* tp_str */
|
||||
0, /* tp_getattro */
|
||||
0, /* tp_setattro */
|
||||
0, /* tp_as_buffer */
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
|
||||
#else
|
||||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_CHECKTYPES, /* tp_flags */
|
||||
#endif
|
||||
"float vector type", /* tp_doc */
|
||||
0, /* tp_traverse */
|
||||
0, /* tp_clear */
|
||||
0, /* tp_richcompare */
|
||||
0, /* tp_weaklistoffset */
|
||||
0, /* tp_iter */
|
||||
0, /* tp_iternext */
|
||||
PbVec4Methods, /* tp_methods */
|
||||
PbVec4Members, /* tp_members */
|
||||
0, /* tp_getset */
|
||||
0, /* tp_base */
|
||||
0, /* tp_dict */
|
||||
0, /* tp_descr_get */
|
||||
0, /* tp_descr_set */
|
||||
0, /* tp_dictoffset */
|
||||
(initproc)PbVec4Init, /* tp_init */
|
||||
0, /* tp_alloc */
|
||||
PbVec4New, /* tp_new */
|
||||
};
|
||||
|
||||
// register
|
||||
|
||||
void PbVecInitialize(PyObject *module)
|
||||
{
|
||||
if (PyType_Ready(&PbVec3Type) < 0)
|
||||
errMsg("can't initialize Vec3 type");
|
||||
Py_INCREF(castPy(&PbVec3Type));
|
||||
PyModule_AddObject(module, "vec3", (PyObject *)&PbVec3Type);
|
||||
|
||||
if (PyType_Ready(&PbVec4Type) < 0)
|
||||
errMsg("can't initialize Vec4 type");
|
||||
Py_INCREF(castPy(&PbVec4Type));
|
||||
PyModule_AddObject(module, "vec4", (PyObject *)&PbVec4Type);
|
||||
}
|
||||
const static Pb::Register _REG(PbVecInitialize);
|
||||
|
||||
} // namespace Manta
|
||||
48
blender-5.2.0/extern/mantaflow/helper/pwrapper/pythonInclude.h
vendored
Normal file
48
blender-5.2.0/extern/mantaflow/helper/pwrapper/pythonInclude.h
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* Base class for particle systems
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef _PYTHONINCLUDE_H
|
||||
#define _PYTHONINCLUDE_H
|
||||
|
||||
#if defined(WIN32) || defined(_WIN32)
|
||||
|
||||
// note - we have to include these first!
|
||||
# include <string>
|
||||
# include <vector>
|
||||
# include <iostream>
|
||||
|
||||
#endif
|
||||
|
||||
// the PYTHON_DEBUG_WITH_RELEASE define enables linking with python debug libraries
|
||||
#if (defined(_DEBUG) || (DEBUG == 1)) && defined(DEBUG_PYTHON_WITH_RELEASE)
|
||||
|
||||
// special handling, disable linking with debug version of python libs
|
||||
# undef _DEBUG
|
||||
# define NDEBUG
|
||||
# include <Python.h>
|
||||
# if NUMPY == 1
|
||||
# define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
|
||||
# include "numpy/arrayobject.h"
|
||||
# endif
|
||||
# define _DEBUG
|
||||
# undef NDEBUG
|
||||
|
||||
#else
|
||||
# include <Python.h>
|
||||
# if NUMPY == 1
|
||||
# define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
|
||||
# include "numpy/arrayobject.h"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
817
blender-5.2.0/extern/mantaflow/helper/pwrapper/registry.cpp
vendored
Normal file
817
blender-5.2.0/extern/mantaflow/helper/pwrapper/registry.cpp
vendored
Normal file
@@ -0,0 +1,817 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* MantaFlow fluid solver framework
|
||||
* Copyright 2011-2014 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
|
||||
*
|
||||
* Auto python registry
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
#include "pythonInclude.h"
|
||||
#include "structmember.h"
|
||||
#include "manta.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
const string gDefaultModuleName = "manta";
|
||||
|
||||
namespace Pb {
|
||||
|
||||
//******************************************************************************
|
||||
// Custom object definition
|
||||
|
||||
struct Method {
|
||||
Method(const string &n, const string &d, GenericFunction f) : name(n), doc(d), func(f)
|
||||
{
|
||||
}
|
||||
string name, doc;
|
||||
GenericFunction func;
|
||||
|
||||
PyMethodDef def()
|
||||
{
|
||||
PyMethodDef def = {&name[0], (PyCFunction)func, METH_VARARGS | METH_KEYWORDS, &doc[0]};
|
||||
return def;
|
||||
}
|
||||
};
|
||||
struct GetSet {
|
||||
GetSet() : getter(0), setter(0)
|
||||
{
|
||||
}
|
||||
GetSet(const string &n, const string &d, Getter g, Setter s)
|
||||
: name(n), doc(d), getter(g), setter(s)
|
||||
{
|
||||
}
|
||||
string name, doc;
|
||||
Getter getter;
|
||||
Setter setter;
|
||||
|
||||
PyGetSetDef def()
|
||||
{
|
||||
PyGetSetDef def = {&name[0], getter, setter, &doc[0], nullptr};
|
||||
return def;
|
||||
}
|
||||
};
|
||||
|
||||
struct ClassData {
|
||||
string cName, pyName;
|
||||
string cPureName, cTemplate;
|
||||
InitFunc init;
|
||||
PyTypeObject typeInfo;
|
||||
PyNumberMethods numInfo;
|
||||
// PySequenceMethods seqInfo;
|
||||
vector<Method> methods;
|
||||
map<string, GetSet> getset;
|
||||
map<string, OperatorFunction> ops;
|
||||
ClassData *baseclass;
|
||||
string baseclassName;
|
||||
Constructor constructor;
|
||||
|
||||
vector<PyMethodDef> genMethods;
|
||||
vector<PyGetSetDef> genGetSet;
|
||||
};
|
||||
|
||||
struct PbObject {
|
||||
PyObject_HEAD
|
||||
Manta::PbClass *instance;
|
||||
ClassData *classdef;
|
||||
};
|
||||
|
||||
//******************************************************
|
||||
// Internal wrapper class
|
||||
|
||||
//! Registers all classes and methods exposed to Python.
|
||||
/*! This class is only used internally by Pb:: framwork.
|
||||
* Please use the functionality of PbClass to lookup and translate pointers. */
|
||||
class WrapperRegistry {
|
||||
public:
|
||||
static WrapperRegistry &instance();
|
||||
void addClass(const std::string &name,
|
||||
const std::string &internalName,
|
||||
const std::string &baseclass);
|
||||
void addEnumEntry(const std::string &name, int value);
|
||||
void addExternalInitializer(InitFunc func);
|
||||
void addMethod(const std::string &classname,
|
||||
const std::string &methodname,
|
||||
GenericFunction method);
|
||||
void addOperator(const std::string &classname,
|
||||
const std::string &methodname,
|
||||
OperatorFunction method);
|
||||
void addConstructor(const std::string &classname, Constructor method);
|
||||
void addGetSet(const std::string &classname,
|
||||
const std::string &property,
|
||||
Getter getfunc,
|
||||
Setter setfunc);
|
||||
void addPythonPath(const std::string &path);
|
||||
void addPythonCode(const std::string &file, const std::string &code);
|
||||
PyObject *createPyObject(const std::string &classname,
|
||||
const std::string &name,
|
||||
Manta::PbArgs &args,
|
||||
Manta::PbClass *parent);
|
||||
void construct(bool python_lifecycle, const std::string &scriptname, const vector<string> &args);
|
||||
void cleanup();
|
||||
void renameObjects();
|
||||
void runPreInit(PyObject *name_space);
|
||||
PyObject *initModule();
|
||||
ClassData *lookup(const std::string &name);
|
||||
bool canConvert(ClassData *from, ClassData *to);
|
||||
|
||||
private:
|
||||
ClassData *getOrConstructClass(const string &name);
|
||||
void registerBaseclasses();
|
||||
void registerDummyTypes();
|
||||
void registerMeta();
|
||||
void addConstants(PyObject *module);
|
||||
void registerOperators(ClassData *cls);
|
||||
void addParentMethods(ClassData *cls, ClassData *base);
|
||||
WrapperRegistry();
|
||||
~WrapperRegistry();
|
||||
std::map<std::string, ClassData *> mClasses;
|
||||
std::vector<ClassData *> mClassList;
|
||||
std::vector<InitFunc> mExtInitializers;
|
||||
std::vector<std::string> mPaths;
|
||||
std::string mCode, mScriptName;
|
||||
std::vector<std::string> args;
|
||||
std::map<std::string, int> mEnumValues;
|
||||
};
|
||||
|
||||
//******************************************************************************
|
||||
// Callback functions
|
||||
|
||||
PyObject *cbGetClass(PbObject *self, void *cl)
|
||||
{
|
||||
return Manta::toPy(self->classdef->cPureName);
|
||||
}
|
||||
|
||||
PyObject *cbGetTemplate(PbObject *self, void *cl)
|
||||
{
|
||||
return Manta::toPy(self->classdef->cTemplate);
|
||||
}
|
||||
|
||||
PyObject *cbGetCName(PbObject *self, void *cl)
|
||||
{
|
||||
return Manta::toPy(self->classdef->cName);
|
||||
}
|
||||
|
||||
void cbDealloc(PbObject *self)
|
||||
{
|
||||
// cout << "dealloc " << self->instance->getName() << " " << self->classdef->cName << endl;
|
||||
if (self->instance) {
|
||||
#ifndef BLENDER
|
||||
// don't delete top-level objects
|
||||
if (self->instance->getParent() != self->instance)
|
||||
delete self->instance;
|
||||
#else
|
||||
// in Blender we *have* to delete all objects
|
||||
delete self->instance;
|
||||
#endif
|
||||
}
|
||||
Py_TYPE(self)->tp_free((PyObject *)self);
|
||||
}
|
||||
|
||||
PyObject *cbNew(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
PbObject *self = (PbObject *)type->tp_alloc(type, 0);
|
||||
if (self != nullptr) {
|
||||
// lookup and link classdef
|
||||
self->classdef = WrapperRegistry::instance().lookup(type->tp_name);
|
||||
self->instance = nullptr;
|
||||
// cout << "creating " << self->classdef->cName << endl;
|
||||
}
|
||||
else
|
||||
errMsg("can't allocate new python class object");
|
||||
return (PyObject *)self;
|
||||
}
|
||||
|
||||
int cbDisableConstructor(PyObject *self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
errMsg("Can't instantiate a class template without template arguments");
|
||||
return -1;
|
||||
}
|
||||
|
||||
PyMODINIT_FUNC PyInit_manta_main(void)
|
||||
{
|
||||
MantaEnsureRegistration();
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
return WrapperRegistry::instance().initModule();
|
||||
#else
|
||||
WrapperRegistry::instance().initModule();
|
||||
#endif
|
||||
}
|
||||
|
||||
//******************************************************
|
||||
// WrapperRegistry
|
||||
|
||||
WrapperRegistry::WrapperRegistry()
|
||||
{
|
||||
addClass("__modclass__", "__modclass__", "");
|
||||
addClass("PbClass", "PbClass", "");
|
||||
}
|
||||
|
||||
WrapperRegistry::~WrapperRegistry()
|
||||
{
|
||||
// Some static constructions may have called WrapperRegistry.instance() and added
|
||||
// own classes, functions, etc. Ensure everything is cleaned up properly.
|
||||
cleanup();
|
||||
}
|
||||
|
||||
ClassData *WrapperRegistry::getOrConstructClass(const string &classname)
|
||||
{
|
||||
map<string, ClassData *>::iterator it = mClasses.find(classname);
|
||||
|
||||
if (it != mClasses.end())
|
||||
return it->second;
|
||||
ClassData *data = new ClassData;
|
||||
data->cName = classname;
|
||||
data->cPureName = classname;
|
||||
data->cTemplate = "";
|
||||
size_t tplIdx = classname.find('<');
|
||||
if (tplIdx != string::npos) {
|
||||
data->cPureName = classname.substr(0, tplIdx);
|
||||
data->cTemplate = classname.substr(tplIdx + 1, classname.find('>') - tplIdx - 1);
|
||||
}
|
||||
data->baseclass = nullptr;
|
||||
data->constructor = cbDisableConstructor;
|
||||
mClasses[classname] = data;
|
||||
mClassList.push_back(data);
|
||||
return data;
|
||||
}
|
||||
|
||||
void replaceAll(string &source, string const &find, string const &replace)
|
||||
{
|
||||
for (string::size_type i = 0; (i = source.find(find, i)) != std::string::npos;) {
|
||||
source.replace(i, find.length(), replace);
|
||||
i += replace.length() - find.length() + 1;
|
||||
}
|
||||
}
|
||||
|
||||
void WrapperRegistry::addClass(const string &pyName,
|
||||
const string &internalName,
|
||||
const string &baseclass)
|
||||
{
|
||||
ClassData *data = getOrConstructClass(internalName);
|
||||
|
||||
// regularize python name
|
||||
string pythonName = pyName;
|
||||
replaceAll(pythonName, "<", "_");
|
||||
replaceAll(pythonName, ">", "");
|
||||
replaceAll(pythonName, ",", "_");
|
||||
|
||||
if (data->pyName.empty())
|
||||
data->pyName = pythonName;
|
||||
mClasses[pythonName] = data;
|
||||
if (!baseclass.empty())
|
||||
data->baseclassName = baseclass;
|
||||
}
|
||||
|
||||
void WrapperRegistry::addEnumEntry(const string &name, int value)
|
||||
{
|
||||
/// Gather static definitions to add them as static python objects afterwards
|
||||
if (mEnumValues.insert(std::make_pair(name, value)).second == false) {
|
||||
errMsg("Enum entry '" + name + "' already existing...");
|
||||
}
|
||||
}
|
||||
|
||||
void WrapperRegistry::addExternalInitializer(InitFunc func)
|
||||
{
|
||||
mExtInitializers.push_back(func);
|
||||
}
|
||||
|
||||
void WrapperRegistry::addPythonPath(const string &path)
|
||||
{
|
||||
mPaths.push_back(path);
|
||||
}
|
||||
|
||||
void WrapperRegistry::addPythonCode(const string &file, const string &code)
|
||||
{
|
||||
mCode += code + "\n";
|
||||
}
|
||||
|
||||
void WrapperRegistry::addGetSet(const string &classname,
|
||||
const string &property,
|
||||
Getter getfunc,
|
||||
Setter setfunc)
|
||||
{
|
||||
ClassData *classdef = getOrConstructClass(classname);
|
||||
GetSet &def = classdef->getset[property];
|
||||
if (def.name.empty()) {
|
||||
def.name = property;
|
||||
def.doc = property;
|
||||
}
|
||||
if (getfunc)
|
||||
def.getter = getfunc;
|
||||
if (setfunc)
|
||||
def.setter = setfunc;
|
||||
}
|
||||
|
||||
void WrapperRegistry::addMethod(const string &classname,
|
||||
const string &methodname,
|
||||
GenericFunction func)
|
||||
{
|
||||
string aclass = classname;
|
||||
if (aclass.empty())
|
||||
aclass = "__modclass__";
|
||||
|
||||
ClassData *classdef = getOrConstructClass(aclass);
|
||||
for (int i = 0; i < (int)classdef->methods.size(); i++)
|
||||
if (classdef->methods[i].name == methodname)
|
||||
return; // avoid duplicates
|
||||
classdef->methods.push_back(Method(methodname, methodname, func));
|
||||
}
|
||||
|
||||
void WrapperRegistry::addOperator(const string &classname,
|
||||
const string &methodname,
|
||||
OperatorFunction func)
|
||||
{
|
||||
if (classname.empty())
|
||||
errMsg("PYTHON operators have to be defined within classes.");
|
||||
|
||||
string op = methodname.substr(8);
|
||||
ClassData *classdef = getOrConstructClass(classname);
|
||||
classdef->ops[op] = func;
|
||||
}
|
||||
|
||||
void WrapperRegistry::addConstructor(const string &classname, Constructor func)
|
||||
{
|
||||
ClassData *classdef = getOrConstructClass(classname);
|
||||
classdef->constructor = func;
|
||||
}
|
||||
|
||||
void WrapperRegistry::addParentMethods(ClassData *cur, ClassData *base)
|
||||
{
|
||||
if (base == 0)
|
||||
return;
|
||||
|
||||
for (vector<Method>::iterator it = base->methods.begin(); it != base->methods.end(); ++it)
|
||||
addMethod(cur->cName, it->name, it->func);
|
||||
|
||||
for (map<string, GetSet>::iterator it = base->getset.begin(); it != base->getset.end(); ++it)
|
||||
addGetSet(cur->cName, it->first, it->second.getter, it->second.setter);
|
||||
|
||||
for (map<string, OperatorFunction>::iterator it = base->ops.begin(); it != base->ops.end(); ++it)
|
||||
cur->ops[it->first] = it->second;
|
||||
|
||||
addParentMethods(cur, base->baseclass);
|
||||
}
|
||||
|
||||
void WrapperRegistry::registerBaseclasses()
|
||||
{
|
||||
for (int i = 0; i < (int)mClassList.size(); i++) {
|
||||
string bname = mClassList[i]->baseclassName;
|
||||
if (!bname.empty()) {
|
||||
mClassList[i]->baseclass = lookup(bname);
|
||||
if (!mClassList[i]->baseclass)
|
||||
errMsg("Registering class '" + mClassList[i]->cName + "' : Base class '" + bname +
|
||||
"' not found");
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < (int)mClassList.size(); i++) {
|
||||
addParentMethods(mClassList[i], mClassList[i]->baseclass);
|
||||
}
|
||||
}
|
||||
|
||||
void WrapperRegistry::registerMeta()
|
||||
{
|
||||
for (int i = 0; i < (int)mClassList.size(); i++) {
|
||||
mClassList[i]->getset["_class"] = GetSet("_class", "C class name", (Getter)cbGetClass, 0);
|
||||
mClassList[i]->getset["_cname"] = GetSet("_cname", "Full C name", (Getter)cbGetCName, 0);
|
||||
mClassList[i]->getset["_T"] = GetSet("_T", "C template argument", (Getter)cbGetTemplate, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void WrapperRegistry::registerOperators(ClassData *cls)
|
||||
{
|
||||
PyNumberMethods &num = cls->numInfo;
|
||||
for (map<string, OperatorFunction>::iterator it = cls->ops.begin(); it != cls->ops.end(); it++) {
|
||||
const string &op = it->first;
|
||||
OperatorFunction func = it->second;
|
||||
if (op == "+=")
|
||||
num.nb_inplace_add = func;
|
||||
else if (op == "-=")
|
||||
num.nb_inplace_subtract = func;
|
||||
else if (op == "*=")
|
||||
num.nb_inplace_multiply = func;
|
||||
else if (op == "+")
|
||||
num.nb_add = func;
|
||||
else if (op == "-")
|
||||
num.nb_subtract = func;
|
||||
else if (op == "*")
|
||||
num.nb_multiply = func;
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
else if (op == "/=")
|
||||
num.nb_inplace_divide = func;
|
||||
else if (op == "/")
|
||||
num.nb_divide = func;
|
||||
#else
|
||||
else if (op == "/=")
|
||||
num.nb_inplace_true_divide = func;
|
||||
else if (op == "/")
|
||||
num.nb_true_divide = func;
|
||||
#endif
|
||||
else
|
||||
errMsg("PYTHON operator " + op + " not supported");
|
||||
}
|
||||
}
|
||||
|
||||
void WrapperRegistry::registerDummyTypes()
|
||||
{
|
||||
vector<string> add;
|
||||
for (vector<ClassData *>::iterator it = mClassList.begin(); it != mClassList.end(); ++it) {
|
||||
string cName = (*it)->cName;
|
||||
if (cName.find('<') != string::npos)
|
||||
add.push_back(cName.substr(0, cName.find('<')));
|
||||
}
|
||||
for (int i = 0; i < (int)add.size(); i++)
|
||||
addClass(add[i], add[i], "");
|
||||
}
|
||||
|
||||
ClassData *WrapperRegistry::lookup(const string &name)
|
||||
{
|
||||
for (map<string, ClassData *>::iterator it = mClasses.begin(); it != mClasses.end(); ++it) {
|
||||
if (it->first == name || it->second->cName == name)
|
||||
return it->second;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void WrapperRegistry::cleanup()
|
||||
{
|
||||
for (vector<ClassData *>::iterator it = mClassList.begin(); it != mClassList.end(); ++it) {
|
||||
delete *it;
|
||||
}
|
||||
mClasses.clear();
|
||||
mClassList.clear();
|
||||
}
|
||||
|
||||
WrapperRegistry &WrapperRegistry::instance()
|
||||
{
|
||||
static WrapperRegistry inst;
|
||||
return inst;
|
||||
}
|
||||
|
||||
bool WrapperRegistry::canConvert(ClassData *from, ClassData *to)
|
||||
{
|
||||
if (from == to)
|
||||
return true;
|
||||
if (from->baseclass)
|
||||
return canConvert(from->baseclass, to);
|
||||
return false;
|
||||
}
|
||||
|
||||
void WrapperRegistry::addConstants(PyObject *module)
|
||||
{
|
||||
// expose arguments
|
||||
PyObject *list = PyList_New(args.size());
|
||||
for (int i = 0; i < (int)args.size(); i++)
|
||||
PyList_SET_ITEM(list, i, Manta::toPy(args[i]));
|
||||
PyModule_AddObject(module, "args", list);
|
||||
PyModule_AddObject(module, "SCENEFILE", Manta::toPy(mScriptName));
|
||||
|
||||
// expose compile flags
|
||||
#ifdef DEBUG
|
||||
PyModule_AddObject(module, "DEBUG", Manta::toPy<bool>(true));
|
||||
#else
|
||||
PyModule_AddObject(module, "DEBUG", Manta::toPy<bool>(false));
|
||||
#endif
|
||||
#ifdef MANTA_MT
|
||||
PyModule_AddObject(module, "MT", Manta::toPy<bool>(true));
|
||||
#else
|
||||
PyModule_AddObject(module, "MT", Manta::toPy<bool>(false));
|
||||
#endif
|
||||
#ifdef GUI
|
||||
PyModule_AddObject(module, "GUI", Manta::toPy<bool>(true));
|
||||
#else
|
||||
PyModule_AddObject(module, "GUI", Manta::toPy<bool>(false));
|
||||
#endif
|
||||
#if FLOATINGPOINT_PRECISION == 2
|
||||
PyModule_AddObject(module, "DOUBLEPRECISION", Manta::toPy<bool>(true));
|
||||
#else
|
||||
PyModule_AddObject(module, "DOUBLEPRECISION", Manta::toPy<bool>(false));
|
||||
#endif
|
||||
// cuda off for now
|
||||
PyModule_AddObject(module, "CUDA", Manta::toPy<bool>(false));
|
||||
|
||||
// expose enum entries
|
||||
std::map<std::string, int>::iterator it;
|
||||
for (it = mEnumValues.begin(); it != mEnumValues.end(); it++) {
|
||||
PyModule_AddObject(module, it->first.c_str(), Manta::toPy(it->second));
|
||||
// Alternative would be:
|
||||
// e.g. PyModule_AddIntConstant(module, "FlagFluid", 1);
|
||||
}
|
||||
}
|
||||
|
||||
void WrapperRegistry::runPreInit(PyObject *name_space)
|
||||
{
|
||||
// add python directories to path
|
||||
PyObject *sys_path = PySys_GetObject((char *)"path");
|
||||
for (size_t i = 0; i < mPaths.size(); i++) {
|
||||
PyObject *path = Manta::toPy(mPaths[i]);
|
||||
if (sys_path == nullptr || path == nullptr || PyList_Append(sys_path, path) < 0) {
|
||||
errMsg("unable to set python path");
|
||||
}
|
||||
Py_DECREF(path);
|
||||
}
|
||||
if (!mCode.empty()) {
|
||||
mCode = "from manta import *\n" + mCode;
|
||||
PyObject *return_value = PyRun_String(mCode.c_str(), Py_file_input, name_space, name_space);
|
||||
if (return_value == nullptr) {
|
||||
if (PyErr_Occurred()) {
|
||||
PyErr_Print();
|
||||
}
|
||||
}
|
||||
else {
|
||||
Py_DECREF(return_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PyObject *WrapperRegistry::createPyObject(const string &classname,
|
||||
const string &name,
|
||||
Manta::PbArgs &args,
|
||||
Manta::PbClass *parent)
|
||||
{
|
||||
ClassData *classdef = lookup(classname);
|
||||
if (!classdef)
|
||||
errMsg("Class " + classname + " doesn't exist.");
|
||||
|
||||
// create object
|
||||
PyObject *obj = cbNew(&classdef->typeInfo, nullptr, nullptr);
|
||||
PbObject *self = (PbObject *)obj;
|
||||
PyObject *nkw = 0;
|
||||
|
||||
if (args.kwds())
|
||||
nkw = PyDict_Copy(args.kwds());
|
||||
else
|
||||
nkw = PyDict_New();
|
||||
|
||||
PyObject *nocheck = Py_BuildValue("s", "yes");
|
||||
PyDict_SetItemString(nkw, "nocheck", nocheck);
|
||||
if (parent)
|
||||
PyDict_SetItemString(nkw, "parent", parent->getPyObject());
|
||||
|
||||
// create instance
|
||||
if (self->classdef->constructor(obj, args.linArgs(), nkw) < 0)
|
||||
errMsg("error raised in constructor"); // assume condition is already set
|
||||
|
||||
Py_DECREF(nkw);
|
||||
Py_DECREF(nocheck);
|
||||
self->instance->setName(name);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
// prepare typeinfo and register python module
|
||||
void WrapperRegistry::construct(const bool python_lifecycle,
|
||||
const string &scriptname,
|
||||
const vector<string> &args)
|
||||
{
|
||||
mScriptName = scriptname;
|
||||
this->args = args;
|
||||
|
||||
registerBaseclasses();
|
||||
registerMeta();
|
||||
registerDummyTypes();
|
||||
|
||||
// Don't extend the init-tab when Python is already initialized.
|
||||
// Since Python 3.12 this isn't supported and will crash.
|
||||
//
|
||||
// When `python_lifecycle` is false (when manta-flow is embedded), it's the responsibility
|
||||
// of the application embedding this code to include #PyInit_manta_main in the init-tab.
|
||||
if (python_lifecycle) {
|
||||
// work around for certain gcc versions, cast to char*
|
||||
PyImport_AppendInittab((char *)gDefaultModuleName.c_str(), PyInit_manta_main);
|
||||
}
|
||||
}
|
||||
|
||||
inline PyObject *castPy(PyTypeObject *p)
|
||||
{
|
||||
return reinterpret_cast<PyObject *>(static_cast<void *>(p));
|
||||
}
|
||||
|
||||
PyObject *WrapperRegistry::initModule()
|
||||
{
|
||||
// generate and terminate all method lists
|
||||
PyMethodDef sentinelFunc = {nullptr, nullptr, 0, nullptr};
|
||||
PyGetSetDef sentinelGetSet = {nullptr, nullptr, nullptr, nullptr, nullptr};
|
||||
for (int i = 0; i < (int)mClassList.size(); i++) {
|
||||
ClassData *cls = mClassList[i];
|
||||
cls->genMethods.clear();
|
||||
cls->genGetSet.clear();
|
||||
for (vector<Method>::iterator i2 = cls->methods.begin(); i2 != cls->methods.end(); ++i2)
|
||||
cls->genMethods.push_back(i2->def());
|
||||
for (map<string, GetSet>::iterator i2 = cls->getset.begin(); i2 != cls->getset.end(); ++i2)
|
||||
cls->genGetSet.push_back(i2->second.def());
|
||||
|
||||
cls->genMethods.push_back(sentinelFunc);
|
||||
cls->genGetSet.push_back(sentinelGetSet);
|
||||
}
|
||||
|
||||
// prepare module info
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
static PyModuleDef MainModule = {PyModuleDef_HEAD_INIT,
|
||||
gDefaultModuleName.c_str(),
|
||||
"Bridge module to the C++ solver",
|
||||
-1,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr};
|
||||
// get generic methods (plugin functions)
|
||||
MainModule.m_methods = &mClasses["__modclass__"]->genMethods[0];
|
||||
|
||||
// create module
|
||||
PyObject *module = PyModule_Create(&MainModule);
|
||||
#else
|
||||
PyObject *module = Py_InitModule(gDefaultModuleName.c_str(),
|
||||
&mClasses["__modclass__"]->genMethods[0]);
|
||||
#endif
|
||||
if (module == nullptr)
|
||||
return nullptr;
|
||||
|
||||
// load classes
|
||||
for (vector<ClassData *>::iterator it = mClassList.begin(); it != mClassList.end(); ++it) {
|
||||
ClassData &data = **it;
|
||||
char *nameptr = (char *)data.pyName.c_str();
|
||||
|
||||
// define numeric substruct
|
||||
PyNumberMethods *num = 0;
|
||||
if (!data.ops.empty()) {
|
||||
num = &data.numInfo;
|
||||
memset(num, 0, sizeof(PyNumberMethods));
|
||||
registerOperators(&data);
|
||||
}
|
||||
|
||||
// define python classinfo
|
||||
PyTypeObject t = {
|
||||
PyVarObject_HEAD_INIT(nullptr, 0)(char *) data.pyName.c_str(), // tp_name
|
||||
sizeof(PbObject), // tp_basicsize
|
||||
0, // tp_itemsize
|
||||
(destructor)cbDealloc, // tp_dealloc
|
||||
0, // tp_print
|
||||
0, // tp_getattr
|
||||
0, // tp_setattr
|
||||
0, // tp_reserved
|
||||
0, // tp_repr
|
||||
num, // tp_as_number
|
||||
0, // tp_as_sequence
|
||||
0, // tp_as_mapping
|
||||
0, // tp_hash
|
||||
0, // tp_call
|
||||
0, // tp_str
|
||||
0, // tp_getattro
|
||||
0, // tp_setattro
|
||||
0, // tp_as_buffer
|
||||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, // tp_flags
|
||||
nameptr, // tp_doc
|
||||
0, // tp_traverse
|
||||
0, // tp_clear
|
||||
0, // tp_richcompare
|
||||
0, // tp_weaklistoffset
|
||||
0, // tp_iter
|
||||
0, // tp_iternext
|
||||
&data.genMethods[0], // tp_methods
|
||||
0, // tp_members
|
||||
&data.genGetSet[0], // tp_getset
|
||||
0, // tp_base
|
||||
0, // tp_dict
|
||||
0, // tp_descr_get
|
||||
0, // tp_descr_set
|
||||
0, // tp_dictoffset
|
||||
(initproc)(data.constructor), // tp_init
|
||||
0, // tp_alloc
|
||||
cbNew // tp_new
|
||||
};
|
||||
data.typeInfo = t;
|
||||
|
||||
if (PyType_Ready(&data.typeInfo) < 0)
|
||||
continue;
|
||||
|
||||
for (map<string, ClassData *>::iterator i2 = mClasses.begin(); i2 != mClasses.end(); ++i2) {
|
||||
if (*it != i2->second)
|
||||
continue;
|
||||
// register all aliases
|
||||
Py_INCREF(castPy(&data.typeInfo));
|
||||
PyModule_AddObject(module, (char *)i2->first.c_str(), (PyObject *)&data.typeInfo);
|
||||
}
|
||||
}
|
||||
|
||||
// externals
|
||||
for (vector<InitFunc>::iterator it = mExtInitializers.begin(); it != mExtInitializers.end();
|
||||
++it) {
|
||||
(*it)(module);
|
||||
}
|
||||
|
||||
addConstants(module);
|
||||
|
||||
return module;
|
||||
}
|
||||
|
||||
//******************************************************
|
||||
// Register members and exposed functions
|
||||
|
||||
void setup(const bool python_lifecycle,
|
||||
const std::string &filename,
|
||||
const std::vector<std::string> &args,
|
||||
PyObject *name_space)
|
||||
{
|
||||
WrapperRegistry::instance().construct(python_lifecycle, filename, args);
|
||||
if (python_lifecycle) {
|
||||
Py_Initialize();
|
||||
}
|
||||
WrapperRegistry::instance().runPreInit(name_space);
|
||||
}
|
||||
|
||||
void finalize(const bool python_lifecycle)
|
||||
{
|
||||
if (python_lifecycle) {
|
||||
Py_Finalize();
|
||||
}
|
||||
WrapperRegistry::instance().cleanup();
|
||||
}
|
||||
|
||||
bool canConvert(PyObject *obj, const string &classname)
|
||||
{
|
||||
ClassData *from = ((PbObject *)obj)->classdef;
|
||||
ClassData *dest = WrapperRegistry::instance().lookup(classname);
|
||||
if (!dest)
|
||||
errMsg("Classname '" + classname + "' is not registered.");
|
||||
return WrapperRegistry::instance().canConvert(from, dest);
|
||||
}
|
||||
|
||||
Manta::PbClass *objFromPy(PyObject *obj)
|
||||
{
|
||||
if (Py_TYPE(obj)->tp_dealloc != (destructor)cbDealloc) // not a manta object
|
||||
return nullptr;
|
||||
|
||||
return ((PbObject *)obj)->instance;
|
||||
}
|
||||
|
||||
PyObject *copyObject(Manta::PbClass *cls, const string &classname)
|
||||
{
|
||||
ClassData *classdef = WrapperRegistry::instance().lookup(classname);
|
||||
assertMsg(classdef, "python class " + classname + " does not exist.");
|
||||
|
||||
// allocate new object
|
||||
PbObject *obj = (PbObject *)classdef->typeInfo.tp_alloc(&(classdef->typeInfo), 0);
|
||||
assertMsg(obj, "cannot allocate new python object");
|
||||
|
||||
obj->classdef = classdef;
|
||||
cls->registerObject((PyObject *)obj, 0);
|
||||
|
||||
return cls->getPyObject();
|
||||
}
|
||||
|
||||
Manta::PbClass *createPy(const std::string &classname,
|
||||
const std::string &name,
|
||||
Manta::PbArgs &args,
|
||||
Manta::PbClass *parent)
|
||||
{
|
||||
PyObject *obj = WrapperRegistry::instance().createPyObject(classname, name, args, parent);
|
||||
return ((PbObject *)obj)->instance;
|
||||
}
|
||||
|
||||
void setReference(Manta::PbClass *cls, PyObject *obj)
|
||||
{
|
||||
((PbObject *)obj)->instance = cls;
|
||||
}
|
||||
|
||||
Register::Register(const string &className, const string &funcName, GenericFunction func)
|
||||
{
|
||||
WrapperRegistry::instance().addMethod(className, funcName, func);
|
||||
}
|
||||
Register::Register(const string &className, const string &funcName, OperatorFunction func)
|
||||
{
|
||||
WrapperRegistry::instance().addOperator(className, funcName, func);
|
||||
}
|
||||
Register::Register(const string &className, const string &funcName, Constructor func)
|
||||
{
|
||||
WrapperRegistry::instance().addConstructor(className, func);
|
||||
}
|
||||
Register::Register(const string &className, const string &property, Getter getter, Setter setter)
|
||||
{
|
||||
WrapperRegistry::instance().addGetSet(className, property, getter, setter);
|
||||
}
|
||||
Register::Register(const string &className, const string &pyName, const string &baseClass)
|
||||
{
|
||||
WrapperRegistry::instance().addClass(pyName, className, baseClass);
|
||||
}
|
||||
Register::Register(const string &name, const int value)
|
||||
{
|
||||
WrapperRegistry::instance().addEnumEntry(name, value);
|
||||
}
|
||||
Register::Register(const string &file, const string &pythonCode)
|
||||
{
|
||||
WrapperRegistry::instance().addPythonCode(file, pythonCode);
|
||||
}
|
||||
Register::Register(InitFunc func)
|
||||
{
|
||||
WrapperRegistry::instance().addExternalInitializer(func);
|
||||
}
|
||||
|
||||
} // namespace Pb
|
||||
109
blender-5.2.0/extern/mantaflow/helper/pwrapper/registry.h
vendored
Normal file
109
blender-5.2.0/extern/mantaflow/helper/pwrapper/registry.h
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* MantaFlow fluid solver framework
|
||||
* Copyright 2011-2014 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
|
||||
*
|
||||
* Auto python registry
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef _REGISTRY_H
|
||||
#define _REGISTRY_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
// forward declaration to minimize Python.h includes
|
||||
#ifndef PyObject_HEAD
|
||||
# ifndef PyObject_Fake
|
||||
struct _object;
|
||||
typedef _object PyObject;
|
||||
# define PyObject_Fake
|
||||
# endif
|
||||
#endif
|
||||
|
||||
namespace Manta {
|
||||
class PbClass;
|
||||
class PbArgs;
|
||||
} // namespace Manta
|
||||
|
||||
// **************************************************
|
||||
// NOTE
|
||||
// Everything in this file is intend only for internal
|
||||
// use by the generated wrappers or pclass/pconvert.
|
||||
// For user code, use the functionality exposed in
|
||||
// pclass.h / pconvert.h instead.
|
||||
// **************************************************
|
||||
|
||||
// Used to turn names into strings
|
||||
namespace Manta {
|
||||
template<class T> struct Namify {
|
||||
static const char *S;
|
||||
};
|
||||
} // namespace Manta
|
||||
namespace Pb {
|
||||
|
||||
// internal registry access
|
||||
void setup(bool python_lifecycle,
|
||||
const std::string &filename,
|
||||
const std::vector<std::string> &args,
|
||||
PyObject *name_space);
|
||||
void finalize(bool python_lifecycle);
|
||||
bool canConvert(PyObject *obj, const std::string &to);
|
||||
Manta::PbClass *objFromPy(PyObject *obj);
|
||||
Manta::PbClass *createPy(const std::string &classname,
|
||||
const std::string &name,
|
||||
Manta::PbArgs &args,
|
||||
Manta::PbClass *parent);
|
||||
void setReference(Manta::PbClass *cls, PyObject *obj);
|
||||
PyObject *copyObject(Manta::PbClass *cls, const std::string &classname);
|
||||
void MantaEnsureRegistration();
|
||||
|
||||
#ifdef BLENDER
|
||||
# ifdef PyMODINIT_FUNC
|
||||
PyMODINIT_FUNC PyInit_manta_main(void);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// callback type
|
||||
typedef void (*InitFunc)(PyObject *);
|
||||
typedef PyObject *(*GenericFunction)(PyObject *self, PyObject *args, PyObject *kwds);
|
||||
typedef PyObject *(*OperatorFunction)(PyObject *self, PyObject *o);
|
||||
typedef int (*Constructor)(PyObject *self, PyObject *args, PyObject *kwds);
|
||||
typedef PyObject *(*Getter)(PyObject *self, void *closure);
|
||||
typedef int (*Setter)(PyObject *self, PyObject *value, void *closure);
|
||||
|
||||
//! Auto registry of python methods and classes
|
||||
struct Register {
|
||||
//! register method
|
||||
Register(const std::string &className, const std::string &funcName, GenericFunction func);
|
||||
//! register operator
|
||||
Register(const std::string &className, const std::string &funcName, OperatorFunction func);
|
||||
//! register constructor
|
||||
Register(const std::string &className, const std::string &funcName, Constructor func);
|
||||
//! register getter/setter
|
||||
Register(const std::string &className,
|
||||
const std::string &property,
|
||||
Getter getter,
|
||||
Setter setter);
|
||||
//! register class
|
||||
Register(const std::string &className, const std::string &pyName, const std::string &baseClass);
|
||||
//! register enum entry
|
||||
Register(const std::string &name, const int value);
|
||||
//! register python code
|
||||
Register(const std::string &file, const std::string &pythonCode);
|
||||
//! register external code
|
||||
Register(InitFunc func);
|
||||
};
|
||||
|
||||
#define KEEP_UNUSED(var) \
|
||||
do { \
|
||||
(void)var; \
|
||||
} while (false);
|
||||
|
||||
} // namespace Pb
|
||||
#endif
|
||||
Reference in New Issue
Block a user