88#if PY_VERSION_HEX >= 0x030e0000
109#define ct_c_uint32 10
112#define ct_c_longlong 13
113#define ct_c_ulonglong 14
115#define ct_c_double 16
116#define ct_c_longdouble 17
117#define ct_c_char_p 18
118#define ct_c_wchar_p 19
119#define ct_c_void_p 20
120#define ct_c_fcomplex 21
121#define ct_c_complex 22
122#define ct_c_pointer 23
123#define ct_c_funcptr 24
129 "c_bool",
"c_char",
"c_wchar",
"c_byte",
"c_ubyte",
130 "c_short",
"c_ushort",
"c_uint16",
"c_int",
"c_uint",
131 "c_uint32",
"c_long",
"c_ulong",
"c_longlong",
"c_ulonglong",
132 "c_float",
"c_double",
"c_longdouble",
"c_char_p",
"c_wchar_p",
133 "c_void_p",
"c_fcomplex",
"c_complex",
"_Pointer",
"_CFuncPtr",
134 "c_int16",
"c_int32"};
143 static PyObject* ctmod = PyImport_ImportModule(
"ctypes");
150 ct_t = (PyTypeObject*)PyObject_GetAttrString(ctmod,
gCTypesNames[nidx]);
162 static PyObject* ctmod = PyImport_ImportModule(
"ctypes");
170 cpt_t = (PyTypeObject*)PyObject_GetAttrString(ctmod,
"c_char_p");
174 PyObject* ptrcreat = PyObject_GetAttrString(ctmod,
"POINTER");
176 (PyTypeObject*)PyObject_CallFunctionObjArgs(ptrcreat, ct_t, NULL);
189 static PyTypeObject* pycarg_type =
nullptr;
191 PyObject* ctmod = PyImport_ImportModule(
"ctypes");
196 (PyTypeObject*)PyObject_GetAttrString(ctmod,
"c_int");
197 PyObject* cobj = ct_t->tp_new(ct_t,
nullptr,
nullptr);
198 PyObject* byref = PyObject_GetAttrString(ctmod,
"byref");
199 PyObject* pyptr = PyObject_CallFunctionObjArgs(byref, cobj, NULL);
203 pycarg_type = Py_TYPE(pyptr);
208 return Py_TYPE(pyobject) == pycarg_type;
211#if PY_VERSION_HEX < 0x30d0000
213 static PyTypeObject* cstgdict_type =
nullptr;
214 if (!cstgdict_type) {
217 if (ct_int && ct_int->tp_dict) {
218 cstgdict_type = Py_TYPE(ct_int->tp_dict);
222 PyTypeObject* pytype = Py_TYPE(pyobject);
223 if (pytype->tp_dict && Py_TYPE(pytype->tp_dict) == cstgdict_type)
232 PyTypeObject* DictRemover_Type;
233 PyTypeObject* PyCArg_Type;
234 PyTypeObject* PyCField_Type;
235 PyTypeObject* PyCThunk_Type;
236 PyTypeObject* StructParam_Type;
237 PyTypeObject* PyCType_Type;
238 PyTypeObject* PyCStructType_Type;
239 PyTypeObject* UnionType_Type;
240 PyTypeObject* PyCPointerType_Type;
242} _cppjit_ctypes_state;
247 static _cppjit_ctypes_state* state =
nullptr;
249 PyObject* ctmod = PyImport_AddModule(
252 state = (_cppjit_ctypes_state*)PyModule_GetState(ctmod);
256 if (state && (PyObject_IsInstance((
PyObject*)Py_TYPE(pyobject),
258 PyObject_IsInstance((
PyObject*)Py_TYPE(pyobject),
259 (
PyObject*)state->PyCPointerType_Type))) {
277 std::ostringstream attr_name;
278 attr_name <<
"__" << ref;
280 PyObject_SetAttrString(holder, (
char*)attr_name.str().c_str(),
target);
289 std::ostringstream attr_name;
290 attr_name <<
"__" << ref;
292 PyObject_GetAttrString(holder, (
char*)attr_name.str().c_str());
307 bool accept_rvalue =
false) {
319 else if (klass && PyTuple_CheckExact(castobj)) {
324 (
CPPInstance*)PyObject_Call(pyclass, castobj, NULL);
347 if (!PyLong_Check(pyobject) || PyLong_CheckExact(pyobject) ||
348 PyBool_Check(pyobject))
350 return PyObject_HasAttr((
PyObject*)Py_TYPE(pyobject),
360 (PyBool_Check(pyobject) ||
381 long l = PyLong_AsLong(pyobject);
383 if (!(
l == 0 ||
l == 1) || PyFloat_Check(pyobject)) {
384 PyErr_SetString(PyExc_ValueError,
385 "boolean value should be bool, or integer 1 or 0");
393#define CPPJIT_PYLONG_AS_TYPE(name, type, limit_low, limit_high) \
394 static inline type cpyrt_PyLong_As##name(PyObject* pyobject) { \
395 if (!PyLong_Check(pyobject)) { \
396 if (pyobject == cpyrt::gDefaultObject) \
398 PyErr_SetString(PyExc_TypeError, \
399 #type " conversion expects an integer object"); \
402 long l = PyLong_AsLong(pyobject); \
403 if (l < limit_low || limit_high < l) { \
404 PyErr_Format(PyExc_ValueError, "integer %ld out of range for " #type, \
425 if (!PyLong_Check(pyobject)) {
428 PyErr_SetString(PyExc_TypeError,
429 "int/long conversion expects an integer object");
433 return (
long)PyLong_AsLong(pyobject);
440 if (!PyLong_Check(pyobject)) {
443 PyErr_SetString(PyExc_TypeError,
444 "int/long conversion expects an integer object");
448 return PyLong_AsLongLong(pyobject);
453 char tc,
int size,
bool check =
true) {
459 if (llview->fBufInfo.itemsize !=
size ||
460 !strchr(llview->fBufInfo.format, tc)) {
461 PyErr_Format(PyExc_TypeError,
462 "could not convert argument to buffer or nullptr");
481 PyErr_Format(PyExc_TypeError,
482 "could not convert argument to buffer or nullptr");
496 bool manage =
true) {
516 if (clName.compare(0, 6,
"std::_") == 0 ||
517 (!clName.empty() && clName[0] ==
'_')) {
518 bool sameTemplate =
false;
521 if (
src &&
src != klass) {
523 std::string::size_type lt = clName.find(
'<');
524 sameTemplate = lt != std::string::npos && srcName.size() > lt &&
525 srcName[lt] ==
'<' &&
526 srcName.compare(0, lt, clName, 0, lt) == 0;
538 PyTypeObject* pytype = (PyTypeObject*)Py_TYPE(pyobject);
539 if (!(pytype == &PyList_Type ||
540 pytype == &PyTuple_Type)) {
558 PyTuple_SET_ITEM(args, 0, pyobject);
562 if (!pytmp && PyTuple_CheckExact(pyobject)) {
566 pytmp = (
CPPInstance*)PyObject_Call(pyscope, pyobject, NULL);
592 PyErr_SetString(PyExc_TypeError,
"C++ type cannot be converted from memory");
600 PyErr_SetString(PyExc_TypeError,
"C++ type cannot be converted to memory");
605#define CPPJIT_IMPL_BASIC_CONVERTER_BODY(name, type, stype, ctype, F1, F2, tc) \
607 type val = (type)F2(pyobject); \
608 if (val == (type) - 1 && PyErr_Occurred()) { \
609 static PyTypeObject* ctypes_type = nullptr; \
610 if (!ctypes_type) { \
611 auto error = cpyrt::Utility::FetchPyError(); \
612 ctypes_type = GetCTypesType(ct_##ctype); \
613 cpyrt::Utility::RestorePyError(error); \
615 if (Py_TYPE(pyobject) == ctypes_type) { \
617 val = *((type*)((cpyrt_tagCDataObject*)pyobject)->b_ptr); \
618 } else if (pyobject == cpyrt::gDefaultObject) { \
624 para.fValue.f##name = val; \
625 para.fTypeCode = tc; \
628#define CPPJIT_IMPL_BASIC_CONVERTER_METHODS(name, type, stype, ctype, F1, F2) \
629 PyObject* cpyrt::name##Converter::FromMemory(void* address) { \
630 return F1((stype) * ((type*)address)); \
633 bool cpyrt::name##Converter::ToMemory(PyObject* value, void* address, \
635 type s = (type)F2(value); \
636 if (s == (type) - 1 && PyErr_Occurred()) { \
637 if (value == cpyrt::gDefaultObject) { \
643 *((type*)address) = (type)s; \
647#define CPPJIT_IMPL_BASIC_CONVERTER_NI(name, type, stype, ctype, F1, F2, tc) \
648 bool cpyrt::name##Converter::SetArg(PyObject* pyobject, Parameter& para, \
649 CallContext* ctxt) { \
650 if (!StrictBool(pyobject, ctxt)) \
652 CPPJIT_IMPL_BASIC_CONVERTER_BODY(name, type, stype, ctype, F1, F2, tc) \
654 CPPJIT_IMPL_BASIC_CONVERTER_METHODS(name, type, stype, ctype, F1, F2)
656#define CPPJIT_IMPL_BASIC_CONVERTER_IB(name, type, stype, ctype, F1, F2, tc) \
657 bool cpyrt::name##Converter::SetArg(PyObject* pyobject, Parameter& para, \
658 CallContext* ctxt) { \
659 if (!ImplicitBool(pyobject, ctxt)) \
661 CPPJIT_IMPL_BASIC_CONVERTER_BODY(name, type, stype, ctype, F1, F2, tc) \
663 CPPJIT_IMPL_BASIC_CONVERTER_METHODS(name, type, stype, ctype, F1, F2)
665#define CPPJIT_IMPL_BASIC_CONVERTER_NB(name, type, stype, ctype, F1, F2, tc) \
666 bool cpyrt::name##Converter::SetArg(PyObject* pyobject, Parameter& para, \
668 if (PyBool_Check(pyobject)) \
670 CPPJIT_IMPL_BASIC_CONVERTER_BODY(name, type, stype, ctype, F1, F2, tc) \
672 CPPJIT_IMPL_BASIC_CONVERTER_METHODS(name, type, stype, ctype, F1, F2)
678 if (PyBytes_Check(pyobject)) {
679 if (PyBytes_GET_SIZE(pyobject) == 1)
680 lchar = (
int)(PyBytes_AsString(pyobject)[0]);
682 PyErr_Format(PyExc_ValueError,
684 PyBytes_GET_SIZE(pyobject));
685 }
else if (PyUnicode_Check(pyobject)) {
686 if (PyUnicode_GET_LENGTH(pyobject) == 1)
687 lchar = (
int)(PyUnicode_AsUTF8(pyobject)[0]);
689 PyErr_Format(PyExc_ValueError,
691 PyUnicode_GET_LENGTH(pyobject));
694 }
else if (!PyFloat_Check(pyobject)) {
695 lchar = (
int)PyLong_AsLong(pyobject);
696 if (lchar == -1 && PyErr_Occurred())
698 else if (!(low <= lchar && lchar <= high)) {
699 PyErr_Format(PyExc_ValueError,
700 "integer to character: value %d not in range [%d,%d]", lchar,
705 PyErr_SetString(PyExc_TypeError,
"char or small int type expected");
711#define CPPJIT_IMPL_REFCONVERTER_FROM_MEMORY(name, ctype) \
712 PyObject* cpyrt::name##RefConverter::FromMemory(void* ptr) { \
714 PyTypeObject* ctypes_type = GetCTypesType(ct_##ctype); \
715 if (!ctypes_type) { \
716 PyErr_SetString(PyExc_RuntimeError, "no ctypes available"); \
719 PyObject* ref = ctypes_type->tp_new(ctypes_type, nullptr, nullptr); \
720 ((cpyrt_tagCDataObject*)ref)->b_ptr = (char*)ptr; \
721 ((cpyrt_tagCDataObject*)ref)->b_needsfree = 0; \
726#define CPPJIT_IMPL_BASIC_CONST_REFCONVERTER(name, type, ctype, F1) \
727 bool cpyrt::Const##name##RefConverter::SetArg( \
728 PyObject* pyobject, Parameter& para, CallContext* ) { \
729 type val = (type)F1(pyobject); \
730 if (val == (type) - 1 && PyErr_Occurred()) { \
731 if (pyobject == cpyrt::gDefaultObject) { \
737 para.fValue.f##name = val; \
738 para.fRef = ¶.fValue.f##name; \
739 para.fTypeCode = 'r'; \
742 CPPJIT_IMPL_REFCONVERTER_FROM_MEMORY(Const##name, ctype)
745#define CPPJIT_IMPL_BASIC_CONST_CHAR_REFCONVERTER(name, type, ctype, low, \
747 bool cpyrt::Const##name##RefConverter::SetArg( \
748 PyObject* pyobject, Parameter& para, CallContext* ) { \
751 type val = (type)ExtractChar(pyobject, #type, low, high); \
752 if (val == (type) - 1 && PyErr_Occurred()) \
754 para.fValue.fLong = val; \
755 para.fTypeCode = 'l'; \
758 CPPJIT_IMPL_REFCONVERTER_FROM_MEMORY(Const##name, ctype)
761#define CPPJIT_IMPL_BASIC_CHAR_CONVERTER(name, type, low, high) \
762 bool cpyrt::name##Converter::SetArg(PyObject* pyobject, Parameter& para, \
766 long val = ExtractChar(pyobject, #type, low, high); \
767 if (val == -1 && PyErr_Occurred()) \
769 para.fValue.fLong = val; \
770 para.fTypeCode = 'l'; \
774 PyObject* cpyrt::name##Converter::FromMemory(void* address) { \
776 return PyUnicode_FromFormat("%c", *((type*)address)); \
779 bool cpyrt::name##Converter::ToMemory(PyObject* value, void* address, \
782 const char* cstr = nullptr; \
783 if (PyBytes_Check(value)) \
784 PyBytes_AsStringAndSize(value, (char**)&cstr, &len); \
786 cstr = cpyrt_PyText_AsStringAndSize(value, &len); \
789 PyErr_Format(PyExc_TypeError, \
790 #type " expected, got string of size %zd", len); \
793 *((type*)address) = (type)cstr[0]; \
796 long l = PyLong_AsLong(value); \
797 if (l == -1 && PyErr_Occurred()) { \
798 if (value == cpyrt::gDefaultObject) { \
804 if (!(low <= l && l <= high)) { \
805 PyErr_Format(PyExc_ValueError, \
806 "integer to character: value %ld not in range [%d,%d]", \
810 *((type*)address) = (type)l; \
826 para.fTypeCode =
'V';
831 para.fTypeCode =
'V';
835 PyErr_SetString(PyExc_TypeError,
836 "use ctypes.c_long for pass-by-ref of longs");
881 PyErr_SetString(PyExc_TypeError,
"use ctypes.c_int for pass-by-ref of ints");
886#define CPPJIT_IMPL_REFCONVERTER(name, ctype, type, code) \
887 bool cpyrt::name##RefConverter::SetArg(PyObject* pyobject, Parameter& para, \
890 if (Py_TYPE(pyobject) == GetCTypesType(ct_##ctype)) { \
891 para.fValue.fVoidp = (void*)((cpyrt_tagCDataObject*)pyobject)->b_ptr; \
892 para.fTypeCode = 'V'; \
895 bool res = CArraySetArg(pyobject, para, code, sizeof(type)); \
897 PyErr_SetString(PyExc_TypeError, \
898 "use ctypes." #ctype " for pass-by-ref of " #type); \
901 para.fTypeCode = 'V'; \
904 CPPJIT_IMPL_REFCONVERTER_FROM_MEMORY(name, ctype)
942PyObject* cpyrt::SCharAsIntConverter::FromMemory(
void* address) {
945 return PyLong_FromLong((
long)*((
signed char*)address));
948PyObject* cpyrt::UCharAsIntConverter::FromMemory(
void* address) {
951 return PyLong_FromLong((
long)*((
unsigned char*)address));
958 if (!PyUnicode_Check(pyobject) || PyUnicode_GET_LENGTH(pyobject) != 1) {
959 PyErr_SetString(PyExc_ValueError,
"single wchar_t character expected");
963 Py_ssize_t res = PyUnicode_AsWideChar(pyobject, &val, 1);
971PyObject* cpyrt::WCharConverter::FromMemory(
void* address) {
972 return PyUnicode_FromWideChar((
const wchar_t*)address, 1);
975bool cpyrt::WCharConverter::ToMemory(
PyObject*
value,
void* address,
977 if (!PyUnicode_Check(
value) || PyUnicode_GET_LENGTH(
value) != 1) {
978 PyErr_SetString(PyExc_ValueError,
"single wchar_t character expected");
982 Py_ssize_t res = PyUnicode_AsWideChar(
value, &val, 1);
985 *((
wchar_t*)address) = val;
993 if (!PyUnicode_Check(pyobject) || PyUnicode_GET_LENGTH(pyobject) != 1) {
994 PyErr_SetString(PyExc_ValueError,
"single char16_t character expected");
998 PyObject* bstr = PyUnicode_AsUTF16String(pyobject);
1003 *(
char16_t*)(PyBytes_AS_STRING(bstr) +
sizeof(char16_t) );
1010PyObject* cpyrt::Char16Converter::FromMemory(
void* address) {
1011 return PyUnicode_DecodeUTF16((
const char*)address,
sizeof(
char16_t),
nullptr,
1015bool cpyrt::Char16Converter::ToMemory(
PyObject*
value,
void* address,
1017 if (!PyUnicode_Check(
value) || PyUnicode_GET_LENGTH(
value) != 1) {
1018 PyErr_SetString(PyExc_ValueError,
"single char16_t character expected");
1026 *((
char16_t*)address) =
1027 *(
char16_t*)(PyBytes_AS_STRING(bstr) +
sizeof(char16_t) );
1036 if (!PyUnicode_Check(pyobject) || 2 < PyUnicode_GET_LENGTH(pyobject)) {
1037 PyErr_SetString(PyExc_ValueError,
"single char32_t character expected");
1041 PyObject* bstr = PyUnicode_AsUTF32String(pyobject);
1046 *(
char32_t*)(PyBytes_AS_STRING(bstr) +
sizeof(char32_t) );
1053PyObject* cpyrt::Char32Converter::FromMemory(
void* address) {
1054 return PyUnicode_DecodeUTF32((
const char*)address,
sizeof(
char32_t),
nullptr,
1058bool cpyrt::Char32Converter::ToMemory(
PyObject*
value,
void* address,
1060 if (!PyUnicode_Check(
value) || 2 < PyUnicode_GET_LENGTH(
value)) {
1061 PyErr_SetString(PyExc_ValueError,
"single char32_t character expected");
1069 *((
char32_t*)address) =
1070 *(
char32_t*)(PyBytes_AS_STRING(bstr) +
sizeof(char32_t) );
1104 if (para.fValue.fULong == (
unsigned long)-1 && PyErr_Occurred())
1106 para.fTypeCode =
'L';
1110PyObject* cpyrt::ULongConverter::FromMemory(
void* address) {
1112 return PyLong_FromUnsignedLong(*((
unsigned long*)address));
1115bool cpyrt::ULongConverter::ToMemory(
PyObject*
value,
void* address,
1119 if (u == (
unsigned long)-1 && PyErr_Occurred()) {
1122 u = (
unsigned long)0;
1126 *((
unsigned long*)address) = u;
1131PyObject* cpyrt::UIntConverter::FromMemory(
void* address) {
1133 return PyLong_FromUnsignedLong(*((
unsigned int*)address));
1136bool cpyrt::UIntConverter::ToMemory(
PyObject*
value,
void* address,
1140 if (u == (
unsigned long)-1 && PyErr_Occurred())
1143 if (u > (
unsigned long)UINT_MAX) {
1144 PyErr_SetString(PyExc_OverflowError,
"value too large for unsigned int");
1148 *((
unsigned int*)address) = (
unsigned int)u;
1154 PyFloat_FromDouble, PyFloat_AsDouble,
'f')
1156 PyFloat_FromDouble, PyFloat_AsDouble, '
d')
1159 c_longdouble, PyFloat_FromDouble,
1160 PyFloat_AsDouble, '
g')
1162cpyrt::ComplexDConverter::ComplexDConverter(
bool keepControl)
1163 : InstanceConverter(interop::GetFullScope("std::complex<
double>"),
1169 const Py_complex& pc = PyComplex_AsCComplex(pyobject);
1170 if (pc.real != -1.0 || !PyErr_Occurred()) {
1178 return this->InstanceConverter::SetArg(pyobject, para, ctxt);
1181PyObject* cpyrt::ComplexDConverter::FromMemory(
void* address) {
1182 std::complex<double>* dc = (std::complex<double>*)address;
1183 return PyComplex_FromDoubles(dc->real(), dc->imag());
1186bool cpyrt::ComplexDConverter::ToMemory(
PyObject*
value,
void* address,
1188 const Py_complex& pc = PyComplex_AsCComplex(
value);
1189 if (pc.real != -1.0 || !PyErr_Occurred()) {
1190 std::complex<double>* dc = (std::complex<double>*)address;
1195 return this->InstanceConverter::ToMemory(
value, address, ctxt);
1217 PyErr_SetString(PyExc_TypeError,
1218 "use ctypes.c_double for pass-by-ref of doubles");
1233 PyErr_SetString(PyExc_SystemError,
"void/unknown arguments can\'t be set");
1245 if (PyErr_Occurred())
1251PyObject* cpyrt::LLongConverter::FromMemory(
void* address) {
1256bool cpyrt::LLongConverter::ToMemory(
PyObject*
value,
void* address,
1260 if (ll == -1 && PyErr_Occurred()) {
1279 if (PyErr_Occurred())
1285PyObject* cpyrt::ULLongConverter::FromMemory(
void* address) {
1287 return PyLong_FromUnsignedLongLong(*(
PY_ULONG_LONG*)address);
1290bool cpyrt::ULLongConverter::ToMemory(
PyObject*
value,
void* address,
1294 if (PyErr_Occurred()) {
1318 exact = (
fEnumName == PyUnicode_AsUTF8(pycppname));
1319 Py_DECREF(pycppname);
1335PyObject* cpyrt::EnumConverter::FromMemory(
void* address) {
1339bool cpyrt::EnumConverter::ToMemory(
PyObject*
value,
void* address,
1344std::string cpyrt::EnumConverter::GetFailureMsg() {
1369 if (PyErr_WarnEx(PyExc_RuntimeWarning,
1370 (
char*)
"string too long for char array (truncated)",
1389PyObject* cpyrt::CStringConverter::FromMemory(
void* address) {
1391 if (address && *(
void**)address) {
1394 return PyUnicode_FromStringAndSize(*(
char**)address,
1397 if (*(
void**)address ==
1399 return PyUnicode_FromStringAndSize((
char*)
fBuffer.data(),
fBuffer.size());
1402 return PyUnicode_FromString(*(
char**)address);
1410bool cpyrt::CStringConverter::ToMemory(
PyObject*
value,
void* address,
1420 if (PyErr_WarnEx(PyExc_RuntimeWarning,
1421 (
char*)
"string too long for char array (truncated)",
1429 void* ptrval = *(
void**)address;
1430 if (ptrval == (
void*)
fBuffer.data()) {
1432 *(
void**)address = (
void*)
fBuffer.data();
1434 }
else if (ptrval &&
HasLifeLine(ctxt, (intptr_t)ptrval)) {
1442 *(
void**)address = (
void*)cstr;
1448 strncpy(*(
char**)address, cstr,
fMaxSize);
1451 strcpy(*(
char**)address, cstr);
1460 Py_ssize_t
len = PyUnicode_GetLength(pyobject);
1461 if (
len == (Py_ssize_t)-1 && PyErr_Occurred())
1465 Py_ssize_t res = PyUnicode_AsWideChar(pyobject,
fBuffer,
len);
1476PyObject* cpyrt::WCStringConverter::FromMemory(
void* address) {
1478 if (address && *(
wchar_t**)address) {
1481 return PyUnicode_FromWideChar(*(
wchar_t**)address, (Py_ssize_t)
fMaxSize);
1483 return PyUnicode_FromWideChar(*(
wchar_t**)address,
1484 wcslen(*(
wchar_t**)address));
1489 return PyUnicode_FromWideChar(&
w, 0);
1492bool cpyrt::WCStringConverter::ToMemory(
PyObject*
value,
void* address,
1495 Py_ssize_t
len = PyUnicode_GetLength(
value);
1496 if (
len == (Py_ssize_t)-1 && PyErr_Occurred())
1501 if (PyErr_WarnEx(PyExc_RuntimeWarning,
1502 (
char*)
"string too long for wchar_t array (truncated)",
1506 Py_ssize_t res = -1;
1507 if (
fMaxSize != std::wstring::npos)
1509 PyUnicode_AsWideChar(
value, *(
wchar_t**)address, (Py_ssize_t)
fMaxSize);
1512 res = PyUnicode_AsWideChar(
value, *(
wchar_t**)address,
len);
1520#define CPYRT_WIDESTRING_CONVERTER(name, type, encode, decode, snull) \
1521 bool cpyrt::name##Converter::SetArg(PyObject* pyobject, Parameter& para, \
1524 PyObject* bstr = encode(pyobject); \
1528 Py_ssize_t len = PyBytes_GET_SIZE(bstr) - sizeof(type) ; \
1529 fBuffer = (type*)realloc(fBuffer, len + sizeof(type)); \
1530 memcpy(fBuffer, PyBytes_AS_STRING(bstr) + sizeof(type) , len); \
1533 fBuffer[len / sizeof(type)] = snull; \
1534 para.fValue.fVoidp = (void*)fBuffer; \
1535 para.fTypeCode = 'p'; \
1539 PyObject* cpyrt::name##Converter::FromMemory(void* address) { \
1541 if (address && *(type**)address) { \
1542 if (fMaxSize != std::wstring::npos) \
1543 return decode(*(const char**)address, \
1544 (Py_ssize_t)fMaxSize * sizeof(type), nullptr, nullptr); \
1545 return decode(*(const char**)address, \
1546 std::char_traits<type>::length(*(type**)address) * \
1548 nullptr, nullptr); \
1553 return decode((const char*)&w, 0, nullptr, nullptr); \
1556 bool cpyrt::name##Converter::ToMemory(PyObject* value, void* address, \
1559 PyObject* bstr = encode(value); \
1563 Py_ssize_t len = PyBytes_GET_SIZE(bstr) - sizeof(type) ; \
1564 Py_ssize_t maxbytes = (Py_ssize_t)fMaxSize * sizeof(type); \
1567 if (fMaxSize != std::wstring::npos && maxbytes < len) { \
1568 if (PyErr_WarnEx(PyExc_RuntimeWarning, \
1569 (char*)"string too long for " #type \
1570 " array (truncated)", \
1578 memcpy(*((void**)address), PyBytes_AS_STRING(bstr) + sizeof(type) , \
1583 if (len / sizeof(type) < fMaxSize) \
1584 (*(type**)address)[len / sizeof(type)] = snull; \
1589 PyUnicode_DecodeUTF16, u
'\0')
1591 PyUnicode_DecodeUTF32, U
'\0')
1594bool cpyrt::NonConstCStringConverter::SetArg(
PyObject* pyobject,
1599 if (this->CStringConverter::SetArg(pyobject, para, ctxt))
1604 return CArraySetArg(pyobject, para,
'c',
sizeof(
char));
1608PyObject* cpyrt::NonConstCStringConverter::FromMemory(
void* address) {
1612 return PyUnicode_FromStringAndSize(*(
char**)address, (Py_ssize_t)
fMaxSize);
1613 return this->CStringConverter::FromMemory(address);
1626 if (PyLong_CheckExact(pyobject)) {
1627 intptr_t val = (intptr_t)PyLong_AsLongLong(pyobject);
1629 address = (
void*)val;
1637 if (PyCapsule_CheckExact(pyobject)) {
1638 address = (
void*)PyCapsule_GetPointer(pyobject,
nullptr);
1664 if (GetAddressSpecialCase(pyobject, para.
fValue.
fVoidp)) {
1705 if (!address || *(uintptr_t*)address == 0) {
1729 void* ptr =
nullptr;
1730 if (GetAddressSpecialCase(
value, ptr)) {
1731 *(
void**)address = ptr;
1736 void* buf =
nullptr;
1738 if (!buf || buflen == 0)
1741 *(
void**)address = buf;
1745#if __cplusplus >= 202002L
1749class StdSpanConverter :
public InstanceConverter {
1752 bool keepControl =
false)
1753 : InstanceConverter{klass, keepControl}, fTypeName{typeName} {}
1755 ~StdSpanConverter() {
1757 PyBuffer_Release(&fBufinfo);
1762 bool HasState()
override {
return true; }
1765 std::string fTypeName;
1766 std::span<std::size_t>
fBuffer;
1767 bool fHasBuffer =
false;
1780 !PyObject_CheckBuffer(pyobject)) {
1782 return this->InstanceConverter::SetArg(pyobject, para, ctxt);
1785 Py_ssize_t buflen = 0;
1786 char typecode = typecodeFound->second;
1787 memset(&fBufinfo, 0,
sizeof(Py_buffer));
1789 if (PyObject_GetBuffer(pyobject, &fBufinfo, PyBUF_FORMAT) == 0) {
1790 if (!strchr(fBufinfo.format, typecode)) {
1791 PyErr_Format(PyExc_TypeError,
1792 "buffer has incompatible type: expected '%c' for C++ type "
1793 "'%s', but got format '%s'",
1794 typecode, fTypeName.c_str(),
1795 fBufinfo.format ? fBufinfo.format :
"<null>");
1796 PyBuffer_Release(&fBufinfo);
1808 static_cast<std::size_t
>(buflen)};
1822template <
class type>
1829 Py_ssize_t oldsz = 1;
1830 for (Py_ssize_t idim = 0; idim < shape.
ndim(); ++idim) {
1835 oldsz *= shape[idim];
1838 PyErr_SetString(PyExc_ValueError,
"buffer too large for value");
1843 memcpy(*(
type**)address, buf, (0 < buflen ? buflen : 1) * sizeof(
type));
1856#define CPPJIT_IMPL_ARRAY_CONVERTER(name, ctype, type, code, suffix) \
1857 cpyrt::name##ArrayConverter::name##ArrayConverter(cdims_t dims) \
1859 fIsFixed = dims ? fShape[0] != UNKNOWN_SIZE : false; \
1862 bool cpyrt::name##ArrayConverter::SetArg( \
1863 PyObject* pyobject, Parameter& para, CallContext* ctxt) { \
1865 bool convOk = false; \
1868 if (!convOk && fShape.ndim() == 2) { \
1869 if (Py_TYPE(pyobject) == GetCTypesPtrType(ct_##ctype)) { \
1870 para.fValue.fVoidp = (void*)((cpyrt_tagCDataObject*)pyobject)->b_ptr; \
1871 para.fTypeCode = 'p'; \
1873 } else if (Py_TYPE(pyobject) == GetCTypesType(ct_c_void_p)) { \
1876 para.fValue.fVoidp = (void*)((cpyrt_tagCDataObject*)pyobject)->b_ptr; \
1877 para.fTypeCode = 'p'; \
1879 } else if (LowLevelView_Check(pyobject) && \
1880 ((LowLevelView*)pyobject)->fBufInfo.ndim == 2 && \
1881 strchr(((LowLevelView*)pyobject)->fBufInfo.format, code)) { \
1882 para.fValue.fVoidp = ((LowLevelView*)pyobject)->get_buf(); \
1883 para.fTypeCode = 'p'; \
1890 PyTypeObject* ctypes_type = GetCTypesType(ct_##ctype); \
1891 if (Py_TYPE(pyobject) == ctypes_type) { \
1892 para.fValue.fVoidp = (void*)((cpyrt_tagCDataObject*)pyobject)->b_ptr; \
1893 para.fTypeCode = 'p'; \
1895 } else if (Py_TYPE(pyobject) == GetCTypesPtrType(ct_##ctype)) { \
1896 para.fValue.fVoidp = (void*)((cpyrt_tagCDataObject*)pyobject)->b_ptr; \
1897 para.fTypeCode = 'V'; \
1899 } else if (IsPyCArgObject(pyobject)) { \
1900 cpyrt_tagPyCArgObject* carg = (cpyrt_tagPyCArgObject*)pyobject; \
1901 if (carg->obj && Py_TYPE(carg->obj) == ctypes_type) { \
1902 para.fValue.fVoidp = \
1903 (void*)((cpyrt_tagCDataObject*)carg->obj)->b_ptr; \
1904 para.fTypeCode = 'p'; \
1907 } else if (LowLevelView_Check(pyobject) && \
1908 strchr(((LowLevelView*)pyobject)->fBufInfo.format, code)) { \
1909 para.fValue.fVoidp = ((LowLevelView*)pyobject)->get_buf(); \
1910 para.fTypeCode = 'p'; \
1917 bool ismulti = fShape.ndim() > 1; \
1918 convOk = CArraySetArg(pyobject, para, code, \
1919 ismulti ? sizeof(void*) : sizeof(type), true); \
1924 SetLifeLine(ctxt->fPyContext, pyobject, (intptr_t)this); \
1929 PyObject* cpyrt::name##ArrayConverter::FromMemory(void* address) { \
1931 return CreateLowLevelView##suffix((type**)address, fShape); \
1932 return CreateLowLevelView##suffix(*(type**)address, fShape); \
1935 bool cpyrt::name##ArrayConverter::ToMemory(PyObject* value, void* address, \
1937 if (fShape.ndim() <= 1 || fIsFixed) { \
1938 void* buf = nullptr; \
1939 Py_ssize_t buflen = Utility::GetBuffer(value, code, sizeof(type), buf); \
1943 Py_ssize_t oldsz = 1; \
1944 for (Py_ssize_t idim = 0; idim < fShape.ndim(); ++idim) { \
1945 if (fShape[idim] == UNKNOWN_SIZE) { \
1949 oldsz *= fShape[idim]; \
1951 if (fShape.ndim() != UNKNOWN_SIZE && 0 < oldsz && oldsz < buflen) { \
1952 PyErr_SetString(PyExc_ValueError, "buffer too large for value"); \
1957 memcpy(*(type**)address, buf, \
1958 (0 < buflen ? buflen : 1) * sizeof(type)); \
1960 *(type**)address = (type*)buf; \
1962 fShape[0] = buflen; \
1963 SetLifeLine(ctxt, value, (intptr_t)address); \
1967 void* buf = nullptr; \
1968 Py_ssize_t buflen = Utility::GetBuffer(value, code, sizeof(void*), buf); \
1971 *(type**)address = (type*)buf; \
1972 SetLifeLine(ctxt, value, (intptr_t)address); \
2014 para.fTypeCode =
'V';
2017 }
else if (PySequence_Check(pyobject) && !PyUnicode_Check(pyobject) &&
2018 !PyBytes_Check(pyobject)) {
2022 size_t len = (size_t)PySequence_Size(pyobject);
2023 if (
len == (
size_t)-1) {
2024 PyErr_SetString(PyExc_ValueError,
2025 "can not convert sequence object of unknown length");
2030 for (
size_t i = 0; i <
len; ++i) {
2031 PyObject* item = PySequence_GetItem(pyobject, i);
2040 PyErr_Format(PyExc_TypeError,
"could not convert item %d to string",
2049 para.fValue.fVoidp = (
void*)
fBuffer.data();
2050 para.fTypeCode =
'p';
2054 return SCharArrayConverter::SetArg(pyobject, para, ctxt);
2058PyObject* cpyrt::CStringArrayConverter::FromMemory(
void* address) {
2066bool cpyrt::CStringArrayConverter::ToMemory(
PyObject*
value,
void* address,
2071 return ToArrayFromBuffer<char>(
value, address, ctxt, cstr,
len,
fShape,
2074 return SCharArrayConverter::ToMemory(
value, address, ctxt);
2078PyObject* cpyrt::NonConstCStringArrayConverter::FromMemory(
void* address) {
2099template <
typename T>
2103 if (PyBytes_Check(pyobject)) {
2104 Py_INCREF(pyobject);
2106 }
else if (PyUnicode_Check(pyobject)) {
2107 pybytes = PyUnicode_AsUTF8String(pyobject);
2112 const char* cstr =
nullptr;
2113 PyBytes_AsStringAndSize(pybytes, (
char**)&cstr, &
len);
2115 buffer = T{cstr, (
typename T::size_type)
len};
2123#define CPPJIT_IMPL_STRING_AS_PRIMITIVE_CONVERTER(name, type, F1, F2) \
2124 cpyrt::name##Converter::name##Converter(bool keepControl) \
2125 : InstanceConverter(interop::GetFullScope(#type), keepControl) {} \
2127 bool cpyrt::name##Converter::SetArg(PyObject* pyobject, Parameter& para, \
2128 CallContext* ctxt) { \
2129 if (cpyrt_PyUnicodeAsBytes2Buffer(pyobject, fBuffer)) { \
2130 para.fValue.fVoidp = &fBuffer; \
2131 para.fTypeCode = 'V'; \
2136 if (!PyLong_Check(pyobject)) { \
2137 bool result = InstanceConverter::SetArg(pyobject, para, ctxt); \
2138 para.fTypeCode = 'V'; \
2145 PyObject* cpyrt::name##Converter::FromMemory(void* address) { \
2147 return InstanceConverter::FromMemory(address); \
2148 auto* empty = new type(); \
2149 return BindCppObjectNoCast(interop::TCppObject_t((void*)empty), fClass, \
2150 CPPInstance::kIsOwner); \
2153 bool cpyrt::name##Converter::ToMemory(PyObject* value, void* address, \
2155 if (cpyrt_PyUnicodeAsBytes2Buffer(value, *((type*)address))) \
2157 return InstanceConverter::ToMemory(value, address, ctxt); \
2162cpyrt::STLWStringConverter::STLWStringConverter(
bool keepControl)
2163 : InstanceConverter(interop::
GetFullScope(
"std::wstring"), keepControl) {}
2167 if (PyUnicode_Check(pyobject)) {
2168 Py_ssize_t
len = PyUnicode_GET_LENGTH(pyobject);
2170 PyUnicode_AsWideChar(pyobject, &
fBuffer[0],
len);
2176 if (!PyLong_Check(pyobject)) {
2185PyObject* cpyrt::STLWStringConverter::FromMemory(
void* address) {
2187 return PyUnicode_FromWideChar(((std::wstring*)address)->c_str(),
2188 ((std::wstring*)address)->
size());
2190 return PyUnicode_FromWideChar(&
w, 0);
2193bool cpyrt::STLWStringConverter::ToMemory(
PyObject*
value,
void* address,
2195 if (PyUnicode_Check(
value)) {
2196 Py_ssize_t
len = PyUnicode_GET_LENGTH(
value);
2197 wchar_t* buf =
new wchar_t[
len + 1];
2198 PyUnicode_AsWideChar(
value, buf,
len);
2199 *((std::wstring*)address) = std::wstring(buf,
len);
2203 return InstanceConverter::ToMemory(
value, address, ctxt);
2206cpyrt::STLStringViewConverter::STLStringViewConverter(
bool keepControl)
2207 : InstanceConverter(interop::
GetFullScope(
"std::string_view"),
2213 if (!PyLong_Check(pyobject)) {
2215 if (InstanceConverter::SetArg(pyobject, para, ctxt)) {
2227 fBuffer = std::string_view(cstr, (std::string_view::size_type)
len);
2249 fBuffer = *((std::string*)ptr);
2259PyObject* cpyrt::STLStringViewConverter::FromMemory(
void* address) {
2261 return InstanceConverter::FromMemory(address);
2262 auto* empty =
new std::string_view();
2266bool cpyrt::STLStringViewConverter::ToMemory(
PyObject*
value,
void* address,
2269 if (InstanceConverter::ToMemory(
value, address, ctxt))
2278 *
reinterpret_cast<std::string_view*
>(address) =
2279 std::string_view(cstr, (std::string_view::size_type)
len);
2289 int moveit_reason = 3;
2301 if (moveit_reason) {
2302 bool result = this->STLStringConverter::SetArg(pyobject, para, ctxt);
2303 if (!
result && moveit_reason == 2)
2308 PyErr_SetString(PyExc_ValueError,
"object is not an rvalue");
2313template <
bool ISCONST>
2321 if (GetAddressSpecialCase(pyobject, para.
fValue.
fVoidp)) {
2359template <
bool ISCONST>
2368 void* pobj = *(
void**)address;
2372 if (actual && actual !=
fClass &&
2380template <
bool ISCONST>
2388 void* ptr =
nullptr;
2389 if (GetAddressSpecialCase(
value, ptr)) {
2390 *(
void**)address = ptr;