33std::unordered_map<std::string, std::vector<PyObject*>>&
pythonizations();
43 bool mustBecpyrt =
false) {
73inline bool IsTemplatedSTLClass(
const std::string&
name,
74 const std::string& klass) {
77 auto pos =
name.find(klass);
78 return pos == 5 &&
name.rfind(
"std::", 0, 5) == 0 &&
79 name.find(
"::",
name.rfind(
">")) == std::string::npos;
87 PyObject_CallMethod(obj,
const_cast<char*
>(meth),
const_cast<char*
>(
""));
97 PyObject*
result = PyObject_CallMethod(obj,
const_cast<char*
>(meth),
98 const_cast<char*
>(
"O"), arg1);
106 Py_ssize_t idx = PyLong_AsSsize_t(
index);
107 if (idx == (Py_ssize_t)-1 && PyErr_Occurred())
110 Py_ssize_t
size = PySequence_Size(self);
111 if (idx >=
size || (idx < 0 && idx < -
size)) {
112 PyErr_SetString(PyExc_IndexError,
"index out of range");
121 pyindex = PyLong_FromSsize_t(
size + idx);
127inline bool AdjustSlice(
const Py_ssize_t nlen, Py_ssize_t& start,
128 Py_ssize_t& stop, Py_ssize_t& step) {
130 if ((step > 0 && stop <= start) || (step < 0 && start <= stop))
140 stop = step > 0 ? std::min(nlen, stop) : (stop >= 0 ? stop : -1);
156 PyObject_CallMethodOneArg((
PyObject*)self, pymeth, pyindex);
165 if (!PyUnicode_Check(
name))
166 PyErr_SetString(PyExc_TypeError,
167 "getattr(): attribute name must be string");
169 PyObject* pyptr = PyObject_CallMethodNoArgs(self, method);
174 if (Py_TYPE(pyptr) == Py_TYPE(self)) {
177 PyErr_Format(PyExc_AttributeError,
"%s object has no attribute \'%s\'",
178 PyUnicode_AsUTF8(val1), PyUnicode_AsUTF8(val2));
199 PyErr_SetString(PyExc_AttributeError, PyUnicode_AsUTF8(
name));
213 const int contains_value = PyObject_IsTrue(has_value);
214 Py_DECREF(has_value);
215 if (contains_value < 0)
217 if (!contains_value) {
218 PyErr_SetObject(PyExc_AttributeError,
name);
222 return DeRefGetAttr(self,
name);
235 PyErr_SetString(PyExc_TypeError,
"C++ object proxy expected");
249 ItemGetter(
PyObject* pyobj) : fPyObject(pyobj) { Py_INCREF(fPyObject); }
250 virtual ~ItemGetter() { Py_DECREF(fPyObject); }
251 virtual Py_ssize_t
size() = 0;
256struct CountedItemGetter :
public ItemGetter {
257 CountedItemGetter(
PyObject* pyobj) : ItemGetter(pyobj), fCur(0) {}
261struct TupleItemGetter :
public CountedItemGetter {
262 using CountedItemGetter::CountedItemGetter;
263 Py_ssize_t
size()
override {
return PyTuple_GET_SIZE(fPyObject); }
265 if (fCur < PyTuple_GET_SIZE(fPyObject)) {
266 PyObject* item = PyTuple_GET_ITEM(fPyObject, fCur++);
270 PyErr_SetString(PyExc_StopIteration,
"end of tuple");
275struct ListItemGetter :
public CountedItemGetter {
276 using CountedItemGetter::CountedItemGetter;
277 Py_ssize_t
size()
override {
return PyList_GET_SIZE(fPyObject); }
279 if (fCur < PyList_GET_SIZE(fPyObject)) {
280 PyObject* item = PyList_GET_ITEM(fPyObject, fCur++);
284 PyErr_SetString(PyExc_StopIteration,
"end of list");
289struct SequenceItemGetter :
public CountedItemGetter {
290 using CountedItemGetter::CountedItemGetter;
291 Py_ssize_t
size()
override {
292 Py_ssize_t sz = PySequence_Size(fPyObject);
295 return PyObject_LengthHint(fPyObject, 8);
299 PyObject*
get()
override {
return PySequence_GetItem(fPyObject, fCur++); }
302struct IterItemGetter :
public ItemGetter {
303 using ItemGetter::ItemGetter;
304 Py_ssize_t
size()
override {
return PyObject_LengthHint(fPyObject, 8); }
306 return (*(Py_TYPE(fPyObject)->tp_iternext))(fPyObject);
310static ItemGetter* GetGetter(
PyObject* args) {
312 ItemGetter* getter =
nullptr;
314 if (PyTuple_GET_SIZE(args) == 1) {
315 PyObject* fi = PyTuple_GET_ITEM(args, 0);
316 if (PyUnicode_Check(fi) || PyBytes_Check(fi))
322 if (PyObject_CheckBuffer(fi))
325 if (PyTuple_CheckExact(fi))
326 getter =
new TupleItemGetter(fi);
327 else if (PyList_CheckExact(fi))
328 getter =
new ListItemGetter(fi);
329 else if (PySequence_Check(fi))
330 getter =
new SequenceItemGetter(fi);
332 PyObject* iter = PyObject_GetIter(fi);
334 getter =
new IterItemGetter{iter};
346void compileSpanHelpers() {
347 static bool compiled =
false;
355namespace __cppjit_internal {
362 ptr_iterator(T *c, T *e) : cur(c), end(e) {}
364 T &operator*() const { return *cur; }
365 ptr_iterator &operator++()
370 bool operator==(const ptr_iterator &other) const { return cur == other.cur; }
371 bool operator!=(const ptr_iterator &other) const { return !(*this == other); }
375ptr_iterator<T> make_iter(T *begin, T *end)
380} // namespace __cppjit_internal
382// Note: for const span<T>, T is const-qualified here
384auto __cppjit_internal_begin(T &s) noexcept
386 return __cppjit_internal::make_iter(s.data(), s.data() + s.size());
389// Note: for const span<T>, T is const-qualified here
391auto __cppjit_internal_end(T &s) noexcept
393 // end iterator = begin iterator with cur == end
394 return __cppjit_internal::make_iter(s.data() + s.size(), s.data() + s.size());
403 compileSpanHelpers();
405 pyFunc = PyObject_GetAttrString(py_ns,
"__cppjit_internal_begin");
407 PyErr_Format(PyExc_RuntimeError,
408 "cppyy internal error: failed to locate helper "
409 "'__cppjit_internal_begin' for std::span pythonization");
418 compileSpanHelpers();
420 pyFunc = PyObject_GetAttrString(py_ns,
"__cppjit_internal_end");
422 PyErr_Format(PyExc_RuntimeError,
423 "cppyy internal error: failed to locate helper "
424 "'__cppjit_internal_end' for std::span pythonization");
433 auto begin = spanBegin();
436 return PyObject_CallOneArg(begin, self);
440 auto end = spanEnd();
443 return PyObject_CallOneArg(end, self);
447 Py_ssize_t sz = getter->size();
454 PyObject_CallMethod(vecin, (
char*)
"reserve", (
char*)
"n", sz);
463 PyObject* fi = PySequence_GetItem(PyTuple_GET_ITEM(args, 0), 0);
466 if (fi && (PyTuple_CheckExact(fi) || PyList_CheckExact(fi))) {
468 PyObject* eb_call = PyObject_GetAttrString(vecin, (
char*)
"emplace_back");
471 bool value_is_vector =
false;
472 if (vtype && PyLong_Check(vtype)) {
476 .rfind(
"std::vector", 0) != std::string::npos)
477 value_is_vector =
true;
484 for (
int i = 0; ; ++i) {
487 if (value_is_vector && PySequence_Check(item)) {
488 eb_args = PyTuple_New(1);
489 PyTuple_SET_ITEM(eb_args, 0, item);
490 }
else if (PyTuple_CheckExact(item)) {
492 }
else if (PyList_CheckExact(item)) {
493 Py_ssize_t isz = PyList_GET_SIZE(item);
494 eb_args = PyTuple_New(isz);
495 for (Py_ssize_t j = 0; j < isz; ++j) {
496 PyObject* iarg = PyList_GET_ITEM(item, j);
498 PyTuple_SET_ITEM(eb_args, j, iarg);
503 PyErr_Format(PyExc_TypeError,
"argument %d is not a tuple or list",
508 PyObject* ebres = PyObject_CallObject(eb_call, eb_args);
516 if (PyErr_Occurred()) {
517 if (!(PyErr_ExceptionMatches(PyExc_IndexError) ||
518 PyErr_ExceptionMatches(PyExc_StopIteration)))
531 PyObject* pb_call = PyObject_GetAttrString(vecin, (
char*)
"push_back");
537 PyObject_CallFunctionObjArgs(pb_call, item,
nullptr);
545 if (PyErr_Occurred()) {
546 if (!(PyErr_ExceptionMatches(PyExc_IndexError) ||
547 PyErr_ExceptionMatches(PyExc_StopIteration)))
566 ItemGetter* getter = GetGetter(args);
569 bool fill_ok =
FillVector(self, args, getter);
581 if (PyTuple_GET_SIZE(args) == 1) {
582 PyObject* fi = PyTuple_GET_ITEM(args, 0);
583 if (PyObject_CheckBuffer(fi) &&
584 !(PyUnicode_Check(fi) || PyBytes_Check(fi))) {
606 if (!PyErr_Occurred())
607 PyErr_SetString(PyExc_TypeError,
"argument is not iterable");
618 ItemGetter* getter = GetGetter(args);
628 bool fill_ok =
FillVector(self, args, getter);
652 PyObject* pydata = CallPyObjMethod(self,
"__real_data");
662 long clen = PyLong_AsLong(pylen);
676 PyObject* pydata = VectorData(self,
nullptr);
678 PyObject* newarr = PyObject_Call(arrcall, args, kwargs);
695#if PY_VERSION_HEX >= 0x030e0000
711 vi->
vi_stride = PyLong_AsLong(pyvalue_size);
712 Py_DECREF(pyvalue_size);
718 if (PyLong_Check(pyvalue_type)) {
759 PyObject* pydata = CallPyObjMethod(
v,
"__real_data");
775 Py_XDECREF(pyvalue_type);
778 vi->
ii_len = PySequence_Size(
v);
780 PyObject_GC_Track(vi);
786 if (PySlice_Check(
index)) {
788 PyErr_SetString(PyExc_TypeError,
"unsubscriptable object");
793 PyObject* nseq = PyObject_CallObject(pyclass,
nullptr);
795 Py_ssize_t start, stop, step;
797 &start, &stop, &step);
799 const Py_ssize_t nlen = PySequence_Size((
PyObject*)self);
800 if (!AdjustSlice(nlen, start, stop, step))
803 const Py_ssize_t sign = step < 0 ? -1 : 1;
804 for (Py_ssize_t i = start; i * sign < stop * sign; i += step) {
805 PyObject* pyidx = PyLong_FromSsize_t(i);
808 CallPyObjMethod(nseq,
"push_back", item);
825 PyErr_Format(PyExc_TypeError,
826 "require object of type std::vector<bool>, but %s given",
832 PyErr_SetString(PyExc_TypeError,
"unsubscriptable object");
836 if (PySlice_Check(idx)) {
838 PyObject* nseq = PyObject_CallObject(pyclass,
nullptr);
840 Py_ssize_t start, stop, step;
841 PySlice_GetIndices((
PyObject*)idx, PyObject_Length((
PyObject*)self), &start,
843 const Py_ssize_t nlen = PySequence_Size((
PyObject*)self);
844 if (!AdjustSlice(nlen, start, stop, step))
847 const Py_ssize_t sign = step < 0 ? -1 : 1;
848 for (Py_ssize_t i = start; i * sign < stop * sign; i += step) {
849 PyObject* pyidx = PyLong_FromSsize_t(i);
852 CallPyObjMethod(nseq,
"push_back", item);
864 int index = (
int)PyLong_AsLong(pyindex);
869 std::vector<bool>* vb = (std::vector<bool>*)self->
GetObject();
872 if (
bool((*vb)[
index]))
881 PyErr_Format(PyExc_TypeError,
882 "require object of type std::vector<bool>, but %s given",
888 PyErr_SetString(PyExc_TypeError,
"unsubscriptable object");
894 if (!PyArg_ParseTuple(args,
const_cast<char*
>(
"Oi:__setitem__"), &idx, &bval))
901 int index = (
int)PyLong_AsLong(pyindex);
906 std::vector<bool>* vb = (std::vector<bool>*)self->
GetObject();
920 if (args && PyTuple_GET_SIZE(args) == 1 &&
921 PySequence_Check(PyTuple_GET_ITEM(args, 0))) {
927 PyObject* items = PyTuple_GET_ITEM(args, 0);
928 Py_ssize_t fillsz = PySequence_Size(items);
929 if (PySequence_Size(self) != fillsz) {
930 PyErr_Format(PyExc_ValueError,
931 "received sequence of size %zd where %zd expected", fillsz,
932 PySequence_Size(self));
938 for (Py_ssize_t i = 0; i < fillsz; ++i) {
939 PyObject* item = PySequence_GetItem(items, i);
942 PyObject_CallFunctionObjArgs(si_call,
index, item,
nullptr);
977 for (Py_ssize_t i = 0; i < PySequence_Size(pairs); ++i) {
978 PyObject* pair = PySequence_GetItem(pairs, i);
980 if (pair && PySequence_Check(pair) && PySequence_Size(pair) == 2) {
981 PyObject* key = PySequence_GetItem(pair, 0);
983 sires = PyObject_CallFunctionObjArgs(si_call, key,
value,
nullptr);
991 if (!PyErr_Occurred())
994 "Failed to fill map (argument not a dict or sequence of pairs)");
1012 if (PyTuple_GET_SIZE(args) == 1 &&
1013 PyMapping_Check(PyTuple_GET_ITEM(args, 0)) &&
1014 !(PyTuple_Check(PyTuple_GET_ITEM(args, 0)) ||
1015 PyList_Check(PyTuple_GET_ITEM(args, 0)))) {
1016 PyObject* assoc = PyTuple_GET_ITEM(args, 0);
1019 PyObject* items = PyMapping_Items(assoc);
1020 if (items && PySequence_Check(items)) {
1034 if (PyTuple_GET_SIZE(args) == 1 &&
1035 PySequence_Check(PyTuple_GET_ITEM(args, 0)))
1036 return MapFromPairs(self, PyTuple_GET_ITEM(args, 0));
1043 Py_DECREF(realInit);
1054 PyObject* iter = CallPyObjMethod(self,
"find", obj);
1058 if (!PyObject_RichCompareBool(iter, end, Py_EQ)) {
1070 Py_INCREF(Py_False);
1080 if (PyTuple_GET_SIZE(args) == 1 && PySet_Check(PyTuple_GET_ITEM(args, 0))) {
1081 PyObject* pyset = PyTuple_GET_ITEM(args, 0);
1088 PyObject* iter = PyObject_GetIter(pyset);
1090 PyObject* ins_call = PyObject_GetAttrString(self, (
char*)
"insert");
1092 IterItemGetter getter{iter};
1098 PyObject_CallFunctionObjArgs(ins_call, item,
nullptr);
1101 Py_DECREF(ins_call);
1106 item = getter.get();
1108 Py_DECREF(ins_call);
1118 Py_DECREF(realInit);
1126static const ptrdiff_t PS_END_ADDR = 7;
1127static const ptrdiff_t PS_FLAG_ADDR = 11;
1128static const ptrdiff_t PS_COLL_ADDR = 13;
1139 Py_ssize_t sz = PySequence_Size(self);
1144 PyObject* lliter = Py_TYPE(iter)->tp_iter(iter);
1152 PyErr_SetString(PyExc_TypeError,
1153 "unrecognized iterator type for low level views");
1174 PyTypeObject* itype = Py_TYPE(iter);
1175 if (!PyIter_Check(iter)) {
1177 itype->tp_iternext = (iternextfunc)STLIterNext;
1179 (PyCFunction)STLIterNext, METH_NOARGS);
1180 if (!itype->tp_iter) {
1181 itype->tp_iter = (getiterfunc)PyObject_SelfIter;
1183 (PyCFunction)PyObject_SelfIter, METH_NOARGS);
1185 PyType_Modified(itype);
1189 auto& dmc = ((
CPPInstance*)iter)->GetDatamemberCache();
1190 dmc.push_back(std::make_pair(PS_END_ADDR, end));
1193 Py_INCREF(Py_False);
1194 dmc.push_back(std::make_pair(PS_FLAG_ADDR, Py_False));
1198 dmc.push_back(std::make_pair(PS_COLL_ADDR, self));
1220 ii->
ii_len = PySequence_Size(
c);
1222 PyObject_GC_Track(ii);
1259 long idx = PyLong_AsLong(pyindex);
1260 if (idx == -1 && PyErr_Occurred())
1264 PyErr_SetString(PyExc_TypeError,
"unsubscriptable object");
1270 else if ((
int)idx == 1)
1274 PyErr_SetString(PyExc_IndexError,
"out of bounds");
1288 Py_DECREF(realInit);
1289 if (
result && PyTuple_GET_SIZE(args) == 1 &&
1303 return !PyObject_RichCompareBool(one, other, Py_EQ);
1305static inline PyObject* cpyrt_PyString_FromCppString(std::string_view s,
1306 bool native =
true) {
1308 return PyBytes_FromStringAndSize(s.data(), s.size());
1309 return PyUnicode_FromStringAndSize(s.data(), s.size());
1312static inline PyObject* cpyrt_PyString_FromCppString(std::wstring_view s,
1313 bool native =
true) {
1314 PyObject* pyobj = PyUnicode_FromWideChar(s.data(), s.size());
1315 if (pyobj && native) {
1316 PyObject* pybytes = PyUnicode_AsEncodedString(pyobj,
"UTF-8",
"strict");
1323#define CPPJIT_IMPL_STRING_PYTHONIZATION(type, name) \
1324 static inline PyObject* name##StringGetData(PyObject* self, \
1325 bool native = true) { \
1326 if (cpyrt::CPPInstance_Check(self)) { \
1327 type* obj = ((type*)((CPPInstance*)self)->GetObject()); \
1329 return cpyrt_PyString_FromCppString(*obj, native); \
1331 PyErr_Format(PyExc_TypeError, "object mismatch (%s expected)", #type); \
1335 PyObject* name##StringStr(PyObject* self) { \
1336 PyObject* pyobj = name##StringGetData(self, false); \
1340 PyObject* pybytes = name##StringGetData(self, true); \
1342 pyobj = PyObject_Str(pybytes); \
1343 Py_DECREF(pybytes); \
1349 PyObject* name##StringBytes(PyObject* self) { \
1350 return name##StringGetData(self, true); \
1353 PyObject* name##StringRepr(PyObject* self) { \
1354 PyObject* data = name##StringGetData(self, true); \
1356 PyObject* repr = PyObject_Repr(data); \
1363 PyObject* name##StringIsEqual(PyObject* self, PyObject* obj) { \
1364 PyObject* data = name##StringGetData(self, PyBytes_Check(obj)); \
1366 PyObject* result = PyObject_RichCompare(data, obj, Py_EQ); \
1373 PyObject* name##StringIsNotEqual(PyObject* self, PyObject* obj) { \
1374 PyObject* data = name##StringGetData(self, PyBytes_Check(obj)); \
1376 PyObject* result = PyObject_RichCompare(data, obj, Py_NE); \
1384#define CPPJIT_IMPL_STRING_PYTHONIZATION_CMP(type, name) \
1385 CPPJIT_IMPL_STRING_PYTHONIZATION(type, name) \
1386 PyObject* name##StringCompare(PyObject* self, PyObject* obj) { \
1387 PyObject* data = name##StringGetData(self, PyBytes_Check(obj)); \
1390 result = PyObject_Compare(data, obj); \
1393 if (PyErr_Occurred()) \
1395 return PyLong_FromLong(result); \
1402static inline std::string* GetSTLString(
CPPInstance* self) {
1404 PyErr_SetString(PyExc_TypeError,
"std::string object expected");
1408 std::string* obj = (std::string*)self->
GetObject();
1410 PyErr_SetString(PyExc_ReferenceError,
"attempt to access a null-pointer");
1416 std::string* obj = GetSTLString(self);
1420 char* keywords[] = {(
char*)
"encoding", (
char*)
"errors", (
char*)
nullptr};
1421 const char* encoding =
nullptr;
1422 const char* errors =
nullptr;
1423 if (!PyArg_ParseTupleAndKeywords(args, kwds,
const_cast<char*
>(
"s|s"),
1424 keywords, &encoding, &errors))
1427 return PyUnicode_Decode(obj->data(), obj->size(), encoding, errors);
1431 std::string* obj = GetSTLString(self);
1435 const char* needle = PyUnicode_AsUTF8(pyobj);
1439 if (obj->find(needle) != std::string::npos) {
1448 std::string* obj = GetSTLString(self);
1456 if (2 <= PyTuple_GET_SIZE(args) &&
1457 PyUnicode_Check(PyTuple_GET_ITEM(args, 0))) {
1458 PyObject* pystr = PyUnicode_FromStringAndSize(obj->data(), obj->size());
1459 PyObject* meth = PyObject_GetAttrString(pystr, (
char*)
"replace");
1467 PyObject_GetAttrString((
PyObject*)self, (
char*)
"__cpp_replace");
1470 Py_DECREF(cppreplace);
1474 PyErr_SetString(PyExc_AttributeError,
1475 "\'std::string\' object has no attribute \'replace\'");
1479#define CPYRT_STRING_FINDMETHOD(name, cppname, pyname) \
1480 PyObject* STLString##name(CPPInstance* self, PyObject* args, \
1482 std::string* obj = GetSTLString(self); \
1486 PyObject* cppmeth = \
1487 PyObject_GetAttrString((PyObject*)self, (char*)#cppname); \
1489 PyObject* result = PyObject_Call(cppmeth, args, nullptr); \
1490 Py_DECREF(cppmeth); \
1492 if (PyLongOrInt_AsULong64(result) == \
1493 (PY_ULONG_LONG)std::string::npos) { \
1494 Py_DECREF(result); \
1495 return PyLong_FromLong(-1); \
1502 PyObject* pystr = PyUnicode_FromStringAndSize(obj->data(), obj->size()); \
1503 PyObject* pymeth = PyObject_GetAttrString(pystr, (char*)#pyname); \
1505 PyObject* result = PyObject_CallObject(pymeth, args); \
1506 Py_DECREF(pymeth); \
1518 std::string* obj = GetSTLString(self);
1522 PyObject* pystr = PyUnicode_FromStringAndSize(obj->data(), obj->size());
1528Py_hash_t STLStringHash(
PyObject* self) {
1532 Py_hash_t
h = PyUnicode_Type.tp_hash(
data);
1544 PyObject *strbuf =
nullptr, *newArgs =
nullptr;
1545 if (PyTuple_GET_SIZE(args) == 1) {
1546 PyObject* arg0 = PyTuple_GET_ITEM(args, 0);
1547 if (PyUnicode_Check(arg0)) {
1549 strbuf = PyUnicode_AsEncodedString(arg0,
"UTF-8",
"strict");
1550 newArgs = PyTuple_New(1);
1552 PyTuple_SET_ITEM(newArgs, 0, strbuf);
1553 }
else if (PyBytes_Check(arg0)) {
1561 PyObject_Call(realInit, newArgs ? newArgs : args, nullptr);
1563 Py_XDECREF(newArgs);
1564 Py_DECREF(realInit);
1568 if (
result && self && strbuf)
1580 bool mustIncrement =
true;
1583 auto& dmc = ((
CPPInstance*)self)->GetDatamemberCache();
1584 for (
auto&
p : dmc) {
1585 if (
p.first == PS_END_ADDR) {
1588 }
else if (
p.first == PS_FLAG_ADDR) {
1589 mustIncrement =
p.second == Py_True;
1590 if (!mustIncrement) {
1591 Py_DECREF(
p.second);
1602 if (!PyObject_RichCompareBool(last, self, Py_EQ)) {
1603 bool iter_valid =
true;
1604 if (mustIncrement) {
1610 static PyObject* dummy = PyLong_FromLong(1l);
1613 iter_valid = iter && PyObject_RichCompareBool(last, self, Py_NE);
1627 PyErr_SetString(PyExc_StopIteration,
"");
1632#define COMPLEX_METH_GETSET(name, cppname) \
1633 static PyObject* name##ComplexGet(PyObject* self, void*) { \
1634 return PyObject_CallMethodNoArgs(self, cppname); \
1636 static int name##ComplexSet(PyObject* self, PyObject* value, void*) { \
1637 PyObject* result = PyObject_CallMethodOneArg(self, cppname, value); \
1639 Py_DECREF(result); \
1644 PyGetSetDef name##Complex{(char*)#name, (getter)name##ComplexGet, \
1645 (setter)name##ComplexSet, nullptr, nullptr};
1654 double r = PyFloat_AsDouble(real);
1656 if (
r == -1. && PyErr_Occurred())
1662 double i = PyFloat_AsDouble(imag);
1664 if (i == -1. && PyErr_Occurred())
1667 return PyComplex_FromDoubles(
r, i);
1674 double r = PyFloat_AsDouble(real);
1676 if (
r == -1. && PyErr_Occurred())
1682 double i = PyFloat_AsDouble(imag);
1684 if (i == -1. && PyErr_Occurred())
1687 std::ostringstream s;
1688 s <<
'(' <<
r <<
'+' << i <<
"j)";
1689 return PyUnicode_FromString(s.str().c_str());
1693 return PyFloat_FromDouble(((std::complex<double>*)self->
GetObject())->real());
1697 double d = PyFloat_AsDouble(
value);
1698 if (
d == -1.0 && PyErr_Occurred())
1700 ((std::complex<double>*)self->
GetObject())->real(
d);
1704PyGetSetDef ComplexDReal{(
char*)
"real", (getter)ComplexDRealGet,
1705 (setter)ComplexDRealSet,
nullptr,
nullptr};
1708 return PyFloat_FromDouble(((std::complex<double>*)self->
GetObject())->imag());
1712 double d = PyFloat_AsDouble(
value);
1713 if (
d == -1.0 && PyErr_Occurred())
1715 ((std::complex<double>*)self->
GetObject())->imag(
d);
1719PyGetSetDef ComplexDImag{(
char*)
"imag", (getter)ComplexDImagGet,
1720 (setter)ComplexDImagSet,
nullptr,
nullptr};
1723 double r = ((std::complex<double>*)self->
GetObject())->real();
1724 double i = ((std::complex<double>*)self->
GetObject())->imag();
1725 return PyComplex_FromDoubles(
r, i);
1736 const std::vector<PyObject*>&
v) {
1739 PyTuple_SET_ITEM(args, 0, pyclass);
1741 PyTuple_SET_ITEM(args, 1, pyname);
1743 bool pstatus =
true;
1744 for (
auto pythonizor :
v) {
1775 const bool has_value_semantics = IsTemplatedSTLClass(
name,
"optional") ||
1776 IsTemplatedSTLClass(
name,
"expected");
1779 if (has_value_semantics)
1792 const char* pybool_name =
"__bool__";
1815 PyObject* size_attr = (sizeDirect || ifaceDirect)
1822 Py_DECREF(size_attr);
1823 size_attr =
nullptr;
1825 bool isContainer = size_attr &&
1828 if (size_attr && !isContainer) {
1839 auto isIntegral = [](
const std::string& tn) {
1840 static const char*
const integrals[] = {
1841 "char",
"signed char",
"unsigned char",
"short",
1842 "unsigned short",
"int",
"unsigned int",
"long",
1843 "unsigned long",
"long long",
"unsigned long long"};
1844 for (
const char* i : integrals)
1850 std::vector<interop::TCppMethod_t> sizes;
1851 std::deque<interop::TCppScope_t> todo{klass->
fCppType};
1852 while (sizes.empty() && !todo.empty()) {
1866 Py_XDECREF(size_attr);
1873 if (!IsTemplatedSTLClass(
name,
"vector") &&
1874 !((PyTypeObject*)pyclass)->tp_iter) {
1878 const auto& methods =
1880 if (!methods.empty()) {
1887 if (resname.find(
"iterator") == std::string::npos)
1894 ((PyTypeObject*)pyclass)->tp_iter = (getiterfunc)STLSequenceIter;
1902 if (resolved.back() ==
'*' &&
1904 ((PyTypeObject*)pyclass)->tp_iter = (getiterfunc)LLSequenceIter;
1906 (PyCFunction)LLSequenceIter, METH_NOARGS);
1911 if (!((PyTypeObject*)pyclass)->tp_iter &&
1919 ((PyTypeObject*)pyclass)->tp_iter = (getiterfunc)index_iter;
1967 bool stdclass =
false;
1980 std::vector<interop::TCppScope_t> datamems;
1982 if (!datamems.empty()) {
1983 std::string rname =
name;
1986 std::ostringstream initdef;
1987 initdef <<
"namespace __cppjit_internal {\n"
1988 <<
"void init_" << rname <<
"(" <<
name <<
"** self";
1989 bool codegen_ok =
true;
1990 std::vector<std::string> arg_types, arg_names, arg_defaults;
1991 const int ndata = datamems.size();
1992 arg_types.reserve(ndata);
1993 arg_names.reserve(ndata);
1994 arg_defaults.reserve(ndata);
1995 for (
auto data : datamems) {
2000 const std::string& res =
2009 if (res_clean ==
"internal_enum_type_t")
2012 if (res.rfind(
']') == std::string::npos &&
2013 res.rfind(
')') == std::string::npos) {
2015 arg_types.push_back(res_clean + cpd);
2017 arg_types.push_back(
"const " + res_clean +
"&");
2019 if ((!cpd.empty() && cpd.back() ==
'*') ||
2021 arg_defaults.push_back(
"0");
2025 arg_defaults.push_back(res_clean +
"{}");
2034 if (codegen_ok && !arg_types.empty()) {
2035 bool defaults_ok = arg_defaults.size() == arg_types.size();
2036 for (std::vector<std::string>::size_type i = 0; i < arg_types.size();
2038 initdef <<
", " << arg_types[i] <<
" " << arg_names[i];
2040 initdef <<
" = " << arg_defaults[i];
2042 initdef <<
") {\n *self = new " <<
name <<
"{";
2043 for (std::vector<std::string>::size_type i = 0; i < arg_names.size();
2047 initdef << arg_names[i];
2049 initdef <<
"};\n} }";
2053 const auto& methods =
2055 if (methods.size()) {
2067 if (IsTemplatedSTLClass(
name,
"span")) {
2079 if (IsTemplatedSTLClass(
name,
"vector")) {
2082 if (!sVectorBoolTypeID)
2084 if (klass->
fCppType == sVectorBoolTypeID) {
2086 (PyCFunction)VectorBoolGetItem, METH_O);
2088 (PyCFunction)VectorBoolSetItem);
2093 METH_VARARGS | METH_KEYWORDS);
2108 ((PyTypeObject*)pyclass)->tp_iter = (getiterfunc)vector_iter;
2112 METH_VARARGS | METH_KEYWORDS);
2126 METH_VARARGS | METH_KEYWORDS );
2129 PyObject* pyvalue_type = PyLong_FromVoidPtr(vtype.data);
2131 Py_DECREF(pyvalue_type);
2135 Py_DECREF(pyvalue_type);
2140 PyObject* pyvalue_size = PyLong_FromSsize_t(typesz);
2142 Py_DECREF(pyvalue_size);
2147 else if (IsTemplatedSTLClass(
name,
"array")) {
2151 METH_VARARGS | METH_KEYWORDS);
2154 else if (IsTemplatedSTLClass(
name,
"map") ||
2155 IsTemplatedSTLClass(
name,
"unordered_map")) {
2159 METH_VARARGS | METH_KEYWORDS);
2167 (PyCFunction)STLContainsWithFind, METH_O);
2170 else if (IsTemplatedSTLClass(
name,
"set")) {
2174 METH_VARARGS | METH_KEYWORDS);
2181 (PyCFunction)STLContainsWithFind, METH_O);
2184 else if (IsTemplatedSTLClass(
name,
"pair")) {
2191 if (IsTemplatedSTLClass(
name,
"shared_ptr") ||
2192 IsTemplatedSTLClass(
name,
"unique_ptr")) {
2195 METH_VARARGS | METH_KEYWORDS);
2198 else if (!((PyTypeObject*)pyclass)->tp_iter &&
2199 (
name.find(
"iterator") != std::string::npos ||
2201 ((PyTypeObject*)pyclass)->tp_iternext = (iternextfunc)STLIterNext;
2204 ((PyTypeObject*)pyclass)->tp_iter = (getiterfunc)PyObject_SelfIter;
2209 else if (
name ==
"std::basic_string<char>" ||
2210 name ==
"std::basic_string<char,std::char_traits<char>,std::"
2211 "allocator<char> >" ||
2212 name ==
"std::basic_string<char, std::char_traits<char>, "
2213 "std::allocator<char> >" ||
2214 name ==
"std::__1::basic_string<char>" ||
2215 name ==
"std::string") {
2236 METH_VARARGS | METH_KEYWORDS);
2239 METH_VARARGS | METH_KEYWORDS);
2242 METH_VARARGS | METH_KEYWORDS);
2245 METH_VARARGS | METH_KEYWORDS);
2250 ((PyTypeObject*)pyclass)->tp_hash = (hashfunc)STLStringHash;
2253 else if (
name ==
"std::basic_string_view<char>" ||
2254 name ==
"std::basic_string_view<char,std::char_traits<char> >" ||
2255 name ==
"std::basic_string_view<char, std::char_traits<char> >" ||
2257 "std::__1::basic_string_view<char>" ||
2258 name ==
"std::string_view") {
2262 METH_VARARGS | METH_KEYWORDS);
2281 else if (
name ==
"std::basic_string<wchar_t,std::char_traits<wchar_t>,std::"
2282 "allocator<wchar_t> >" ||
2283 name ==
"std::basic_string<wchar_t, std::char_traits<wchar_t>, "
2284 "std::allocator<wchar_t> >" ||
2285 name ==
"basic_string<wchar_t,char_traits<wchar_t>,allocator<wchar_"
2287 name ==
"std::basic_string<wchar_t,char_traits<wchar_t>,allocator<"
2289 name ==
"std::__1::basic_string<wchar_t,std::__1::char_traits<wchar_"
2290 "t>,std::__1::allocator<wchar_t> >" ||
2291 name ==
"std::wstring") {
2306 else if (
name ==
"complex<double>" ||
name ==
"std::complex<double>") {
2308 PyObject_SetAttrString(
2310 PyDescr_NewGetSet((PyTypeObject*)pyclass, &ComplexDReal));
2312 PyObject_SetAttrString(
2314 PyDescr_NewGetSet((PyTypeObject*)pyclass, &ComplexDImag));
2321 else if (IsTemplatedSTLClass(
name,
"complex")) {
2323 PyObject_SetAttrString(
2325 PyDescr_NewGetSet((PyTypeObject*)pyclass, &realComplex));
2327 PyObject_SetAttrString(
2329 PyDescr_NewGetSet((PyTypeObject*)pyclass, &imagComplex));
2343 bool bUserOk =
true;
2347 res = PyObject_CallMethodObjArgs(pyclass, exPythonize, pyclass, pyname,
2349 bUserOk = (
bool)res;
2351 res = PyObject_CallFunctionObjArgs(func, pyclass, pyname,
nullptr);
2353 bUserOk = (
bool)res;
2366 bool pstatus =
true;
2369 if (!outer_scope.empty()) {
2370 auto p = pyzMap.find(outer_scope);
2371 if (
p != pyzMap.end()) {
2372 PyObject* subname = PyUnicode_FromString(
2373 name.substr(outer_scope.size() + 2, std::string::npos).c_str());
2380 auto p = pyzMap.find(
"");
2381 if (
p != pyzMap.end())
bool PyUnstable_Object_IsUniqueReferencedTemporary(PyObject *pyobject)
#define CPPJIT_IMPL_STRING_PYTHONIZATION_CMP(type, name)
#define CPYRT_STRING_FINDMETHOD(name, cppname, pyname)
static bool run_pythonizors(PyObject *pyclass, PyObject *pyname, const std::vector< PyObject * > &v)
#define COMPLEX_METH_GETSET(name, cppname)
void FillVector(std::vector< double > &v, int size, T *a)
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void data
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t r
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t result
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t index
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t attr
interop::TCppScope_t ObjectIsA(bool check_smart=true) const
Utility::PyOperators * fOperators
interop::TCppScope_t fCppType
CoordSystem::Scalar get(DisplacementVector2D< CoordSystem, Tag > const &p)
std::string extract_namespace(const std::string &name)
std::string clean_type(const std::string &cppname, bool template_strip=true, bool const_strip=true)
std::string compound(const std::string &name)
void cppscope_to_legalname(std::string &cppscope)
bool AddToClass(PyObject *pyclass, const char *label, PyCFunction cfunc, int flags=METH_VARARGS)
Py_ssize_t GetBuffer(PyObject *pyobject, char tc, int size, void *&buf, bool check=true)
PyObject * GetPythonizeHook(PyObject *pyclass)
PyObject * ExplicitPythonizeHookName(PyObject *pyclass)
bool CPPOverload_Check(T *object)
CPYRT_EXTERN Converter * CreateConverter(const std::string &name, cdims_t=0)
bool LowLevelView_Check(T *object)
PyObject * GetScopeProxy(interop::TCppScope_t)
std::set< std::string > gIteratorTypes
bool CPPScope_Check(T *object)
bool CPPInstance_Check(T *object)
PyTypeObject VectorIter_Type
PyTypeObject IndexIter_Type
std::unordered_map< std::string, std::vector< PyObject * > > & pythonizations()
bool Pythonize(PyObject *pyclass, interop::TCppScope_t scope)
static PyObject * GetAttrDirect(PyObject *pyclass, PyObject *pyname)
void GetDatamembers(TCppScope_t scope, std::vector< TCppScope_t > &datamembers)
TCppType_t GetTypeFromScope(TCppScope_t klass)
std::string GetTypeAsString(TCppType_t type)
TCppType_t GetDatamemberType(TCppScope_t data)
bool IsBuiltin(const std::string &type_name)
std::string GetName(TCppScope_t)
std::string ResolveName(const std::string &cppitem_name)
TCppScope_t GetParentScope(TCppScope_t scope)
std::string GetMethodReturnTypeAsString(TCppMethod_t)
bool IsStaticDatamember(TCppScope_t var)
TCppIndex_t GetNumBases(TCppScope_t klass)
TCppScope_t GetNamed(const std::string &scope_name, TCppScope_t parent_scope=TCppScope_t{})
size_t SizeOfType(TCppType_t type)
Cpp::FuncRef TCppMethod_t
bool IsPublicData(TCppScope_t var)
TCppScope_t GetBaseScope(TCppScope_t klass, TCppIndex_t ibase)
bool IsPointerType(TCppType_t type)
size_t SizeOf(TCppScope_t klass)
TCppType_t ResolveType(TCppType_t cppitem_name)
TCppScope_t GetGlobalScope()
bool Compile(const std::string &code, bool silent=false)
std::vector< TCppMethod_t > GetMethodsFromName(TCppScope_t scope, const std::string &name)
bool IsDefaultConstructable(TCppScope_t scope)
bool IsNamespace(TCppScope_t scope)
TCppScope_t GetScopeFromType(TCppType_t type)
TCppScope_t GetScope(const std::string &scope_name, TCppScope_t parent_scope=TCppScope_t{})
std::string GetFinalName(TCppScope_t type)
bool IsSmartPtr(TCppScope_t klass)
bool IsAggregate(TCppScope_t type)
std::string GetScopedFinalName(TCppScope_t type)
bool IsEnumType(TCppType_t type)
PyObject_HEAD PyObject * ii_container
interop::TCppScope_t vi_klass