87#if PY_VERSION_HEX >= 0x030e0000
108#define ct_c_uint32 10
111#define ct_c_longlong 13
112#define ct_c_ulonglong 14
114#define ct_c_double 16
115#define ct_c_longdouble 17
116#define ct_c_char_p 18
117#define ct_c_wchar_p 19
118#define ct_c_void_p 20
119#define ct_c_fcomplex 21
120#define ct_c_complex 22
121#define ct_c_pointer 23
122#define ct_c_funcptr 24
128 "c_bool",
"c_char",
"c_wchar",
"c_byte",
"c_ubyte",
129 "c_short",
"c_ushort",
"c_uint16",
"c_int",
"c_uint",
130 "c_uint32",
"c_long",
"c_ulong",
"c_longlong",
"c_ulonglong",
131 "c_float",
"c_double",
"c_longdouble",
"c_char_p",
"c_wchar_p",
132 "c_void_p",
"c_fcomplex",
"c_complex",
"_Pointer",
"_CFuncPtr",
133 "c_int16",
"c_int32"};
142 static PyObject* ctmod = PyImport_ImportModule(
"ctypes");
149 ct_t = (PyTypeObject*)PyObject_GetAttrString(ctmod,
gCTypesNames[nidx]);
161 static PyObject* ctmod = PyImport_ImportModule(
"ctypes");
169 cpt_t = (PyTypeObject*)PyObject_GetAttrString(ctmod,
"c_char_p");
173 PyObject* ptrcreat = PyObject_GetAttrString(ctmod,
"POINTER");
175 (PyTypeObject*)PyObject_CallFunctionObjArgs(ptrcreat, ct_t, NULL);
188 static PyTypeObject* pycarg_type =
nullptr;
190 PyObject* ctmod = PyImport_ImportModule(
"ctypes");
195 (PyTypeObject*)PyObject_GetAttrString(ctmod,
"c_int");
196 PyObject* cobj = ct_t->tp_new(ct_t,
nullptr,
nullptr);
197 PyObject* byref = PyObject_GetAttrString(ctmod,
"byref");
198 PyObject* pyptr = PyObject_CallFunctionObjArgs(byref, cobj, NULL);
202 pycarg_type = Py_TYPE(pyptr);
207 return Py_TYPE(pyobject) == pycarg_type;
210#if PY_VERSION_HEX < 0x30d0000
212 static PyTypeObject* cstgdict_type =
nullptr;
213 if (!cstgdict_type) {
216 if (ct_int && ct_int->tp_dict) {
217 cstgdict_type = Py_TYPE(ct_int->tp_dict);
221 PyTypeObject* pytype = Py_TYPE(pyobject);
222 if (pytype->tp_dict && Py_TYPE(pytype->tp_dict) == cstgdict_type)
231 PyTypeObject* DictRemover_Type;
232 PyTypeObject* PyCArg_Type;
233 PyTypeObject* PyCField_Type;
234 PyTypeObject* PyCThunk_Type;
235 PyTypeObject* StructParam_Type;
236 PyTypeObject* PyCType_Type;
237 PyTypeObject* PyCStructType_Type;
238 PyTypeObject* UnionType_Type;
239 PyTypeObject* PyCPointerType_Type;
241} _cppjit_ctypes_state;
246 static _cppjit_ctypes_state* state =
nullptr;
248 PyObject* ctmod = PyImport_AddModule(
251 state = (_cppjit_ctypes_state*)PyModule_GetState(ctmod);
255 if (state && (PyObject_IsInstance((
PyObject*)Py_TYPE(pyobject),
257 PyObject_IsInstance((
PyObject*)Py_TYPE(pyobject),
258 (
PyObject*)state->PyCPointerType_Type))) {
276 std::ostringstream attr_name;
277 attr_name <<
"__" << ref;
279 PyObject_SetAttrString(holder, (
char*)attr_name.str().c_str(),
target);
288 std::ostringstream attr_name;
289 attr_name <<
"__" << ref;
291 PyObject_GetAttrString(holder, (
char*)attr_name.str().c_str());
306 bool accept_rvalue =
false) {
318 else if (klass && PyTuple_CheckExact(castobj)) {
323 (
CPPInstance*)PyObject_Call(pyclass, castobj, NULL);
346 if (!PyLong_Check(pyobject) || PyLong_CheckExact(pyobject) ||
347 PyBool_Check(pyobject))
349 return PyObject_HasAttr((
PyObject*)Py_TYPE(pyobject),
359 (PyBool_Check(pyobject) ||
380 long l = PyLong_AsLong(pyobject);
382 if (!(
l == 0 ||
l == 1) || PyFloat_Check(pyobject)) {
383 PyErr_SetString(PyExc_ValueError,
384 "boolean value should be bool, or integer 1 or 0");
392#define CPPJIT_PYLONG_AS_TYPE(name, type, limit_low, limit_high) \
393 static inline type cpyrt_PyLong_As##name(PyObject* pyobject) { \
394 if (!PyLong_Check(pyobject)) { \
395 if (pyobject == cpyrt::gDefaultObject) \
397 PyErr_SetString(PyExc_TypeError, \
398 #type " conversion expects an integer object"); \
401 long l = PyLong_AsLong(pyobject); \
402 if (l < limit_low || limit_high < l) { \
403 PyErr_Format(PyExc_ValueError, "integer %ld out of range for " #type, \
424 if (!PyLong_Check(pyobject)) {
427 PyErr_SetString(PyExc_TypeError,
428 "int/long conversion expects an integer object");
432 return (
long)PyLong_AsLong(pyobject);
439 if (!PyLong_Check(pyobject)) {
442 PyErr_SetString(PyExc_TypeError,
443 "int/long conversion expects an integer object");
447 return PyLong_AsLongLong(pyobject);
452 char tc,
int size,
bool check =
true) {
458 if (llview->fBufInfo.itemsize !=
size ||
460 PyErr_Format(PyExc_TypeError,
461 "could not convert argument to buffer or nullptr");
480 PyErr_Format(PyExc_TypeError,
481 "could not convert argument to buffer or nullptr");
495 bool manage =
true) {
515 if (clName.compare(0, 6,
"std::_") == 0 ||
516 (!clName.empty() && clName[0] ==
'_')) {
517 bool sameTemplate =
false;
520 if (
src &&
src != klass) {
522 std::string::size_type lt = clName.find(
'<');
523 sameTemplate = lt != std::string::npos && srcName.size() > lt &&
524 srcName[lt] ==
'<' &&
525 srcName.compare(0, lt, clName, 0, lt) == 0;
537 PyTypeObject* pytype = (PyTypeObject*)Py_TYPE(pyobject);
538 if (!(pytype == &PyList_Type ||
539 pytype == &PyTuple_Type)) {
557 PyTuple_SET_ITEM(args, 0, pyobject);
561 if (!pytmp && PyTuple_CheckExact(pyobject)) {
565 pytmp = (
CPPInstance*)PyObject_Call(pyscope, pyobject, NULL);
591 PyErr_SetString(PyExc_TypeError,
"C++ type cannot be converted from memory");
599 PyErr_SetString(PyExc_TypeError,
"C++ type cannot be converted to memory");
604#define CPPJIT_IMPL_BASIC_CONVERTER_BODY(name, type, stype, ctype, F1, F2, tc) \
606 type val = (type)F2(pyobject); \
607 if (val == (type) - 1 && PyErr_Occurred()) { \
608 static PyTypeObject* ctypes_type = nullptr; \
609 if (!ctypes_type) { \
610 auto error = cpyrt::Utility::FetchPyError(); \
611 ctypes_type = GetCTypesType(ct_##ctype); \
612 cpyrt::Utility::RestorePyError(error); \
614 if (Py_TYPE(pyobject) == ctypes_type) { \
616 val = *((type*)((cpyrt_tagCDataObject*)pyobject)->b_ptr); \
617 } else if (pyobject == cpyrt::gDefaultObject) { \
623 para.fValue.f##name = val; \
624 para.fTypeCode = tc; \
627#define CPPJIT_IMPL_BASIC_CONVERTER_METHODS(name, type, stype, ctype, F1, F2) \
628 PyObject* cpyrt::name##Converter::FromMemory(void* address) { \
629 return F1((stype) * ((type*)address)); \
632 bool cpyrt::name##Converter::ToMemory(PyObject* value, void* address, \
634 type s = (type)F2(value); \
635 if (s == (type) - 1 && PyErr_Occurred()) { \
636 if (value == cpyrt::gDefaultObject) { \
642 *((type*)address) = (type)s; \
646#define CPPJIT_IMPL_BASIC_CONVERTER_NI(name, type, stype, ctype, F1, F2, tc) \
647 bool cpyrt::name##Converter::SetArg(PyObject* pyobject, Parameter& para, \
648 CallContext* ctxt) { \
649 if (!StrictBool(pyobject, ctxt)) \
651 CPPJIT_IMPL_BASIC_CONVERTER_BODY(name, type, stype, ctype, F1, F2, tc) \
653 CPPJIT_IMPL_BASIC_CONVERTER_METHODS(name, type, stype, ctype, F1, F2)
655#define CPPJIT_IMPL_BASIC_CONVERTER_IB(name, type, stype, ctype, F1, F2, tc) \
656 bool cpyrt::name##Converter::SetArg(PyObject* pyobject, Parameter& para, \
657 CallContext* ctxt) { \
658 if (!ImplicitBool(pyobject, ctxt)) \
660 CPPJIT_IMPL_BASIC_CONVERTER_BODY(name, type, stype, ctype, F1, F2, tc) \
662 CPPJIT_IMPL_BASIC_CONVERTER_METHODS(name, type, stype, ctype, F1, F2)
664#define CPPJIT_IMPL_BASIC_CONVERTER_NB(name, type, stype, ctype, F1, F2, tc) \
665 bool cpyrt::name##Converter::SetArg(PyObject* pyobject, Parameter& para, \
667 if (PyBool_Check(pyobject)) \
669 CPPJIT_IMPL_BASIC_CONVERTER_BODY(name, type, stype, ctype, F1, F2, tc) \
671 CPPJIT_IMPL_BASIC_CONVERTER_METHODS(name, type, stype, ctype, F1, F2)
677 if (PyBytes_Check(pyobject)) {
678 if (PyBytes_GET_SIZE(pyobject) == 1)
679 lchar = (
int)(PyBytes_AsString(pyobject)[0]);
681 PyErr_Format(PyExc_ValueError,
683 PyBytes_GET_SIZE(pyobject));
684 }
else if (PyUnicode_Check(pyobject)) {
685 if (PyUnicode_GET_LENGTH(pyobject) == 1)
686 lchar = (
int)(PyUnicode_AsUTF8(pyobject)[0]);
688 PyErr_Format(PyExc_ValueError,
690 PyUnicode_GET_LENGTH(pyobject));
693 }
else if (!PyFloat_Check(pyobject)) {
694 lchar = (
int)PyLong_AsLong(pyobject);
695 if (lchar == -1 && PyErr_Occurred())
697 else if (!(low <= lchar && lchar <= high)) {
698 PyErr_Format(PyExc_ValueError,
699 "integer to character: value %d not in range [%d,%d]", lchar,
704 PyErr_SetString(PyExc_TypeError,
"char or small int type expected");
710#define CPPJIT_IMPL_REFCONVERTER_FROM_MEMORY(name, ctype) \
711 PyObject* cpyrt::name##RefConverter::FromMemory(void* ptr) { \
713 PyTypeObject* ctypes_type = GetCTypesType(ct_##ctype); \
714 if (!ctypes_type) { \
715 PyErr_SetString(PyExc_RuntimeError, "no ctypes available"); \
718 PyObject* ref = ctypes_type->tp_new(ctypes_type, nullptr, nullptr); \
719 ((cpyrt_tagCDataObject*)ref)->b_ptr = (char*)ptr; \
720 ((cpyrt_tagCDataObject*)ref)->b_needsfree = 0; \
725#define CPPJIT_IMPL_BASIC_CONST_REFCONVERTER(name, type, ctype, F1) \
726 bool cpyrt::Const##name##RefConverter::SetArg( \
727 PyObject* pyobject, Parameter& para, CallContext* ) { \
728 type val = (type)F1(pyobject); \
729 if (val == (type) - 1 && PyErr_Occurred()) { \
730 if (pyobject == cpyrt::gDefaultObject) { \
736 para.fValue.f##name = val; \
737 para.fRef = ¶.fValue.f##name; \
738 para.fTypeCode = 'r'; \
741 CPPJIT_IMPL_REFCONVERTER_FROM_MEMORY(Const##name, ctype)
744#define CPPJIT_IMPL_BASIC_CONST_CHAR_REFCONVERTER(name, type, ctype, low, \
746 bool cpyrt::Const##name##RefConverter::SetArg( \
747 PyObject* pyobject, Parameter& para, CallContext* ) { \
750 type val = (type)ExtractChar(pyobject, #type, low, high); \
751 if (val == (type) - 1 && PyErr_Occurred()) \
753 para.fValue.fLong = val; \
754 para.fTypeCode = 'l'; \
757 CPPJIT_IMPL_REFCONVERTER_FROM_MEMORY(Const##name, ctype)
760#define CPPJIT_IMPL_BASIC_CHAR_CONVERTER(name, type, low, high) \
761 bool cpyrt::name##Converter::SetArg(PyObject* pyobject, Parameter& para, \
765 long val = ExtractChar(pyobject, #type, low, high); \
766 if (val == -1 && PyErr_Occurred()) \
768 para.fValue.fLong = val; \
769 para.fTypeCode = 'l'; \
773 PyObject* cpyrt::name##Converter::FromMemory(void* address) { \
775 return PyUnicode_FromFormat("%c", *((type*)address)); \
778 bool cpyrt::name##Converter::ToMemory(PyObject* value, void* address, \
781 const char* cstr = nullptr; \
782 if (PyBytes_Check(value)) \
783 PyBytes_AsStringAndSize(value, (char**)&cstr, &len); \
785 cstr = cpyrt_PyText_AsStringAndSize(value, &len); \
788 PyErr_Format(PyExc_TypeError, \
789 #type " expected, got string of size %zd", len); \
792 *((type*)address) = (type)cstr[0]; \
795 long l = PyLong_AsLong(value); \
796 if (l == -1 && PyErr_Occurred()) { \
797 if (value == cpyrt::gDefaultObject) { \
803 if (!(low <= l && l <= high)) { \
804 PyErr_Format(PyExc_ValueError, \
805 "integer to character: value %ld not in range [%d,%d]", \
809 *((type*)address) = (type)l; \
825 para.fTypeCode =
'V';
830 para.fTypeCode =
'V';
834 PyErr_SetString(PyExc_TypeError,
835 "use ctypes.c_long for pass-by-ref of longs");
880 PyErr_SetString(PyExc_TypeError,
"use ctypes.c_int for pass-by-ref of ints");
885#define CPPJIT_IMPL_REFCONVERTER(name, ctype, type, code) \
886 bool cpyrt::name##RefConverter::SetArg(PyObject* pyobject, Parameter& para, \
889 if (Py_TYPE(pyobject) == GetCTypesType(ct_##ctype)) { \
890 para.fValue.fVoidp = (void*)((cpyrt_tagCDataObject*)pyobject)->b_ptr; \
891 para.fTypeCode = 'V'; \
894 bool res = CArraySetArg(pyobject, para, code, sizeof(type)); \
896 PyErr_SetString(PyExc_TypeError, \
897 "use ctypes." #ctype " for pass-by-ref of " #type); \
900 para.fTypeCode = 'V'; \
903 CPPJIT_IMPL_REFCONVERTER_FROM_MEMORY(name, ctype)
941PyObject* cpyrt::SCharAsIntConverter::FromMemory(
void* address) {
944 return PyLong_FromLong((
long)*((
signed char*)address));
947PyObject* cpyrt::UCharAsIntConverter::FromMemory(
void* address) {
950 return PyLong_FromLong((
long)*((
unsigned char*)address));
957 if (!PyUnicode_Check(pyobject) || PyUnicode_GET_LENGTH(pyobject) != 1) {
958 PyErr_SetString(PyExc_ValueError,
"single wchar_t character expected");
962 Py_ssize_t res = PyUnicode_AsWideChar(pyobject, &val, 1);
970PyObject* cpyrt::WCharConverter::FromMemory(
void* address) {
971 return PyUnicode_FromWideChar((
const wchar_t*)address, 1);
974bool cpyrt::WCharConverter::ToMemory(
PyObject*
value,
void* address,
976 if (!PyUnicode_Check(
value) || PyUnicode_GET_LENGTH(
value) != 1) {
977 PyErr_SetString(PyExc_ValueError,
"single wchar_t character expected");
981 Py_ssize_t res = PyUnicode_AsWideChar(
value, &val, 1);
984 *((
wchar_t*)address) = val;
992 if (!PyUnicode_Check(pyobject) || PyUnicode_GET_LENGTH(pyobject) != 1) {
993 PyErr_SetString(PyExc_ValueError,
"single char16_t character expected");
997 PyObject* bstr = PyUnicode_AsUTF16String(pyobject);
1002 *(
char16_t*)(PyBytes_AS_STRING(bstr) +
sizeof(char16_t) );
1009PyObject* cpyrt::Char16Converter::FromMemory(
void* address) {
1010 return PyUnicode_DecodeUTF16((
const char*)address,
sizeof(
char16_t),
nullptr,
1014bool cpyrt::Char16Converter::ToMemory(
PyObject*
value,
void* address,
1016 if (!PyUnicode_Check(
value) || PyUnicode_GET_LENGTH(
value) != 1) {
1017 PyErr_SetString(PyExc_ValueError,
"single char16_t character expected");
1025 *((
char16_t*)address) =
1026 *(
char16_t*)(PyBytes_AS_STRING(bstr) +
sizeof(char16_t) );
1035 if (!PyUnicode_Check(pyobject) || 2 < PyUnicode_GET_LENGTH(pyobject)) {
1036 PyErr_SetString(PyExc_ValueError,
"single char32_t character expected");
1040 PyObject* bstr = PyUnicode_AsUTF32String(pyobject);
1045 *(
char32_t*)(PyBytes_AS_STRING(bstr) +
sizeof(char32_t) );
1052PyObject* cpyrt::Char32Converter::FromMemory(
void* address) {
1053 return PyUnicode_DecodeUTF32((
const char*)address,
sizeof(
char32_t),
nullptr,
1057bool cpyrt::Char32Converter::ToMemory(
PyObject*
value,
void* address,
1059 if (!PyUnicode_Check(
value) || 2 < PyUnicode_GET_LENGTH(
value)) {
1060 PyErr_SetString(PyExc_ValueError,
"single char32_t character expected");
1068 *((
char32_t*)address) =
1069 *(
char32_t*)(PyBytes_AS_STRING(bstr) +
sizeof(char32_t) );
1103 if (para.fValue.fULong == (
unsigned long)-1 && PyErr_Occurred())
1105 para.fTypeCode =
'L';
1109PyObject* cpyrt::ULongConverter::FromMemory(
void* address) {
1111 return PyLong_FromUnsignedLong(*((
unsigned long*)address));
1114bool cpyrt::ULongConverter::ToMemory(
PyObject*
value,
void* address,
1118 if (u == (
unsigned long)-1 && PyErr_Occurred()) {
1121 u = (
unsigned long)0;
1125 *((
unsigned long*)address) = u;
1130PyObject* cpyrt::UIntConverter::FromMemory(
void* address) {
1132 return PyLong_FromUnsignedLong(*((
unsigned int*)address));
1135bool cpyrt::UIntConverter::ToMemory(
PyObject*
value,
void* address,
1139 if (u == (
unsigned long)-1 && PyErr_Occurred())
1142 if (u > (
unsigned long)UINT_MAX) {
1143 PyErr_SetString(PyExc_OverflowError,
"value too large for unsigned int");
1147 *((
unsigned int*)address) = (
unsigned int)u;
1153 PyFloat_FromDouble, PyFloat_AsDouble,
'f')
1155 PyFloat_FromDouble, PyFloat_AsDouble, '
d')
1158 c_longdouble, PyFloat_FromDouble,
1159 PyFloat_AsDouble, '
g')
1161cpyrt::ComplexDConverter::ComplexDConverter(
bool keepControl)
1162 : InstanceConverter(interop::GetFullScope("std::complex<
double>"),
1168 const Py_complex& pc = PyComplex_AsCComplex(pyobject);
1169 if (pc.real != -1.0 || !PyErr_Occurred()) {
1177 return this->InstanceConverter::SetArg(pyobject, para, ctxt);
1180PyObject* cpyrt::ComplexDConverter::FromMemory(
void* address) {
1181 std::complex<double>* dc = (std::complex<double>*)address;
1182 return PyComplex_FromDoubles(dc->real(), dc->imag());
1185bool cpyrt::ComplexDConverter::ToMemory(
PyObject*
value,
void* address,
1187 const Py_complex& pc = PyComplex_AsCComplex(
value);
1188 if (pc.real != -1.0 || !PyErr_Occurred()) {
1189 std::complex<double>* dc = (std::complex<double>*)address;
1194 return this->InstanceConverter::ToMemory(
value, address, ctxt);
1216 PyErr_SetString(PyExc_TypeError,
1217 "use ctypes.c_double for pass-by-ref of doubles");
1232 PyErr_SetString(PyExc_SystemError,
"void/unknown arguments can\'t be set");
1244 if (PyErr_Occurred())
1250PyObject* cpyrt::LLongConverter::FromMemory(
void* address) {
1255bool cpyrt::LLongConverter::ToMemory(
PyObject*
value,
void* address,
1259 if (ll == -1 && PyErr_Occurred()) {
1278 if (PyErr_Occurred())
1284PyObject* cpyrt::ULLongConverter::FromMemory(
void* address) {
1286 return PyLong_FromUnsignedLongLong(*(
PY_ULONG_LONG*)address);
1289bool cpyrt::ULLongConverter::ToMemory(
PyObject*
value,
void* address,
1293 if (PyErr_Occurred()) {
1317 exact = (
fEnumName == PyUnicode_AsUTF8(pycppname));
1318 Py_DECREF(pycppname);
1334PyObject* cpyrt::EnumConverter::FromMemory(
void* address) {
1338bool cpyrt::EnumConverter::ToMemory(
PyObject*
value,
void* address,
1343std::string cpyrt::EnumConverter::GetFailureMsg() {
1368 if (PyErr_WarnEx(PyExc_RuntimeWarning,
1369 (
char*)
"string too long for char array (truncated)",
1388PyObject* cpyrt::CStringConverter::FromMemory(
void* address) {
1390 if (address && *(
void**)address) {
1393 return PyUnicode_FromStringAndSize(*(
char**)address,
1396 if (*(
void**)address ==
1398 return PyUnicode_FromStringAndSize((
char*)
fBuffer.data(),
fBuffer.size());
1401 return PyUnicode_FromString(*(
char**)address);
1409bool cpyrt::CStringConverter::ToMemory(
PyObject*
value,
void* address,
1419 if (PyErr_WarnEx(PyExc_RuntimeWarning,
1420 (
char*)
"string too long for char array (truncated)",
1428 void* ptrval = *(
void**)address;
1429 if (ptrval == (
void*)
fBuffer.data()) {
1431 *(
void**)address = (
void*)
fBuffer.data();
1433 }
else if (ptrval &&
HasLifeLine(ctxt, (intptr_t)ptrval)) {
1441 *(
void**)address = (
void*)cstr;
1447 strncpy(*(
char**)address, cstr,
fMaxSize);
1450 strcpy(*(
char**)address, cstr);
1459 Py_ssize_t
len = PyUnicode_GetLength(pyobject);
1460 if (
len == (Py_ssize_t)-1 && PyErr_Occurred())
1464 Py_ssize_t res = PyUnicode_AsWideChar(pyobject,
fBuffer,
len);
1475PyObject* cpyrt::WCStringConverter::FromMemory(
void* address) {
1477 if (address && *(
wchar_t**)address) {
1480 return PyUnicode_FromWideChar(*(
wchar_t**)address, (Py_ssize_t)
fMaxSize);
1482 return PyUnicode_FromWideChar(*(
wchar_t**)address,
1483 wcslen(*(
wchar_t**)address));
1488 return PyUnicode_FromWideChar(&
w, 0);
1491bool cpyrt::WCStringConverter::ToMemory(
PyObject*
value,
void* address,
1494 Py_ssize_t
len = PyUnicode_GetLength(
value);
1495 if (
len == (Py_ssize_t)-1 && PyErr_Occurred())
1500 if (PyErr_WarnEx(PyExc_RuntimeWarning,
1501 (
char*)
"string too long for wchar_t array (truncated)",
1505 Py_ssize_t res = -1;
1506 if (
fMaxSize != std::wstring::npos)
1508 PyUnicode_AsWideChar(
value, *(
wchar_t**)address, (Py_ssize_t)
fMaxSize);
1511 res = PyUnicode_AsWideChar(
value, *(
wchar_t**)address,
len);
1519#define CPYRT_WIDESTRING_CONVERTER(name, type, encode, decode, snull) \
1520 bool cpyrt::name##Converter::SetArg(PyObject* pyobject, Parameter& para, \
1523 PyObject* bstr = encode(pyobject); \
1527 Py_ssize_t len = PyBytes_GET_SIZE(bstr) - sizeof(type) ; \
1528 fBuffer = (type*)realloc(fBuffer, len + sizeof(type)); \
1529 memcpy(fBuffer, PyBytes_AS_STRING(bstr) + sizeof(type) , len); \
1532 fBuffer[len / sizeof(type)] = snull; \
1533 para.fValue.fVoidp = (void*)fBuffer; \
1534 para.fTypeCode = 'p'; \
1538 PyObject* cpyrt::name##Converter::FromMemory(void* address) { \
1540 if (address && *(type**)address) { \
1541 if (fMaxSize != std::wstring::npos) \
1542 return decode(*(const char**)address, \
1543 (Py_ssize_t)fMaxSize * sizeof(type), nullptr, nullptr); \
1544 return decode(*(const char**)address, \
1545 std::char_traits<type>::length(*(type**)address) * \
1547 nullptr, nullptr); \
1552 return decode((const char*)&w, 0, nullptr, nullptr); \
1555 bool cpyrt::name##Converter::ToMemory(PyObject* value, void* address, \
1558 PyObject* bstr = encode(value); \
1562 Py_ssize_t len = PyBytes_GET_SIZE(bstr) - sizeof(type) ; \
1563 Py_ssize_t maxbytes = (Py_ssize_t)fMaxSize * sizeof(type); \
1566 if (fMaxSize != std::wstring::npos && maxbytes < len) { \
1567 if (PyErr_WarnEx(PyExc_RuntimeWarning, \
1568 (char*)"string too long for " #type \
1569 " array (truncated)", \
1577 memcpy(*((void**)address), PyBytes_AS_STRING(bstr) + sizeof(type) , \
1582 if (len / sizeof(type) < fMaxSize) \
1583 (*(type**)address)[len / sizeof(type)] = snull; \
1588 PyUnicode_DecodeUTF16, u
'\0')
1590 PyUnicode_DecodeUTF32, U
'\0')
1593bool cpyrt::NonConstCStringConverter::SetArg(
PyObject* pyobject,
1598 if (this->CStringConverter::SetArg(pyobject, para, ctxt))
1603 return CArraySetArg(pyobject, para,
'c',
sizeof(
char));
1607PyObject* cpyrt::NonConstCStringConverter::FromMemory(
void* address) {
1611 return PyUnicode_FromStringAndSize(*(
char**)address, (Py_ssize_t)
fMaxSize);
1612 return this->CStringConverter::FromMemory(address);
1625 if (PyLong_CheckExact(pyobject)) {
1626 intptr_t val = (intptr_t)PyLong_AsLongLong(pyobject);
1628 address = (
void*)val;
1636 if (PyCapsule_CheckExact(pyobject)) {
1637 address = (
void*)PyCapsule_GetPointer(pyobject,
nullptr);
1663 if (GetAddressSpecialCase(pyobject, para.
fValue.
fVoidp)) {
1704 if (!address || *(uintptr_t*)address == 0) {
1728 void* ptr =
nullptr;
1729 if (GetAddressSpecialCase(
value, ptr)) {
1730 *(
void**)address = ptr;
1735 void* buf =
nullptr;
1737 if (!buf || buflen == 0)
1740 *(
void**)address = buf;
1744#if __cplusplus >= 202002L
1748class StdSpanConverter :
public InstanceConverter {
1751 bool keepControl =
false)
1752 : InstanceConverter{klass, keepControl}, fTypeName{typeName} {}
1754 ~StdSpanConverter() {
1756 PyBuffer_Release(&fBufinfo);
1761 bool HasState()
override {
return true; }
1764 std::string fTypeName;
1765 std::span<std::size_t>
fBuffer;
1766 bool fHasBuffer =
false;
1779 !PyObject_CheckBuffer(pyobject)) {
1781 return this->InstanceConverter::SetArg(pyobject, para, ctxt);
1784 Py_ssize_t buflen = 0;
1785 char typecode = typecodeFound->second;
1786 memset(&fBufinfo, 0,
sizeof(Py_buffer));
1788 if (PyObject_GetBuffer(pyobject, &fBufinfo, PyBUF_FORMAT) == 0) {
1790 PyErr_Format(PyExc_TypeError,
1791 "buffer has incompatible type: expected '%c' for C++ type "
1792 "'%s', but got format '%s'",
1793 typecode, fTypeName.c_str(),
1794 fBufinfo.format ? fBufinfo.format :
"<null>");
1795 PyBuffer_Release(&fBufinfo);
1807 static_cast<std::size_t
>(buflen)};
1821template <
class type>
1828 Py_ssize_t oldsz = 1;
1829 for (Py_ssize_t idim = 0; idim < shape.
ndim(); ++idim) {
1834 oldsz *= shape[idim];
1837 PyErr_SetString(PyExc_ValueError,
"buffer too large for value");
1842 memcpy(*(
type**)address, buf, (0 < buflen ? buflen : 1) * sizeof(
type));
1855#define CPPJIT_IMPL_ARRAY_CONVERTER(name, ctype, type, code, suffix) \
1856 cpyrt::name##ArrayConverter::name##ArrayConverter(cdims_t dims) \
1858 fIsFixed = dims ? fShape[0] != UNKNOWN_SIZE : false; \
1861 bool cpyrt::name##ArrayConverter::SetArg( \
1862 PyObject* pyobject, Parameter& para, CallContext* ctxt) { \
1864 bool convOk = false; \
1867 if (!convOk && fShape.ndim() == 2) { \
1868 if (Py_TYPE(pyobject) == GetCTypesPtrType(ct_##ctype)) { \
1869 para.fValue.fVoidp = (void*)((cpyrt_tagCDataObject*)pyobject)->b_ptr; \
1870 para.fTypeCode = 'p'; \
1872 } else if (Py_TYPE(pyobject) == GetCTypesType(ct_c_void_p)) { \
1875 para.fValue.fVoidp = (void*)((cpyrt_tagCDataObject*)pyobject)->b_ptr; \
1876 para.fTypeCode = 'p'; \
1878 } else if (LowLevelView_Check(pyobject) && \
1879 ((LowLevelView*)pyobject)->fBufInfo.ndim == 2 && \
1880 Utility::BufferFormatCompatible( \
1881 code, ((LowLevelView*)pyobject)->fBufInfo.format)) { \
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 Utility::BufferFormatCompatible( \
1909 code, ((LowLevelView*)pyobject)->fBufInfo.format)) { \
1910 para.fValue.fVoidp = ((LowLevelView*)pyobject)->get_buf(); \
1911 para.fTypeCode = 'p'; \
1918 bool ismulti = fShape.ndim() > 1; \
1919 convOk = CArraySetArg(pyobject, para, code, \
1920 ismulti ? sizeof(void*) : sizeof(type), true); \
1925 SetLifeLine(ctxt->fPyContext, pyobject, (intptr_t)this); \
1930 PyObject* cpyrt::name##ArrayConverter::FromMemory(void* address) { \
1932 return CreateLowLevelView##suffix((type**)address, fShape); \
1933 return CreateLowLevelView##suffix(*(type**)address, fShape); \
1936 bool cpyrt::name##ArrayConverter::ToMemory(PyObject* value, void* address, \
1938 if (fShape.ndim() <= 1 || fIsFixed) { \
1939 void* buf = nullptr; \
1940 Py_ssize_t buflen = Utility::GetBuffer(value, code, sizeof(type), buf); \
1944 Py_ssize_t oldsz = 1; \
1945 for (Py_ssize_t idim = 0; idim < fShape.ndim(); ++idim) { \
1946 if (fShape[idim] == UNKNOWN_SIZE) { \
1950 oldsz *= fShape[idim]; \
1952 if (fShape.ndim() != UNKNOWN_SIZE && 0 < oldsz && oldsz < buflen) { \
1953 PyErr_SetString(PyExc_ValueError, "buffer too large for value"); \
1958 memcpy(*(type**)address, buf, \
1959 (0 < buflen ? buflen : 1) * sizeof(type)); \
1961 *(type**)address = (type*)buf; \
1963 fShape[0] = buflen; \
1964 SetLifeLine(ctxt, value, (intptr_t)address); \
1968 void* buf = nullptr; \
1969 Py_ssize_t buflen = Utility::GetBuffer(value, code, sizeof(void*), buf); \
1972 *(type**)address = (type*)buf; \
1973 SetLifeLine(ctxt, value, (intptr_t)address); \
2015 para.fTypeCode =
'V';
2018 }
else if (PySequence_Check(pyobject) && !PyUnicode_Check(pyobject) &&
2019 !PyBytes_Check(pyobject)) {
2023 size_t len = (size_t)PySequence_Size(pyobject);
2024 if (
len == (
size_t)-1) {
2025 PyErr_SetString(PyExc_ValueError,
2026 "can not convert sequence object of unknown length");
2031 for (
size_t i = 0; i <
len; ++i) {
2032 PyObject* item = PySequence_GetItem(pyobject, i);
2041 PyErr_Format(PyExc_TypeError,
"could not convert item %d to string",
2050 para.fValue.fVoidp = (
void*)
fBuffer.data();
2051 para.fTypeCode =
'p';
2055 return SCharArrayConverter::SetArg(pyobject, para, ctxt);
2059PyObject* cpyrt::CStringArrayConverter::FromMemory(
void* address) {
2067bool cpyrt::CStringArrayConverter::ToMemory(
PyObject*
value,
void* address,
2072 return ToArrayFromBuffer<char>(
value, address, ctxt, cstr,
len,
fShape,
2075 return SCharArrayConverter::ToMemory(
value, address, ctxt);
2079PyObject* cpyrt::NonConstCStringArrayConverter::FromMemory(
void* address) {
2100template <
typename T>
2104 if (PyBytes_Check(pyobject)) {
2105 Py_INCREF(pyobject);
2107 }
else if (PyUnicode_Check(pyobject)) {
2108 pybytes = PyUnicode_AsUTF8String(pyobject);
2113 const char* cstr =
nullptr;
2114 PyBytes_AsStringAndSize(pybytes, (
char**)&cstr, &
len);
2116 buffer = T{cstr, (
typename T::size_type)
len};
2124#define CPPJIT_IMPL_STRING_AS_PRIMITIVE_CONVERTER(name, type, F1, F2) \
2125 cpyrt::name##Converter::name##Converter(bool keepControl) \
2126 : InstanceConverter(interop::GetFullScope(#type), keepControl) {} \
2128 bool cpyrt::name##Converter::SetArg(PyObject* pyobject, Parameter& para, \
2129 CallContext* ctxt) { \
2130 if (cpyrt_PyUnicodeAsBytes2Buffer(pyobject, fBuffer)) { \
2131 para.fValue.fVoidp = &fBuffer; \
2132 para.fTypeCode = 'V'; \
2137 if (!PyLong_Check(pyobject)) { \
2138 bool result = InstanceConverter::SetArg(pyobject, para, ctxt); \
2139 para.fTypeCode = 'V'; \
2146 PyObject* cpyrt::name##Converter::FromMemory(void* address) { \
2148 return InstanceConverter::FromMemory(address); \
2149 auto* empty = new type(); \
2150 return BindCppObjectNoCast(interop::TCppObject_t((void*)empty), fClass, \
2151 CPPInstance::kIsOwner); \
2154 bool cpyrt::name##Converter::ToMemory(PyObject* value, void* address, \
2156 if (cpyrt_PyUnicodeAsBytes2Buffer(value, *((type*)address))) \
2158 return InstanceConverter::ToMemory(value, address, ctxt); \
2163cpyrt::STLWStringConverter::STLWStringConverter(
bool keepControl)
2164 : InstanceConverter(interop::
GetFullScope(
"std::wstring"), keepControl) {}
2168 if (PyUnicode_Check(pyobject)) {
2169 Py_ssize_t
len = PyUnicode_GET_LENGTH(pyobject);
2171 PyUnicode_AsWideChar(pyobject, &
fBuffer[0],
len);
2177 if (!PyLong_Check(pyobject)) {
2186PyObject* cpyrt::STLWStringConverter::FromMemory(
void* address) {
2188 return PyUnicode_FromWideChar(((std::wstring*)address)->c_str(),
2189 ((std::wstring*)address)->
size());
2191 return PyUnicode_FromWideChar(&
w, 0);
2194bool cpyrt::STLWStringConverter::ToMemory(
PyObject*
value,
void* address,
2196 if (PyUnicode_Check(
value)) {
2197 Py_ssize_t
len = PyUnicode_GET_LENGTH(
value);
2198 wchar_t* buf =
new wchar_t[
len + 1];
2199 PyUnicode_AsWideChar(
value, buf,
len);
2200 *((std::wstring*)address) = std::wstring(buf,
len);
2204 return InstanceConverter::ToMemory(
value, address, ctxt);
2207cpyrt::STLStringViewConverter::STLStringViewConverter(
bool keepControl)
2208 : InstanceConverter(interop::
GetFullScope(
"std::string_view"),
2214 if (!PyLong_Check(pyobject)) {
2216 if (InstanceConverter::SetArg(pyobject, para, ctxt)) {
2228 fBuffer = std::string_view(cstr, (std::string_view::size_type)
len);
2250 fBuffer = *((std::string*)ptr);
2260PyObject* cpyrt::STLStringViewConverter::FromMemory(
void* address) {
2262 return InstanceConverter::FromMemory(address);
2263 auto* empty =
new std::string_view();
2267bool cpyrt::STLStringViewConverter::ToMemory(
PyObject*
value,
void* address,
2270 if (InstanceConverter::ToMemory(
value, address, ctxt))
2279 *
reinterpret_cast<std::string_view*
>(address) =
2280 std::string_view(cstr, (std::string_view::size_type)
len);
2290 int moveit_reason = 3;
2302 if (moveit_reason) {
2303 bool result = this->STLStringConverter::SetArg(pyobject, para, ctxt);
2304 if (!
result && moveit_reason == 2)
2309 PyErr_SetString(PyExc_ValueError,
"object is not an rvalue");
2314template <
bool ISCONST>
2322 if (GetAddressSpecialCase(pyobject, para.
fValue.
fVoidp)) {
2360template <
bool ISCONST>
2369 void* pobj = *(
void**)address;
2373 if (actual && actual !=
fClass &&
2381template <
bool ISCONST>
2389 void* ptr =
nullptr;
2390 if (GetAddressSpecialCase(
value, ptr)) {
2391 *(
void**)address = ptr;