38bool HasAttrDirect(
PyObject* pyclass,
PyObject* pyname,
bool mustBeCPyCppyy =
false) {
43 PyObject* attr = PyObject_GetItem(dct, pyname);
58 PyObject *mro = ((PyTypeObject *)pyclass)->tp_mro;
59 if (mro && PyTuple_Check(mro)) {
60 for (
Py_ssize_t i = 1; i < PyTuple_GET_SIZE(mro); ++i) {
61 if (HasAttrDirect(PyTuple_GET_ITEM(mro, i), pyname,
true))
72 PyObject* attr = PyObject_GetItem(dct, pyname);
80inline bool IsTemplatedSTLClass(
const std::string&
name,
const std::string& klass) {
83 return (pos == 0 || pos == 5) &&
name.find(
"::",
name.rfind(
">")) == std::string::npos;
91 PyObject* result = PyObject_CallMethod(obj,
const_cast<char*
>(meth),
const_cast<char*
>(
""));
101 PyObject* result = PyObject_CallMethod(
102 obj,
const_cast<char*
>(meth),
const_cast<char*
>(
"O"), arg1);
112 if (idx == (
Py_ssize_t)-1 && PyErr_Occurred())
116 if (idx >=
size || (idx < 0 && idx < -
size)) {
117 PyErr_SetString(PyExc_IndexError,
"index out of range");
126 pyindex = PyLong_FromSsize_t(
size+idx);
135 if ((step > 0 && stop <=
start) || (step < 0 &&
start <= stop))
140 if (step >= nlen) step = nlen;
142 stop = step > 0 ? std::min(nlen, stop) : (stop >= 0 ? stop : -1);
167 PyErr_SetString(PyExc_TypeError,
"getattr(): attribute name must be string");
177 PyErr_Format(PyExc_AttributeError,
"%s object has no attribute \'%s\'",
219 PyErr_SetString(PyExc_TypeError,
"C++ object proxy expected");
230#if PY_VERSION_HEX < 0x03040000
231#define PyObject_LengthHint _PyObject_LengthHint
236 ItemGetter(
PyObject* pyobj) : fPyObject(pyobj) { Py_INCREF(fPyObject); }
237 virtual ~ItemGetter() { Py_DECREF(fPyObject); }
243struct CountedItemGetter :
public ItemGetter {
244 CountedItemGetter(
PyObject* pyobj) : ItemGetter(pyobj), fCur(0) {}
248struct TupleItemGetter :
public CountedItemGetter {
249 using CountedItemGetter::CountedItemGetter;
250 Py_ssize_t size()
override {
return PyTuple_GET_SIZE(fPyObject); }
252 if (fCur < PyTuple_GET_SIZE(fPyObject)) {
253 PyObject* item = PyTuple_GET_ITEM(fPyObject, fCur++);
257 PyErr_SetString(PyExc_StopIteration,
"end of tuple");
262struct ListItemGetter :
public CountedItemGetter {
263 using CountedItemGetter::CountedItemGetter;
266 if (fCur < PyList_GET_SIZE(fPyObject)) {
267 PyObject* item = PyList_GET_ITEM(fPyObject, fCur++);
271 PyErr_SetString(PyExc_StopIteration,
"end of list");
276struct SequenceItemGetter :
public CountedItemGetter {
277 using CountedItemGetter::CountedItemGetter;
286 PyObject*
get()
override {
return PySequence_GetItem(fPyObject, fCur++); }
289struct IterItemGetter :
public ItemGetter {
290 using ItemGetter::ItemGetter;
295static ItemGetter* GetGetter(
PyObject* args)
298 ItemGetter* getter =
nullptr;
300 if (PyTuple_GET_SIZE(args) == 1) {
301 PyObject* fi = PyTuple_GET_ITEM(args, 0);
308 if (PyObject_CheckBuffer(fi))
311 if (PyTuple_CheckExact(fi))
312 getter =
new TupleItemGetter(fi);
313 else if (PyList_CheckExact(fi))
314 getter =
new ListItemGetter(fi);
315 else if (PySequence_Check(fi))
316 getter =
new SequenceItemGetter(fi);
318 PyObject* iter = PyObject_GetIter(fi);
320 getter =
new IterItemGetter{iter};
332void compileSpanHelpers()
334 static bool compiled =
false;
342namespace __cppyy_internal {
349 ptr_iterator(T *c, T *e) : cur(c), end(e) {}
351 T &operator*() const { return *cur; }
352 ptr_iterator &operator++()
357 bool operator==(const ptr_iterator &other) const { return cur == other.cur; }
358 bool operator!=(const ptr_iterator &other) const { return !(*this == other); }
362ptr_iterator<T> make_iter(T *begin, T *end)
367} // namespace __cppyy_internal
369// Note: for const span<T>, T is const-qualified here
371auto __cppyy_internal_begin(T &s) noexcept
373 return __cppyy_internal::make_iter(s.data(), s.data() + s.size());
376// Note: for const span<T>, T is const-qualified here
378auto __cppyy_internal_end(T &s) noexcept
380 // end iterator = begin iterator with cur == end
381 return __cppyy_internal::make_iter(s.data() + s.size(), s.data() + s.size());
391 compileSpanHelpers();
393 pyFunc = PyObject_GetAttrString(py_ns,
"__cppyy_internal_begin");
395 PyErr_Format(PyExc_RuntimeError,
"cppyy internal error: failed to locate helper "
396 "'__cppyy_internal_begin' for std::span pythonization");
406 compileSpanHelpers();
408 pyFunc = PyObject_GetAttrString(py_ns,
"__cppyy_internal_end");
410 PyErr_Format(PyExc_RuntimeError,
"cppyy internal error: failed to locate helper "
411 "'__cppyy_internal_end' for std::span pythonization");
421 auto begin = spanBegin();
424 return PyObject_CallOneArg(begin, self);
429 auto end = spanEnd();
432 return PyObject_CallOneArg(end, self);
443 PyObject* res = PyObject_CallMethod(vecin, (
char*)
"reserve", (
char*)
"n", sz);
452 PyObject* fi = PySequence_GetItem(PyTuple_GET_ITEM(args, 0), 0);
453 if (!fi) PyErr_Clear();
454 if (fi && (PyTuple_CheckExact(fi) || PyList_CheckExact(fi))) {
456 PyObject* eb_call = PyObject_GetAttrString(vecin, (
char*)
"emplace_back");
458 bool value_is_vector =
false;
462 value_is_vector =
true;
469 for (
int i = 0; ; ++i) {
472 if (value_is_vector && PySequence_Check(item)) {
473 eb_args = PyTuple_New(1);
474 PyTuple_SET_ITEM(eb_args, 0, item);
475 }
else if (PyTuple_CheckExact(item)) {
477 }
else if (PyList_CheckExact(item)) {
479 eb_args = PyTuple_New(isz);
481 PyObject* iarg = PyList_GET_ITEM(item, j);
483 PyTuple_SET_ITEM(eb_args, j, iarg);
488 PyErr_Format(PyExc_TypeError,
"argument %d is not a tuple or list", i);
492 PyObject* ebres = PyObject_CallObject(eb_call, eb_args);
500 if (PyErr_Occurred()) {
501 if (!(PyErr_ExceptionMatches(PyExc_IndexError) ||
502 PyErr_ExceptionMatches(PyExc_StopIteration)))
504 else { PyErr_Clear(); }
513 PyObject* pb_call = PyObject_GetAttrString(vecin, (
char*)
"push_back");
518 PyObject* pbres = PyObject_CallFunctionObjArgs(pb_call, item,
nullptr);
526 if (PyErr_Occurred()) {
527 if (!(PyErr_ExceptionMatches(PyExc_IndexError) ||
528 PyErr_ExceptionMatches(PyExc_StopIteration)))
530 else { PyErr_Clear(); }
546 ItemGetter* getter = GetGetter(args);
549 bool fill_ok =
FillVector(self, args, getter);
561 if (PyTuple_GET_SIZE(args) == 1) {
562 PyObject* fi = PyTuple_GET_ITEM(args, 0);
584 if (!PyErr_Occurred())
585 PyErr_SetString(PyExc_TypeError,
"argument is not iterable");
598 ItemGetter* getter = GetGetter(args);
608 bool fill_ok =
FillVector(self, args, getter);
622 PyObject* result = PyObject_Call(realInit, args,
nullptr);
633 PyObject* pydata = CallPyObjMethod(self,
"__real_data");
643 long clen = PyInt_AsLong(pylen);
666 PyObject* pydata = VectorData(self,
nullptr);
668 PyObject* newarr = PyObject_Call(arrcall, args, kwargs);
678 if (!vi)
return nullptr;
684#if PY_VERSION_HEX >= 0x030e0000
697 vi->
vi_stride = PyLong_AsLong(pyvalue_size);
698 Py_DECREF(pyvalue_size);
721 if (value_type.back() !=
'*')
735 PyObject* pydata = CallPyObjMethod(
v,
"__real_data");
749 Py_XDECREF(pyvalue_type);
752 vi->
ii_len = PySequence_Size(
v);
754 PyObject_GC_Track(vi);
761 if (PySlice_Check(index)) {
763 PyErr_SetString(PyExc_TypeError,
"unsubscriptable object");
768 PyObject* nseq = PyObject_CallObject(pyclass,
nullptr);
774 if (!AdjustSlice(nlen,
start, stop, step))
781 CallPyObjMethod(nseq,
"push_back", item);
800 PyErr_Format(PyExc_TypeError,
801 "require object of type std::vector<bool>, but %s given",
807 PyErr_SetString(PyExc_TypeError,
"unsubscriptable object");
811 if (PySlice_Check(idx)) {
813 PyObject* nseq = PyObject_CallObject(pyclass,
nullptr);
818 if (!AdjustSlice(nlen,
start, stop, step))
825 CallPyObjMethod(nseq,
"push_back", item);
837 int index = (
int)PyLong_AsLong(pyindex);
841 std::vector<bool>* vb = (std::vector<bool>*)self->GetObject();
844 if (
bool((*vb)[index]))
854 PyErr_Format(PyExc_TypeError,
855 "require object of type std::vector<bool>, but %s given",
861 PyErr_SetString(PyExc_TypeError,
"unsubscriptable object");
865 int bval = 0;
PyObject* idx =
nullptr;
866 if (!PyArg_ParseTuple(args,
const_cast<char*
>(
"Oi:__setitem__"), &idx, &bval))
873 int index = (
int)PyLong_AsLong(pyindex);
877 std::vector<bool>* vb = (std::vector<bool>*)self->
GetObject();
880 (*vb)[index] = (
bool)bval;
893 if (args && PyTuple_GET_SIZE(args) == 1 && PySequence_Check(PyTuple_GET_ITEM(args, 0))) {
899 PyObject* items = PyTuple_GET_ITEM(args, 0);
901 if (PySequence_Size(self) != fillsz) {
902 PyErr_Format(PyExc_ValueError,
"received sequence of size %zd where %zd expected",
903 fillsz, PySequence_Size(self));
910 PyObject* item = PySequence_GetItem(items, i);
912 PyObject* sires = PyObject_CallFunctionObjArgs(si_call, index, item,
nullptr);
931 PyObject* result = PyObject_Call(realInit, args,
nullptr);
949 for (
Py_ssize_t i = 0; i < PySequence_Size(pairs); ++i) {
952 if (
pair && PySequence_Check(
pair) && PySequence_Size(
pair) == 2) {
955 sires = PyObject_CallFunctionObjArgs(si_call, key, value,
nullptr);
963 if (!PyErr_Occurred())
964 PyErr_SetString(PyExc_TypeError,
"Failed to fill map (argument not a dict or sequence of pairs)");
982 if (PyTuple_GET_SIZE(args) == 1 && PyMapping_Check(PyTuple_GET_ITEM(args, 0)) && \
983 !(PyTuple_Check(PyTuple_GET_ITEM(args, 0)) || PyList_Check(PyTuple_GET_ITEM(args, 0)))) {
984 PyObject* assoc = PyTuple_GET_ITEM(args, 0);
985#if PY_VERSION_HEX < 0x03000000
987 PyObject* items = PyObject_CallMethod(assoc, (
char*)
"items",
nullptr);
990 PyObject* items = PyMapping_Items(assoc);
992 if (items && PySequence_Check(items)) {
993 PyObject* result = MapFromPairs(self, items);
1005 if (PyTuple_GET_SIZE(args) == 1 && PySequence_Check(PyTuple_GET_ITEM(args, 0)))
1006 return MapFromPairs(self, PyTuple_GET_ITEM(args, 0));
1011 PyObject* result = PyObject_Call(realInit, args,
nullptr);
1012 Py_DECREF(realInit);
1019#if __cplusplus <= 202002L
1025 PyObject* iter = CallPyObjMethod(self,
"find", obj);
1029 if (!PyObject_RichCompareBool(iter, end, Py_EQ)) {
1040 Py_INCREF(Py_False);
1053 if (PyTuple_GET_SIZE(args) == 1 && PySet_Check(PyTuple_GET_ITEM(args, 0))) {
1054 PyObject* pyset = PyTuple_GET_ITEM(args, 0);
1061 PyObject* iter = PyObject_GetIter(pyset);
1063 PyObject* ins_call = PyObject_GetAttrString(self, (
char*)
"insert");
1065 IterItemGetter getter{iter};
1070 PyObject* insres = PyObject_CallFunctionObjArgs(ins_call, item,
nullptr);
1073 Py_DECREF(ins_call);
1078 item = getter.get();
1080 Py_DECREF(ins_call);
1089 PyObject* result = PyObject_Call(realInit, args,
nullptr);
1090 Py_DECREF(realInit);
1099static const ptrdiff_t PS_END_ADDR = 7;
1100static const ptrdiff_t PS_FLAG_ADDR = 11;
1101static const ptrdiff_t PS_COLL_ADDR = 13;
1123 PyErr_SetString(PyExc_TypeError,
"unrecognized iterator type for low level views");
1139 auto& dmc = ((
CPPInstance*)iter)->GetDatamemberCache();
1140 dmc.push_back(std::make_pair(PS_END_ADDR, end));
1143 Py_INCREF(Py_False);
1144 dmc.push_back(std::make_pair(PS_FLAG_ADDR, Py_False));
1148 dmc.push_back(std::make_pair(PS_COLL_ADDR, self));
1163 if (!ii)
return nullptr;
1168 ii->
ii_len = PySequence_Size(
c);
1170 PyObject_GC_Track(ii);
1208 long idx = PyLong_AsLong(pyindex);
1209 if (idx == -1 && PyErr_Occurred())
1213 PyErr_SetString(PyExc_TypeError,
"unsubscriptable object");
1219 else if ((
int)idx == 1)
1223 PyErr_SetString(PyExc_IndexError,
"out of bounds");
1229 return PyInt_FromLong(2);
1239 PyObject* result = PyObject_Call(realInit, args,
nullptr);
1240 Py_DECREF(realInit);
1241 if (result && PyTuple_GET_SIZE(args) == 1 &&
CPPInstance_Check(PyTuple_GET_ITEM(args, 0))) {
1252#if PY_VERSION_HEX >= 0x03000000
1255 return !PyObject_RichCompareBool(one, other, Py_EQ);
1259PyObject* CPyCppyy_PyString_FromCppString(std::string_view s,
bool native=
true) {
1266PyObject* CPyCppyy_PyString_FromCppString(std::wstring_view s,
bool native=
true) {
1267 PyObject* pyobj = PyUnicode_FromWideChar(s.data(), s.size());
1268 if (pyobj && native) {
1269 PyObject* pybytes = PyUnicode_AsEncodedString(pyobj,
"UTF-8",
"strict");
1276#define CPPYY_IMPL_STRING_PYTHONIZATION(type, name) \
1278PyObject* name##StringGetData(PyObject* self, bool native=true) \
1280 if (CPyCppyy::CPPInstance_Check(self)) { \
1281 type* obj = ((type*)((CPPInstance*)self)->GetObject()); \
1282 if (obj) return CPyCppyy_PyString_FromCppString(*obj, native); \
1284 PyErr_Format(PyExc_TypeError, "object mismatch (%s expected)", #type); \
1288PyObject* name##StringStr(PyObject* self) \
1290 PyObject* pyobj = name##StringGetData(self, false); \
1294 PyObject* pybytes = name##StringGetData(self, true); \
1296 pyobj = PyObject_Str(pybytes); \
1297 Py_DECREF(pybytes); \
1303PyObject* name##StringBytes(PyObject* self) \
1305 return name##StringGetData(self, true); \
1308PyObject* name##StringRepr(PyObject* self) \
1310 PyObject* data = name##StringGetData(self, true); \
1312 PyObject* repr = PyObject_Repr(data); \
1319PyObject* name##StringIsEqual(PyObject* self, PyObject* obj) \
1321 PyObject* data = name##StringGetData(self, PyBytes_Check(obj)); \
1323 PyObject* result = PyObject_RichCompare(data, obj, Py_EQ); \
1330PyObject* name##StringIsNotEqual(PyObject* self, PyObject* obj) \
1332 PyObject* data = name##StringGetData(self, PyBytes_Check(obj)); \
1334 PyObject* result = PyObject_RichCompare(data, obj, Py_NE); \
1342#define CPPYY_IMPL_STRING_PYTHONIZATION_CMP(type, name) \
1343CPPYY_IMPL_STRING_PYTHONIZATION(type, name) \
1344PyObject* name##StringCompare(PyObject* self, PyObject* obj) \
1346 PyObject* data = name##StringGetData(self, PyBytes_Check(obj)); \
1349 result = PyObject_Compare(data, obj); \
1352 if (PyErr_Occurred()) \
1354 return PyInt_FromLong(result); \
1361static inline std::string* GetSTLString(
CPPInstance* self) {
1363 PyErr_SetString(PyExc_TypeError,
"std::string object expected");
1367 std::string* obj = (std::string*)self->
GetObject();
1369 PyErr_SetString(PyExc_ReferenceError,
"attempt to access a null-pointer");
1376 std::string* obj = GetSTLString(self);
1380 char* keywords[] = {(
char*)
"encoding", (
char*)
"errors", (
char*)
nullptr};
1381 const char* encoding =
nullptr;
const char* errors =
nullptr;
1382 if (!PyArg_ParseTupleAndKeywords(args, kwds,
1383 const_cast<char*
>(
"s|s"), keywords, &encoding, &errors))
1386 return PyUnicode_Decode(obj->data(), obj->size(), encoding, errors);
1389#if __cplusplus <= 202302L
1392 std::string* obj = GetSTLString(self);
1400 if (obj->find(needle) != std::string::npos) {
1410 std::string* obj = GetSTLString(self);
1420 PyObject* meth = PyObject_GetAttrString(pystr, (
char*)
"replace");
1422 PyObject* result = PyObject_CallObject(meth, args);
1427 PyObject* cppreplace = PyObject_GetAttrString((
PyObject*)self, (
char*)
"__cpp_replace");
1429 PyObject* result = PyObject_Call(cppreplace, args,
nullptr);
1430 Py_DECREF(cppreplace);
1434 PyErr_SetString(PyExc_AttributeError,
"\'std::string\' object has no attribute \'replace\'");
1438#define CPYCPPYY_STRING_FINDMETHOD(name, cppname, pyname) \
1439PyObject* STLString##name(CPPInstance* self, PyObject* args, PyObject* ) \
1441 std::string* obj = GetSTLString(self); \
1445 PyObject* cppmeth = PyObject_GetAttrString((PyObject*)self, (char*)#cppname);\
1447 PyObject* result = PyObject_Call(cppmeth, args, nullptr); \
1448 Py_DECREF(cppmeth); \
1450 if (PyLongOrInt_AsULong64(result) == (PY_ULONG_LONG)std::string::npos) {\
1451 Py_DECREF(result); \
1452 return PyInt_FromLong(-1); \
1459 PyObject* pystr = CPyCppyy_PyText_FromStringAndSize(obj->data(), obj->size());\
1460 PyObject* pymeth = PyObject_GetAttrString(pystr, (char*)#pyname); \
1462 PyObject* result = PyObject_CallObject(pymeth, args); \
1463 Py_DECREF(pymeth); \
1474 std::string* obj = GetSTLString(self);
1479 PyObject* attr = PyObject_GetAttr(pystr, attr_name);
1492 PyObject* str_res = PyObject_Str(res);
1503 PyObject* str_res = PyObject_Str(res);
1513 PyObject* data = STLStringGetData(self,
false);
1528 PyObject *strbuf =
nullptr, *newArgs =
nullptr;
1529 if (PyTuple_GET_SIZE(args) == 1) {
1530 PyObject* arg0 = PyTuple_GET_ITEM(args, 0);
1531 if (PyUnicode_Check(arg0)) {
1533 strbuf = PyUnicode_AsEncodedString(arg0,
"UTF-8",
"strict");
1534 newArgs = PyTuple_New(1);
1536 PyTuple_SET_ITEM(newArgs, 0, strbuf);
1544 PyObject* result = PyObject_Call(realInit, newArgs ? newArgs : args,
nullptr);
1546 Py_XDECREF(newArgs);
1547 Py_DECREF(realInit);
1551 if (result && self && strbuf)
1565 bool mustIncrement =
true;
1568 auto& dmc = ((
CPPInstance*)self)->GetDatamemberCache();
1569 for (
auto& p: dmc) {
1570 if (p.first == PS_END_ADDR) {
1573 }
else if (p.first == PS_FLAG_ADDR) {
1574 mustIncrement = p.second == Py_True;
1575 if (!mustIncrement) {
1576 Py_DECREF(p.second);
1587 if (!PyObject_RichCompareBool(last, self, Py_EQ)) {
1588 bool iter_valid =
true;
1589 if (mustIncrement) {
1595 static PyObject* dummy = PyInt_FromLong(1l);
1598 iter_valid = iter && PyObject_RichCompareBool(last, self, Py_NE);
1604 if (!next) PyErr_Clear();
1610 if (!next) PyErr_SetString(PyExc_StopIteration,
"");
1616#define COMPLEX_METH_GETSET(name, cppname) \
1617static PyObject* name##ComplexGet(PyObject* self, void*) { \
1618 return PyObject_CallMethodNoArgs(self, cppname); \
1620static int name##ComplexSet(PyObject* self, PyObject* value, void*) { \
1621 PyObject* result = PyObject_CallMethodOneArg(self, cppname, value); \
1623 Py_DECREF(result); \
1628PyGetSetDef name##Complex{(char*)#name, (getter)name##ComplexGet, (setter)name##ComplexSet, nullptr, nullptr};
1635 if (!real)
return nullptr;
1636 double r = PyFloat_AsDouble(real);
1638 if (
r == -1. && PyErr_Occurred())
1642 if (!imag)
return nullptr;
1643 double i = PyFloat_AsDouble(imag);
1645 if (i == -1. && PyErr_Occurred())
1648 return PyComplex_FromDoubles(
r, i);
1653 if (!real)
return nullptr;
1654 double r = PyFloat_AsDouble(real);
1656 if (
r == -1. && PyErr_Occurred())
1660 if (!imag)
return nullptr;
1661 double i = PyFloat_AsDouble(imag);
1663 if (i == -1. && PyErr_Occurred())
1666 std::ostringstream s;
1667 s <<
'(' <<
r <<
'+' << i <<
"j)";
1673 return PyFloat_FromDouble(((std::complex<double>*)self->
GetObject())->real());
1678 double d = PyFloat_AsDouble(value);
1679 if (
d == -1.0 && PyErr_Occurred())
1681 ((std::complex<double>*)self->
GetObject())->real(
d);
1685PyGetSetDef ComplexDReal{(
char*)
"real", (getter)ComplexDRealGet, (setter)ComplexDRealSet,
nullptr,
nullptr};
1690 return PyFloat_FromDouble(((std::complex<double>*)self->
GetObject())->imag());
1695 double d = PyFloat_AsDouble(value);
1696 if (
d == -1.0 && PyErr_Occurred())
1698 ((std::complex<double>*)self->
GetObject())->imag(
d);
1702PyGetSetDef ComplexDImag{(
char*)
"imag", (getter)ComplexDImagGet, (setter)ComplexDImagSet,
nullptr,
nullptr};
1706 double r = ((std::complex<double>*)self->
GetObject())->real();
1707 double i = ((std::complex<double>*)self->
GetObject())->imag();
1708 return PyComplex_FromDoubles(
r, i);
1724 Py_INCREF(pyclass); PyTuple_SET_ITEM(args, 0, pyclass);
1725 Py_INCREF(pyname); PyTuple_SET_ITEM(args, 1, pyname);
1727 bool pstatus =
true;
1728 for (
auto pythonizor :
v) {
1729 PyObject* result = PyObject_CallObject(pythonizor, args);
1763#if PY_VERSION_HEX >= 0x03000000
1764 const char* pybool_name =
"__bool__";
1766 const char* pybool_name =
"__nonzero__";
1778 bool sizeIsInteger =
false;
1782 if (ol->HasMethods() && ol->fMethodInfo->fMethods.size() == 1) {
1787 Py_DECREF(pyrestype);
1791 Py_XDECREF(pySizeMethod);
1793 if (sizeIsInteger) {
1797 if (hasIterators || hasSubscript) {
1807 if (!IsTemplatedSTLClass(
name,
"vector") &&
1808 !((PyTypeObject*)pyclass)->tp_iter) {
1819 if (resname.find(
"iterator") == std::string::npos)
1826 ((PyTypeObject*)pyclass)->tp_iter = (getiterfunc)STLSequenceIter;
1832 if (resolved.back() ==
'*' &&
Cppyy::IsBuiltin(resolved.substr(0, resolved.size()-1))) {
1833 ((PyTypeObject*)pyclass)->tp_iter = (getiterfunc)LLSequenceIter;
1839 if (!((PyTypeObject*)pyclass)->tp_iter &&
1845 ((PyTypeObject*)pyclass)->tp_iter = (getiterfunc)index_iter;
1901 name.compare(0, 6,
"tuple<", 6) != 0) {
1906 std::string rname =
name;
1909 std::ostringstream initdef;
1910 initdef <<
"namespace __cppyy_internal {\n"
1911 <<
"void init_" << rname <<
"(" <<
name <<
"** self";
1912 bool codegen_ok =
true;
1913 std::vector<std::string> arg_types, arg_names, arg_defaults;
1914 arg_types.reserve(ndata); arg_names.reserve(ndata); arg_defaults.reserve(ndata);
1924 if (res_clean ==
"internal_enum_type_t")
1927 if (res.rfind(
']') == std::string::npos && res.rfind(
')') == std::string::npos) {
1928 if (!cpd.empty()) arg_types.push_back(res_clean+cpd);
1929 else arg_types.push_back(
"const "+res_clean+
"&");
1932 arg_defaults.push_back(
"0");
1943 if (codegen_ok && !arg_types.empty()) {
1944 bool defaults_ok = arg_defaults.size() == arg_types.size();
1945 for (std::vector<std::string>::size_type i = 0; i < arg_types.size(); ++i) {
1946 initdef <<
", " << arg_types[i] <<
" " << arg_names[i];
1947 if (defaults_ok) initdef <<
" = " << arg_defaults[i];
1949 initdef <<
") {\n *self = new " <<
name <<
"{";
1950 for (std::vector<std::string>::size_type i = 0; i < arg_names.size(); ++i) {
1951 if (i != 0) initdef <<
", ";
1952 initdef << arg_names[i];
1954 initdef <<
"};\n} }";
1972 if (IsTemplatedSTLClass(
name,
"span")) {
1987 if (IsTemplatedSTLClass(
name,
"vector")) {
1991 if (klass->
fCppType == sVectorBoolTypeID) {
1997 Utility::AddToClass(pyclass,
"__init__", (PyCFunction)VectorInit, METH_VARARGS | METH_KEYWORDS);
2011 Utility::AddToClass(pyclass,
"__array__", (PyCFunction)VectorArray, METH_VARARGS | METH_KEYWORDS );
2021 ((PyTypeObject*)pyclass)->tp_iter = (getiterfunc)vector_iter;
2024 Utility::AddToClass(pyclass,
"__iadd__", (PyCFunction)VectorIAdd, METH_VARARGS | METH_KEYWORDS);
2028 if (vtype.rfind(
"value_type") == std::string::npos) {
2031 Py_DECREF(pyvalue_type);
2036 PyObject* pyvalue_size = PyLong_FromSsize_t(typesz);
2038 Py_DECREF(pyvalue_size);
2043 else if (IsTemplatedSTLClass(
name,
"array")) {
2046 Utility::AddToClass(pyclass,
"__init__", (PyCFunction)ArrayInit, METH_VARARGS | METH_KEYWORDS);
2049 else if (IsTemplatedSTLClass(
name,
"map") || IsTemplatedSTLClass(
name,
"unordered_map")) {
2052 Utility::AddToClass(pyclass,
"__init__", (PyCFunction)MapInit, METH_VARARGS | METH_KEYWORDS);
2053#if __cplusplus <= 202002L
2059 else if (IsTemplatedSTLClass(
name,
"set")) {
2062 Utility::AddToClass(pyclass,
"__init__", (PyCFunction)SetInit, METH_VARARGS | METH_KEYWORDS);
2064#if __cplusplus <= 202002L
2070 else if (IsTemplatedSTLClass(
name,
"pair")) {
2075 if (IsTemplatedSTLClass(
name,
"shared_ptr") || IsTemplatedSTLClass(
name,
"unique_ptr")) {
2077 Utility::AddToClass(pyclass,
"__init__", (PyCFunction)SmartPtrInit, METH_VARARGS | METH_KEYWORDS);
2080 else if (!((PyTypeObject*)pyclass)->tp_iter && \
2082 ((PyTypeObject*)pyclass)->tp_iternext = (iternextfunc)STLIterNext;
2084 ((PyTypeObject*)pyclass)->tp_iter = (getiterfunc)PyObject_SelfIter;
2088 else if (
name ==
"string" ||
name ==
"std::string") {
2095#if __cplusplus <= 202302L
2099 Utility::AddToClass(pyclass,
"decode", (PyCFunction)STLStringDecode, METH_VARARGS | METH_KEYWORDS);
2101 Utility::AddToClass(pyclass,
"find", (PyCFunction)STLStringFind, METH_VARARGS | METH_KEYWORDS);
2103 Utility::AddToClass(pyclass,
"rfind", (PyCFunction)STLStringRFind, METH_VARARGS | METH_KEYWORDS);
2105 Utility::AddToClass(pyclass,
"replace", (PyCFunction)STLStringReplace, METH_VARARGS | METH_KEYWORDS);
2109 ((PyTypeObject*)pyclass)->tp_hash = (hashfunc)STLStringHash;
2112 else if (
name ==
"basic_string_view<char,char_traits<char> >" ||
name ==
"std::basic_string_view<char>") {
2114 Utility::AddToClass(pyclass,
"__init__", (PyCFunction)StringViewInit, METH_VARARGS | METH_KEYWORDS);
2127 else if (
name ==
"std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> >"
2128 ||
name ==
"basic_string<wchar_t,char_traits<wchar_t>,allocator<wchar_t> >"
2129 ||
name ==
"std::basic_string<wchar_t,char_traits<wchar_t>,allocator<wchar_t> >"
2139 else if (
name ==
"complex<double>" ||
name ==
"std::complex<double>") {
2141 PyObject_SetAttrString(pyclass,
"real", PyDescr_NewGetSet((PyTypeObject*)pyclass, &ComplexDReal));
2143 PyObject_SetAttrString(pyclass,
"imag", PyDescr_NewGetSet((PyTypeObject*)pyclass, &ComplexDImag));
2148 else if (IsTemplatedSTLClass(
name,
"complex")) {
2150 PyObject_SetAttrString(pyclass,
"real", PyDescr_NewGetSet((PyTypeObject*)pyclass, &realComplex));
2152 PyObject_SetAttrString(pyclass,
"imag", PyDescr_NewGetSet((PyTypeObject*)pyclass, &imagComplex));
2160 bool bUserOk =
true;
PyObject* res =
nullptr;
2164 bUserOk = (
bool)res;
2168 res = PyObject_CallFunctionObjArgs(func, pyclass, pyname,
nullptr);
2170 bUserOk = (
bool)res;
2184 bool pstatus =
true;
2187 if (!outer_scope.empty()) {
2188 auto p = pyzMap.find(outer_scope);
2189 if (p != pyzMap.end()) {
2191 name.substr(outer_scope.size()+2, std::string::npos).c_str());
2198 auto p = pyzMap.find(
"");
2199 if (p != pyzMap.end())
#define PyInt_FromSsize_t
#define CPyCppyy_PyText_FromStringAndSize
#define CPyCppyy_PySliceCast
#define CPyCppyy_PyText_AsString
static PyObject * PyObject_CallMethodOneArg(PyObject *obj, PyObject *name, PyObject *arg)
#define PyBytes_FromStringAndSize
#define CPyCppyy_PyText_Type
static PyObject * PyObject_CallMethodNoArgs(PyObject *obj, PyObject *name)
#define CPyCppyy_PyText_FromString
#define CPyCppyy_PyText_Check
bool PyUnstable_Object_IsUniqueReferencedTemporary(PyObject *pyobject)
#define CPPYY_IMPL_STRING_PYTHONIZATION_CMP(type, name)
static bool run_pythonizors(PyObject *pyclass, PyObject *pyname, const std::vector< PyObject * > &v)
#define COMPLEX_METH_GETSET(name, cppname)
#define CPYCPPYY_STRING_FINDMETHOD(name, cppname, pyname)
#define PyObject_LengthHint
void FillVector(std::vector< double > &v, int size, T *a)
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
Cppyy::TCppType_t ObjectIsA(bool check_smart=true) const
Utility::PyOperators * fOperators
Cppyy::TCppType_t fCppType
void cppscope_to_legalname(std::string &cppscope)
std::string clean_type(const std::string &cppname, bool template_strip=true, bool const_strip=true)
std::string compound(const std::string &name)
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)
PyTypeObject VectorIter_Type
PyObject * GetScopeProxy(Cppyy::TCppScope_t)
static PyObject * GetAttrDirect(PyObject *pyclass, PyObject *pyname)
bool Pythonize(PyObject *pyclass, const std::string &name)
bool CPPOverload_Check(T *object)
std::map< std::string, std::vector< PyObject * > > & pythonizations()
bool CPPScope_Check(T *object)
bool LowLevelView_Check(T *object)
bool CPPInstance_Check(T *object)
PyTypeObject IndexIter_Type
CPYCPPYY_EXTERN Converter * CreateConverter(const std::string &name, cdims_t=0)
std::set< std::string > gIteratorTypes
const RequestId_t RETURN_TYPE
const FormatId_t AS_STRING
RPY_EXPORTED bool IsIntegerType(const std::string &type_name)
RPY_EXPORTED size_t SizeOf(TCppType_t klass)
RPY_EXPORTED bool IsDefaultConstructable(TCppType_t type)
RPY_EXPORTED bool IsEnum(const std::string &type_name)
RPY_EXPORTED std::vector< TCppIndex_t > GetMethodIndicesFromName(TCppScope_t scope, const std::string &name)
RPY_EXPORTED TCppIndex_t GetNumDatamembers(TCppScope_t scope, bool accept_namespace=false)
RPY_EXPORTED bool Compile(const std::string &code, bool silent=false)
RPY_EXPORTED TCppScope_t gGlobalScope
RPY_EXPORTED std::string ResolveName(const std::string &cppitem_name)
RPY_EXPORTED bool IsAggregate(TCppType_t type)
RPY_EXPORTED std::string GetScopedFinalName(TCppType_t type)
RPY_EXPORTED bool IsPublicData(TCppScope_t scope, TCppIndex_t idata)
RPY_EXPORTED bool IsBuiltin(const std::string &type_name)
RPY_EXPORTED bool IsStaticData(TCppScope_t scope, TCppIndex_t idata)
RPY_EXPORTED std::string GetDatamemberType(TCppScope_t scope, TCppIndex_t idata)
RPY_EXPORTED TCppMethod_t GetMethod(TCppScope_t scope, TCppIndex_t imeth)
RPY_EXPORTED bool IsSmartPtr(TCppType_t type)
RPY_EXPORTED TCppScope_t GetScope(const std::string &scope_name)
RPY_EXPORTED std::string GetMethodResultType(TCppMethod_t)
RPY_EXPORTED std::string GetDatamemberName(TCppScope_t scope, TCppIndex_t idata)
CoordSystem::Scalar get(DisplacementVector2D< CoordSystem, Tag > const &p)
PyObject_HEAD PyObject * ii_container
Cppyy::TCppType_t vi_klass
CPyCppyy::Converter * vi_converter