55inline bool IsTemplatedSTLClass(
const std::string&
name,
const std::string& klass) {
57 auto pos =
name.find(klass);
58 return (pos == 0 || pos == 5) &&
name.find(
"::",
name.rfind(
">")) == std::string::npos;
66 PyObject* result = PyObject_CallMethod(obj,
const_cast<char*
>(meth),
const_cast<char*
>(
""));
76 PyObject* result = PyObject_CallMethod(
77 obj,
const_cast<char*
>(meth),
const_cast<char*
>(
"O"), arg1);
91 if (idx >=
size || (idx < 0 && idx < -
size)) {
92 PyErr_SetString(PyExc_IndexError,
"index out of range");
101 pyindex = PyLong_FromSsize_t(
size+idx);
110 if ((step > 0 && stop <= start) || (step < 0 && start <= stop))
113 if (start < 0) start = 0;
114 if (start >= nlen) start = nlen-1;
115 if (step >= nlen) step = nlen;
117 stop = step > 0 ? std::min(nlen, stop) : (stop >= 0 ? stop : -1);
132 PyObject* result = PyObject_CallMethodObjArgs((
PyObject*)self, pymeth, pyindex,
nullptr);
152 PyErr_SetString(PyExc_TypeError,
"getattr(): attribute name must be string");
160 PyObject* val1 = PyObject_Str(self);
162 PyErr_Format(PyExc_AttributeError,
"%s has no attribute \'%s\'",
182 PyErr_SetString(PyExc_TypeError,
"getattr(): attribute name must be string");
195#if PY_VERSION_HEX < 0x03040000
196#define PyObject_LengthHint _PyObject_LengthHint
201 ItemGetter(
PyObject* pyobj) : fPyObject(pyobj) { Py_INCREF(fPyObject); }
202 virtual ~ItemGetter() { Py_DECREF(fPyObject); }
208struct CountedItemGetter :
public ItemGetter {
209 CountedItemGetter(
PyObject* pyobj) : ItemGetter(pyobj), fCur(0) {}
213struct TupleItemGetter :
public CountedItemGetter {
214 using CountedItemGetter::CountedItemGetter;
217 if (fCur < PyTuple_GET_SIZE(fPyObject)) {
218 PyObject* item = PyTuple_GET_ITEM(fPyObject, fCur++);
222 PyErr_SetString(PyExc_StopIteration,
"end of tuple");
227struct ListItemGetter :
public CountedItemGetter {
228 using CountedItemGetter::CountedItemGetter;
231 if (fCur < PyList_GET_SIZE(fPyObject)) {
232 PyObject* item = PyList_GET_ITEM(fPyObject, fCur++);
236 PyErr_SetString(PyExc_StopIteration,
"end of list");
241struct SequenceItemGetter :
public CountedItemGetter {
242 using CountedItemGetter::CountedItemGetter;
251 virtual PyObject* get() {
return PySequence_GetItem(fPyObject, fCur++); }
254struct IterItemGetter :
public ItemGetter {
255 using ItemGetter::ItemGetter;
257 virtual PyObject* get() {
return (*(
Py_TYPE(fPyObject)->tp_iternext))(fPyObject); }
268 ItemGetter* getter =
nullptr;
269 if (PyTuple_GET_SIZE(args) == 1) {
270 PyObject* fi = PyTuple_GET_ITEM(args, 0);
272 PyErr_SetString(PyExc_TypeError,
"can not convert string to vector");
278 if (!PyObject_CheckBuffer(fi)) {
279 if (PyTuple_CheckExact(fi))
280 getter =
new TupleItemGetter(fi);
281 else if (PyList_CheckExact(fi))
282 getter =
new ListItemGetter(fi);
283 else if (PySequence_Check(fi))
284 getter =
new SequenceItemGetter(fi);
286 PyObject* iter = PyObject_GetIter(fi);
288 getter =
new IterItemGetter{iter};
299 PyObject* result = PyObject_CallMethodObjArgs(self, mname,
nullptr);
314 PyObject* res = PyObject_CallMethod(self, (
char*)
"reserve", (
char*)
"n", sz);
325 PyObject* fi = PySequence_GetItem(PyTuple_GET_ITEM(args, 0), 0);
326 if (!fi) PyErr_Clear();
327 if (fi && (PyTuple_CheckExact(fi) || PyList_CheckExact(fi))) {
329 PyObject* eb_call = PyObject_GetAttrString(self, (
char*)
"emplace_back");
331 bool value_is_vector =
false;
335 value_is_vector =
true;
342 for (
int i = 0; ; ++i) {
345 if (value_is_vector && PySequence_Check(item)) {
346 eb_args = PyTuple_New(1);
347 PyTuple_SET_ITEM(eb_args, 0, item);
348 }
else if (PyTuple_CheckExact(item)) {
350 }
else if (PyList_CheckExact(item)) {
352 eb_args = PyTuple_New(isz);
354 PyObject* iarg = PyList_GET_ITEM(item, j);
356 PyTuple_SET_ITEM(eb_args, j, iarg);
361 PyErr_Format(PyExc_TypeError,
"argument %d is not a tuple or list", i);
365 PyObject* ebres = PyObject_CallObject(eb_call, eb_args);
373 if (PyErr_Occurred()) {
374 if (!(PyErr_ExceptionMatches(PyExc_IndexError) ||
375 PyErr_ExceptionMatches(PyExc_StopIteration)))
377 else { PyErr_Clear(); }
386 PyObject* pb_call = PyObject_GetAttrString(self, (
char*)
"push_back");
391 PyObject* pbres = PyObject_CallFunctionObjArgs(pb_call, item,
nullptr);
399 if (PyErr_Occurred()) {
400 if (!(PyErr_ExceptionMatches(PyExc_IndexError) ||
401 PyErr_ExceptionMatches(PyExc_StopIteration)))
403 else { PyErr_Clear(); }
423 PyObject* realInit = PyObject_GetAttrString(self,
"__real_init");
425 PyObject* result = PyObject_Call(realInit, args,
nullptr);
445 long clen = PyInt_AsLong(pylen);
450 bi.len = clen * bi.itemsize;
451 if (bi.ndim == 1 && bi.shape)
461 if (!vi)
return nullptr;
465 vi->
vi_flags =
v->ob_refcnt <= 2 ? 1 : 0;
471 if (pyvalue_type && pyvalue_size) {
483 vi->
vi_stride = PyLong_AsLong(pyvalue_size);
491 Py_XDECREF(pyvalue_size);
492 Py_XDECREF(pyvalue_type);
495 vi->
ii_len = PySequence_Size(
v);
497 PyObject_GC_Track(vi);
504 if (PySlice_Check(index)) {
506 PyErr_SetString(PyExc_TypeError,
"unsubscriptable object");
511 PyObject* nseq = PyObject_CallObject(pyclass,
nullptr);
517 if (!AdjustSlice(nlen, start, stop, step))
521 for (
Py_ssize_t i = start; i*sign < stop*sign; i += step) {
543 PyErr_Format(PyExc_TypeError,
544 "require object of type std::vector<bool>, but %s given",
550 PyErr_SetString(PyExc_TypeError,
"unsubscriptable object");
554 if (PySlice_Check(idx)) {
556 PyObject* nseq = PyObject_CallObject(pyclass,
nullptr);
561 if (!AdjustSlice(nlen, start, stop, step))
565 for (
Py_ssize_t i = start; i*sign < stop*sign; i += step) {
580 int index = (
int)PyLong_AsLong(pyindex);
584 std::vector<bool>* vb = (std::vector<bool>*)self->
GetObject();
587 if (
bool((*vb)[index]))
597 PyErr_Format(PyExc_TypeError,
598 "require object of type std::vector<bool>, but %s given",
604 PyErr_SetString(PyExc_TypeError,
"unsubscriptable object");
608 int bval = 0;
PyObject* idx =
nullptr;
609 if (!PyArg_ParseTuple(args,
const_cast<char*
>(
"Oi:__setitem__"), &idx, &bval))
616 int index = (
int)PyLong_AsLong(pyindex);
620 std::vector<bool>* vb = (std::vector<bool>*)self->
GetObject();
623 (*vb)[index] = (
bool)bval;
638 if (!PyObject_RichCompareBool(iter, end, Py_EQ)) {
658static const ptrdiff_t PS_END_ADDR = 7;
659static const ptrdiff_t PS_FLAG_ADDR = 11;
660static const ptrdiff_t PS_COLL_ADDR = 13;
672 auto& dmc = ((
CPPInstance*)iter)->GetDatamemberCache();
673 dmc.push_back(std::make_pair(PS_END_ADDR, end));
677 dmc.push_back(std::make_pair(PS_FLAG_ADDR, Py_False));
681 dmc.push_back(std::make_pair(PS_COLL_ADDR, self));
696 if (!ii)
return nullptr;
701 ii->
ii_len = PySequence_Size(
c);
703 PyObject_GC_Track(ii);
740 long idx = PyLong_AsLong(pyindex);
741 if (idx == -1 && PyErr_Occurred())
745 PyErr_SetString(PyExc_TypeError,
"unsubscriptable object");
751 else if ((
int)idx == 1)
755 PyErr_SetString(PyExc_IndexError,
"out of bounds");
769 PyObject* realInit = PyObject_GetAttrString(self,
"__real_init");
771 PyObject* result = PyObject_Call(realInit, args,
nullptr);
773 if (result && PyTuple_GET_SIZE(args) == 1 &&
CPPInstance_Check(PyTuple_GET_ITEM(args, 0)))
774 PyObject_SetAttrString(PyTuple_GET_ITEM(args, 0),
"__python_owns__", Py_False);
782#if PY_VERSION_HEX >= 0x03000000
785 return !PyObject_RichCompareBool(one, other, Py_EQ);
788static inline PyObject* CPyCppyy_PyString_FromCppString(std::string* s) {
792static inline PyObject* CPyCppyy_PyString_FromCppString(std::wstring* s) {
793 return PyUnicode_FromWideChar(s->c_str(), s->size());
796#define CPPYY_IMPL_STRING_PYTHONIZATION(type, name) \
797static PyObject* name##StringGetData(PyObject* self) \
799 if (CPyCppyy::CPPInstance_Check(self)) { \
800 type* obj = ((type*)((CPPInstance*)self)->GetObject()); \
802 return CPyCppyy_PyString_FromCppString(obj); \
804 return CPPInstance_Type.tp_str(self); \
807 PyErr_Format(PyExc_TypeError, "object mismatch (%s expected)", #type); \
811PyObject* name##StringRepr(PyObject* self) \
813 PyObject* data = name##StringGetData(self); \
815 PyObject* repr = PyObject_Repr(data); \
822PyObject* name##StringIsEqual(PyObject* self, PyObject* obj) \
824 PyObject* data = name##StringGetData(self); \
826 PyObject* result = PyObject_RichCompare(data, obj, Py_EQ); \
833PyObject* name##StringIsNotEqual(PyObject* self, PyObject* obj) \
835 PyObject* data = name##StringGetData(self); \
837 PyObject* result = PyObject_RichCompare(data, obj, Py_NE); \
845#define CPPYY_IMPL_STRING_PYTHONIZATION_CMP(type, name) \
846CPPYY_IMPL_STRING_PYTHONIZATION(type, name) \
847PyObject* name##StringCompare(PyObject* self, PyObject* obj) \
849 PyObject* data = name##StringGetData(self); \
852 result = PyObject_Compare(data, obj); \
855 if (PyErr_Occurred()) \
857 return PyInt_FromLong(result); \
867 PyObject* data = StlStringGetData(self);
878 bool mustIncrement =
true;
881 auto& dmc = ((
CPPInstance*)self)->GetDatamemberCache();
883 if (p.first == PS_END_ADDR) {
886 }
else if (p.first == PS_FLAG_ADDR) {
887 mustIncrement = p.second == Py_True;
888 if (!mustIncrement) {
900 if (!PyObject_RichCompareBool(last, self, Py_EQ)) {
901 bool iter_valid =
true;
911 iter_valid = iter && PyObject_RichCompareBool(last, self, Py_NE);
917 if (!next) PyErr_Clear();
923 if (!next) PyErr_SetString(PyExc_StopIteration,
"");
929#define COMPLEX_METH_GETSET(name, cppname) \
930static PyObject* name##ComplexGet(PyObject* self, void*) { \
931 return PyObject_CallMethodObjArgs(self, cppname, nullptr); \
933static int name##ComplexSet(PyObject* self, PyObject* value, void*) { \
934 PyObject* result = PyObject_CallMethodObjArgs(self, cppname, value, nullptr);\
941PyGetSetDef name##Complex{(char*)#name, (getter)name##ComplexGet, (setter)name##ComplexSet, nullptr, nullptr};
948 if (!real)
return nullptr;
951 if (
r == -1. && PyErr_Occurred())
955 if (!imag)
return nullptr;
958 if (i == -1. && PyErr_Occurred())
961 return PyComplex_FromDoubles(
r, i);
966 if (!real)
return nullptr;
969 if (
r == -1. && PyErr_Occurred())
973 if (!imag)
return nullptr;
976 if (i == -1. && PyErr_Occurred())
979 std::ostringstream s;
980 s <<
'(' <<
r <<
'+' << i <<
"j)";
992 if (
d == -1.0 && PyErr_Occurred())
994 ((std::complex<double>*)self->
GetObject())->real(
d);
998PyGetSetDef ComplexDReal{(
char*)
"real", (getter)ComplexDRealGet, (setter)ComplexDRealSet,
nullptr,
nullptr};
1009 if (
d == -1.0 && PyErr_Occurred())
1011 ((std::complex<double>*)self->
GetObject())->imag(
d);
1015PyGetSetDef ComplexDImag{(
char*)
"imag", (getter)ComplexDImagGet, (setter)ComplexDImagSet,
nullptr,
nullptr};
1019 double r = ((std::complex<double>*)self->
GetObject())->real();
1020 double i = ((std::complex<double>*)self->
GetObject())->imag();
1021 return PyComplex_FromDoubles(
r, i);
1057 if (!IsTemplatedSTLClass(
name,
"vector") &&
1058 !((PyTypeObject*)pyclass)->tp_iter) {
1068 if (resname.find(
"iterator") == std::string::npos)
1072 ((PyTypeObject*)pyclass)->tp_iter = (getiterfunc)StlSequenceIter;
1077 if (!((PyTypeObject*)pyclass)->tp_iter &&
1083 ((PyTypeObject*)pyclass)->tp_iter = (getiterfunc)index_iter;
1125 if (IsTemplatedSTLClass(
name,
"vector")) {
1129 if (klass->
fCppType == sVectorBoolTypeID) {
1135 Utility::AddToClass(pyclass,
"__init__", (PyCFunction)VectorInit, METH_VARARGS | METH_KEYWORDS);
1148 ((PyTypeObject*)pyclass)->tp_iter = (getiterfunc)vector_iter;
1154 PyObject* pyvalue_size = PyLong_FromSsize_t(typesz);
1155 PyObject_SetAttrString(pyclass,
"value_size", pyvalue_size);
1156 Py_DECREF(pyvalue_size);
1159 PyObject_SetAttrString(pyclass,
"value_type", pyvalue_type);
1160 Py_DECREF(pyvalue_type);
1165 else if (IsTemplatedSTLClass(
name,
"map")) {
1169 else if (IsTemplatedSTLClass(
name,
"pair")) {
1174 if (IsTemplatedSTLClass(
name,
"shared_ptr")) {
1176 Utility::AddToClass(pyclass,
"__init__", (PyCFunction)SharedPtrInit, METH_VARARGS | METH_KEYWORDS);
1180 ((PyTypeObject*)pyclass)->tp_iternext = (iternextfunc)StlIterNext;
1182 ((PyTypeObject*)pyclass)->tp_iter = (getiterfunc)PyObject_SelfIter;
1186 else if (
name ==
"string" ||
name ==
"std::string") {
1192 ((PyTypeObject*)pyclass)->tp_hash = (hashfunc)StlStringHash;
1195 else if (
name ==
"basic_string<wchar_t,char_traits<wchar_t>,allocator<wchar_t> >" || \
1196 name ==
"std::basic_string<wchar_t,char_traits<wchar_t>,allocator<wchar_t> >") {
1204 else if (
name ==
"complex<double>" ||
name ==
"std::complex<double>") {
1206 PyObject_SetAttrString(pyclass,
"real", PyDescr_NewGetSet((PyTypeObject*)pyclass, &ComplexDReal));
1208 PyObject_SetAttrString(pyclass,
"imag", PyDescr_NewGetSet((PyTypeObject*)pyclass, &ComplexDImag));
1213 else if (IsTemplatedSTLClass(
name,
"complex")) {
1215 PyObject_SetAttrString(pyclass,
"real", PyDescr_NewGetSet((PyTypeObject*)pyclass, &realComplex));
1217 PyObject_SetAttrString(pyclass,
"imag", PyDescr_NewGetSet((PyTypeObject*)pyclass, &imagComplex));
1225 bool bUserOk =
true;
PyObject* res =
nullptr;
1229 bUserOk = (
bool)res;
1233 res = PyObject_CallFunctionObjArgs(func, pyclass,
pyname,
nullptr);
1235 bUserOk = (
bool)res;
1250 PyTuple_SET_ITEM(args, 0, pyclass);
1254 bool pstatus =
true;
1258 PyTuple_SET_ITEM(args, 1,
pyname);
1261 name.substr(outer_scope.size()+2, std::string::npos).c_str()));
1266 for (
auto pythonizor : p->second) {
1267 PyObject* result = PyObject_CallObject(pythonizor, args);
#define PyInt_FromSsize_t
#define CPyCppyy_PyText_FromStringAndSize
#define CPyCppyy_PySliceCast
#define CPyCppyy_PyText_AsString
#define CPyCppyy_PyText_Type
#define CPyCppyy_PyText_FromString
#define CPyCppyy_PyText_Check
#define CPPYY_IMPL_STRING_PYTHONIZATION_CMP(type, name)
#define COMPLEX_METH_GETSET(name, cppname)
#define PyObject_LengthHint
PyObject * CallPyObjMethod(PyObject *obj, const char *meth)
Set of helper functions that are invoked from the C++ implementation of pythonizations.
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
static PyObject * PyStyleIndex(PyObject *self, PyObject *index)
Cppyy::TCppType_t ObjectIsA(bool check_smart=true) const
Utility::PyOperators * fOperators
Cppyy::TCppType_t fCppType
std::string extract_namespace(const std::string &name)
Py_ssize_t GetBuffer(PyObject *pyobject, char tc, int size, void *&buf, bool check=true)
bool AddToClass(PyObject *pyclass, const char *label, PyCFunction cfunc, int flags=METH_VARARGS)
Set of helper functions that are invoked from the pythonizors, on the Python side.
PyTypeObject VectorIter_Type
bool Pythonize(PyObject *pyclass, const std::string &name)
bool CPPOverload_Check(T *object)
std::map< std::string, std::vector< PyObject * > > gPythonizations
bool LowLevelView_Check(T *object)
bool CPPInstance_Check(T *object)
PyTypeObject IndexIter_Type
R__EXTERN PyObject * gThisModule
std::set< std::string > gIteratorTypes
CPYCPPYY_EXTERN Converter * CreateConverter(const std::string &name, Py_ssize_t *dims=nullptr)
RPY_EXPORTED std::vector< TCppIndex_t > GetMethodIndicesFromName(TCppScope_t scope, const std::string &name)
RPY_EXPORTED TCppMethod_t GetMethod(TCppScope_t scope, TCppIndex_t imeth)
RPY_EXPORTED std::string ResolveName(const std::string &cppitem_name)
RPY_EXPORTED size_t SizeOf(TCppType_t klass)
RPY_EXPORTED std::string GetScopedFinalName(TCppType_t type)
RPY_EXPORTED bool IsSmartPtr(TCppType_t type)
RPY_EXPORTED TCppScope_t GetScope(const std::string &scope_name)
RPY_EXPORTED std::string GetMethodResultType(TCppMethod_t)
PyObject_HEAD PyObject * ii_container
Cppyy::TCppType_t vi_klass
CPyCppyy::Converter * vi_converter