72#elif PY_VERSION_HEX < 0x03080000
122#define ct_c_uint32 10
125#define ct_c_longlong 13
126#define ct_c_ulonglong 14
128#define ct_c_double 16
129#define ct_c_longdouble 17
130#define ct_c_char_p 18
131#define ct_c_wchar_p 19
132#define ct_c_void_p 20
133#define ct_c_fcomplex 21
134#define ct_c_complex 22
135#define ct_c_pointer 23
136#define ct_c_funcptr 24
142 "c_bool",
"c_char",
"c_wchar",
"c_byte",
"c_ubyte",
"c_short",
"c_ushort",
"c_uint16",
143 "c_int",
"c_uint",
"c_uint32",
"c_long",
"c_ulong",
"c_longlong",
"c_ulonglong",
144 "c_float",
"c_double",
"c_longdouble",
145 "c_char_p",
"c_wchar_p",
"c_void_p",
"c_fcomplex",
"c_complex",
146 "_Pointer",
"_CFuncPtr" };
156 static PyObject* ctmod = PyImport_ImportModule(
"ctypes");
163 ct_t = (PyTypeObject*)PyObject_GetAttrString(ctmod,
gCTypesNames[nidx]);
164 if (!ct_t) PyErr_Clear();
175 static PyObject* ctmod = PyImport_ImportModule(
"ctypes");
183 cpt_t = (PyTypeObject*)PyObject_GetAttrString(ctmod,
"c_char_p");
187 PyObject* ptrcreat = PyObject_GetAttrString(ctmod,
"POINTER");
188 cpt_t = (PyTypeObject*)PyObject_CallFunctionObjArgs(ptrcreat, ct_t, NULL);
202 static PyTypeObject* pycarg_type =
nullptr;
204 PyObject* ctmod = PyImport_ImportModule(
"ctypes");
205 if (!ctmod) PyErr_Clear();
207 PyTypeObject* ct_t = (PyTypeObject*)PyObject_GetAttrString(ctmod,
"c_int");
208 PyObject* cobj = ct_t->tp_new(ct_t,
nullptr,
nullptr);
209 PyObject* byref = PyObject_GetAttrString(ctmod,
"byref");
210 PyObject* pyptr = PyObject_CallFunctionObjArgs(byref, cobj, NULL);
211 Py_DECREF(byref); Py_DECREF(cobj); Py_DECREF(ct_t);
217 return Py_TYPE(pyobject) == pycarg_type;
220#if PY_VERSION_HEX < 0x30d0000
223 static PyTypeObject* cstgdict_type =
nullptr;
224 if (!cstgdict_type) {
227 if (ct_int && ct_int->tp_dict) {
228 cstgdict_type =
Py_TYPE(ct_int->tp_dict);
232 PyTypeObject* pytype =
Py_TYPE(pyobject);
233 if (pytype->tp_dict &&
Py_TYPE(pytype->tp_dict) == cstgdict_type)
242 PyTypeObject *DictRemover_Type;
243 PyTypeObject *PyCArg_Type;
244 PyTypeObject *PyCField_Type;
245 PyTypeObject *PyCThunk_Type;
246 PyTypeObject *StructParam_Type;
247 PyTypeObject *PyCType_Type;
248 PyTypeObject *PyCStructType_Type;
249 PyTypeObject *UnionType_Type;
250 PyTypeObject *PyCPointerType_Type;
252} _cppyy_ctypes_state;
258 static _cppyy_ctypes_state* state =
nullptr;
260 PyObject* ctmod = PyImport_AddModule(
"_ctypes");
262 state = (_cppyy_ctypes_state*)PyModule_GetState(ctmod);
280 if (!holder)
return false;
285 std::ostringstream attr_name;
286 attr_name <<
"__" << ref;
287 auto res = PyObject_SetAttrString(holder, (
char*)attr_name.str().c_str(), target);
294 if (!holder)
return false;
296 std::ostringstream attr_name;
297 attr_name <<
"__" << ref;
298 PyObject* res = PyObject_GetAttrString(holder, (
char*)attr_name.str().c_str());
325 else if (klass && PyTuple_CheckExact(castobj)) {
374 long l = PyLong_AsLong(pyobject);
376 if (!(
l == 0||
l == 1) || PyFloat_Check(pyobject)) {
377 PyErr_SetString(PyExc_ValueError,
"boolean value should be bool, or integer 1 or 0");
385#define CPPYY_PYLONG_AS_TYPE(name, type, limit_low, limit_high) \
386static inline type CPyCppyy_PyLong_As##name(PyObject* pyobject) \
388 if (!(PyLong_Check(pyobject) || PyInt_Check(pyobject))) { \
389 if (pyobject == CPyCppyy::gDefaultObject) \
391 PyErr_SetString(PyExc_TypeError, #type" conversion expects an integer object");\
394 long l = PyLong_AsLong(pyobject); \
395 if (l < limit_low || limit_high < l) { \
396 PyErr_Format(PyExc_ValueError, "integer %ld out of range for "#type, l);\
417 if (!(PyLong_Check(pyobject) || PyInt_Check(pyobject))) {
420 PyErr_SetString(PyExc_TypeError,
"int/long conversion expects an integer object");
424 return (
long)PyLong_AsLong(pyobject);
432 if (!(PyLong_Check(pyobject) || PyInt_Check(pyobject))) {
435 PyErr_SetString(PyExc_TypeError,
"int/long conversion expects an integer object");
439 return PyLong_AsLongLong(pyobject);
452 if (llview->fBufInfo.itemsize !=
size || !strchr(llview->fBufInfo.format, tc)) {
453 PyErr_Format(PyExc_TypeError,
454 "could not convert argument to buffer or nullptr");
470 PyErr_Format(PyExc_TypeError,
471 "could not convert argument to buffer or nullptr");
495 PyTypeObject* pytype = (PyTypeObject*)
Py_TYPE(pyobject);
496 if (!(pytype == &PyList_Type || pytype == &PyTuple_Type)) {
512 Py_INCREF(pyobject); PyTuple_SET_ITEM(args, 0, pyobject);
516 if (!pytmp && PyTuple_CheckExact(pyobject)) {
519 pytmp = (
CPPInstance*)PyObject_Call(pyscope, pyobject, NULL);
549 PyErr_SetString(PyExc_TypeError,
"C++ type cannot be converted from memory");
557 PyErr_SetString(PyExc_TypeError,
"C++ type cannot be converted to memory");
563#define CPPYY_IMPL_BASIC_CONVERTER_BODY(name, type, stype, ctype, F1, F2, tc)\
565 type val = (type)F2(pyobject); \
566 if (val == (type)-1 && PyErr_Occurred()) { \
567 static PyTypeObject* ctypes_type = nullptr; \
568 if (!ctypes_type) { \
569 auto error = CPyCppyy::Utility::FetchPyError(); \
570 ctypes_type = GetCTypesType(ct_##ctype); \
571 CPyCppyy::Utility::RestorePyError(error); \
573 if (Py_TYPE(pyobject) == ctypes_type) { \
575 val = *((type*)((CPyCppyy_tagCDataObject*)pyobject)->b_ptr); \
576 } else if (pyobject == CPyCppyy::gDefaultObject) { \
582 para.fValue.f##name = val; \
583 para.fTypeCode = tc; \
586#define CPPYY_IMPL_BASIC_CONVERTER_METHODS(name, type, stype, ctype, F1, F2) \
587PyObject* CPyCppyy::name##Converter::FromMemory(void* address) \
589 return F1((stype)*((type*)address)); \
592bool CPyCppyy::name##Converter::ToMemory( \
593 PyObject* value, void* address, PyObject* ) \
595 type s = (type)F2(value); \
596 if (s == (type)-1 && PyErr_Occurred()) { \
597 if (value == CPyCppyy::gDefaultObject) { \
603 *((type*)address) = (type)s; \
607#define CPPYY_IMPL_BASIC_CONVERTER_NI(name, type, stype, ctype, F1, F2, tc) \
608bool CPyCppyy::name##Converter::SetArg( \
609 PyObject* pyobject, Parameter& para, CallContext* ctxt) \
611 if (!StrictBool(pyobject, ctxt)) \
613 CPPYY_IMPL_BASIC_CONVERTER_BODY(name, type, stype, ctype, F1, F2, tc) \
615CPPYY_IMPL_BASIC_CONVERTER_METHODS(name, type, stype, ctype, F1, F2)
617#define CPPYY_IMPL_BASIC_CONVERTER_IB(name, type, stype, ctype, F1, F2, tc) \
618bool CPyCppyy::name##Converter::SetArg( \
619 PyObject* pyobject, Parameter& para, CallContext* ctxt) \
621 if (!ImplicitBool(pyobject, ctxt)) \
623 CPPYY_IMPL_BASIC_CONVERTER_BODY(name, type, stype, ctype, F1, F2, tc) \
625CPPYY_IMPL_BASIC_CONVERTER_METHODS(name, type, stype, ctype, F1, F2)
627#define CPPYY_IMPL_BASIC_CONVERTER_NB(name, type, stype, ctype, F1, F2, tc) \
628bool CPyCppyy::name##Converter::SetArg( \
629 PyObject* pyobject, Parameter& para, CallContext* ) \
631 if (PyBool_Check(pyobject)) \
633 CPPYY_IMPL_BASIC_CONVERTER_BODY(name, type, stype, ctype, F1, F2, tc) \
635CPPYY_IMPL_BASIC_CONVERTER_METHODS(name, type, stype, ctype, F1, F2)
645 PyErr_Format(PyExc_ValueError,
"%s expected, got bytes of size " PY_SSIZE_T_FORMAT,
651 PyErr_Format(PyExc_ValueError,
"%s expected, got str of size " PY_SSIZE_T_FORMAT,
655 }
else if (!PyFloat_Check(pyobject)) {
656 lchar = (
int)PyLong_AsLong(pyobject);
657 if (lchar == -1 && PyErr_Occurred())
659 else if (!(low <= lchar && lchar <= high)) {
660 PyErr_Format(PyExc_ValueError,
661 "integer to character: value %d not in range [%d,%d]", lchar, low, high);
665 PyErr_SetString(PyExc_TypeError,
"char or small int type expected");
671#define CPPYY_IMPL_REFCONVERTER_FROM_MEMORY(name, ctype) \
672PyObject* CPyCppyy::name##RefConverter::FromMemory(void* ptr) \
675 PyTypeObject* ctypes_type = GetCTypesType(ct_##ctype); \
676 if (!ctypes_type) { \
677 PyErr_SetString(PyExc_RuntimeError, "no ctypes available"); \
680 PyObject* ref = ctypes_type->tp_new(ctypes_type, nullptr, nullptr); \
681 ((CPyCppyy_tagCDataObject*)ref)->b_ptr = (char*)ptr; \
682 ((CPyCppyy_tagCDataObject*)ref)->b_needsfree = 0; \
687#define CPPYY_IMPL_BASIC_CONST_REFCONVERTER(name, type, ctype, F1) \
688bool CPyCppyy::Const##name##RefConverter::SetArg( \
689 PyObject* pyobject, Parameter& para, CallContext* ) \
691 type val = (type)F1(pyobject); \
692 if (val == (type)-1 && PyErr_Occurred()) { \
693 if (pyobject == CPyCppyy::gDefaultObject) { \
699 para.fValue.f##name = val; \
700 para.fRef = ¶.fValue.f##name; \
701 para.fTypeCode = 'r'; \
704CPPYY_IMPL_REFCONVERTER_FROM_MEMORY(Const##name, ctype)
707#define CPPYY_IMPL_BASIC_CONST_CHAR_REFCONVERTER(name, type, ctype, low, high)\
708bool CPyCppyy::Const##name##RefConverter::SetArg( \
709 PyObject* pyobject, Parameter& para, CallContext* ) \
712 type val = (type)ExtractChar(pyobject, #type, low, high); \
713 if (val == (type)-1 && PyErr_Occurred()) \
715 para.fValue.fLong = val; \
716 para.fTypeCode = 'l'; \
719CPPYY_IMPL_REFCONVERTER_FROM_MEMORY(Const##name, ctype)
723#define CPPYY_IMPL_BASIC_CHAR_CONVERTER(name, type, low, high) \
724bool CPyCppyy::name##Converter::SetArg( \
725 PyObject* pyobject, Parameter& para, CallContext* ) \
728 long val = ExtractChar(pyobject, #type, low, high); \
729 if (val == -1 && PyErr_Occurred()) \
731 para.fValue.fLong = val; \
732 para.fTypeCode = 'l'; \
736PyObject* CPyCppyy::name##Converter::FromMemory(void* address) \
739 return CPyCppyy_PyText_FromFormat("%c", *((type*)address)); \
742bool CPyCppyy::name##Converter::ToMemory( \
743 PyObject* value, void* address, PyObject* ) \
746 const char* cstr = nullptr; \
747 if (PyBytes_Check(value)) \
748 PyBytes_AsStringAndSize(value, (char**)&cstr, &len); \
750 cstr = CPyCppyy_PyText_AsStringAndSize(value, &len); \
753 PyErr_Format(PyExc_TypeError, #type" expected, got string of size %zd", len);\
756 *((type*)address) = (type)cstr[0]; \
759 long l = PyLong_AsLong(value); \
760 if (l == -1 && PyErr_Occurred()) { \
761 if (value == CPyCppyy::gDefaultObject) { \
767 if (!(low <= l && l <= high)) { \
768 PyErr_Format(PyExc_ValueError, \
769 "integer to character: value %ld not in range [%d,%d]", l, low, high);\
772 *((type*)address) = (type)l; \
786#if PY_VERSION_HEX < 0x03000000
788 para.fValue.fVoidp = (
void*)&((PyIntObject*)pyobject)->ob_ival;
789 para.fTypeCode =
'V';
796 para.fTypeCode =
'V';
801 para.fTypeCode =
'V';
805 PyErr_SetString(PyExc_TypeError,
"use ctypes.c_long for pass-by-ref of longs");
830bool CPyCppyy::IntRefConverter::SetArg(
834#if PY_VERSION_HEX < 0x03000000
836 para.
fValue.
fVoidp = (
void*)&((PyIntObject*)pyobject)->ob_ival;
842#if PY_VERSION_HEX >= 0x02050000
844 para.
fValue.
fVoidp = (
void*)((CPyCppyy_tagCDataObject*)pyobject)->b_ptr;
857#if PY_VERSION_HEX < 0x02050000
858 PyErr_SetString(PyExc_TypeError,
"use cppyy.Long for pass-by-ref of ints");
860 PyErr_SetString(PyExc_TypeError,
"use ctypes.c_int for pass-by-ref of ints");
866#define CPPYY_IMPL_REFCONVERTER(name, ctype, type, code) \
867bool CPyCppyy::name##RefConverter::SetArg( \
868 PyObject* pyobject, Parameter& para, CallContext* ) \
871 if (Py_TYPE(pyobject) == GetCTypesType(ct_##ctype)) { \
872 para.fValue.fVoidp = (void*)((CPyCppyy_tagCDataObject*)pyobject)->b_ptr;\
873 para.fTypeCode = 'V'; \
876 bool res = CArraySetArg(pyobject, para, code, sizeof(type)); \
878 PyErr_SetString(PyExc_TypeError, "use ctypes."#ctype" for pass-by-ref of "#type);\
881 para.fTypeCode = 'V'; \
884CPPYY_IMPL_REFCONVERTER_FROM_MEMORY(name, ctype)
925 return PyInt_FromLong((
long)*((
signed char*)address));
928PyObject* CPyCppyy::UCharAsIntConverter::FromMemory(
void* address)
932 return PyInt_FromLong((
long)*((
unsigned char*)address));
936bool CPyCppyy::WCharConverter::SetArg(
941 PyErr_SetString(PyExc_ValueError,
"single wchar_t character expected");
953PyObject* CPyCppyy::WCharConverter::FromMemory(
void* address)
955 return PyUnicode_FromWideChar((
const wchar_t*)address, 1);
958bool CPyCppyy::WCharConverter::ToMemory(
PyObject* value,
void* address,
PyObject* )
961 PyErr_SetString(PyExc_ValueError,
"single wchar_t character expected");
968 *((
wchar_t*)address) = val;
973bool CPyCppyy::Char16Converter::SetArg(
978 PyErr_SetString(PyExc_ValueError,
"single char16_t character expected");
982 PyObject* bstr = PyUnicode_AsUTF16String(pyobject);
983 if (!bstr)
return false;
992PyObject* CPyCppyy::Char16Converter::FromMemory(
void* address)
994 return PyUnicode_DecodeUTF16((
const char*)address,
sizeof(
char16_t),
nullptr,
nullptr);
997bool CPyCppyy::Char16Converter::ToMemory(
PyObject* value,
void* address,
PyObject* )
1000 PyErr_SetString(PyExc_ValueError,
"single char16_t character expected");
1004 PyObject* bstr = PyUnicode_AsUTF16String(value);
1005 if (!bstr)
return false;
1007 *((
char16_t*)address) = *(
char16_t*)(
PyBytes_AS_STRING(bstr) +
sizeof(
char16_t) );
1013bool CPyCppyy::Char32Converter::SetArg(
1018 PyErr_SetString(PyExc_ValueError,
"single char32_t character expected");
1022 PyObject* bstr = PyUnicode_AsUTF32String(pyobject);
1023 if (!bstr)
return false;
1032PyObject* CPyCppyy::Char32Converter::FromMemory(
void* address)
1034 return PyUnicode_DecodeUTF32((
const char*)address,
sizeof(
char32_t),
nullptr,
nullptr);
1037bool CPyCppyy::Char32Converter::ToMemory(
PyObject* value,
void* address,
PyObject* )
1040 PyErr_SetString(PyExc_ValueError,
"single char32_t character expected");
1044 PyObject* bstr = PyUnicode_AsUTF32String(value);
1045 if (!bstr)
return false;
1047 *((
char32_t*)address) = *(
char32_t*)(
PyBytes_AS_STRING(bstr) +
sizeof(
char32_t) );
1073bool CPyCppyy::ULongConverter::SetArg(
1081 if (para.fValue.fULong == (
unsigned long)-1 && PyErr_Occurred())
1083 para.fTypeCode =
'L';
1087PyObject* CPyCppyy::ULongConverter::FromMemory(
void* address)
1090 return PyLong_FromUnsignedLong(*((
unsigned long*)address));
1093bool CPyCppyy::ULongConverter::ToMemory(
PyObject* value,
void* address,
PyObject* )
1097 if (u == (
unsigned long)-1 && PyErr_Occurred()) {
1100 u = (
unsigned long)0;
1104 *((
unsigned long*)address) = u;
1109PyObject* CPyCppyy::UIntConverter::FromMemory(
void* address)
1112 return PyLong_FromUnsignedLong(*((
unsigned int*)address));
1115bool CPyCppyy::UIntConverter::ToMemory(
PyObject* value,
void* address,
PyObject* )
1119 if (u == (
unsigned long)-1 && PyErr_Occurred())
1122 if (u > (
unsigned long)UINT_MAX) {
1123 PyErr_SetString(PyExc_OverflowError,
"value too large for unsigned int");
1127 *((
unsigned int*)address) = (
unsigned int)u;
1133 Float,
float,
double, c_float, PyFloat_FromDouble, PyFloat_AsDouble,
'f')
1135 Double,
double,
double, c_double, PyFloat_FromDouble, PyFloat_AsDouble,
'd')
1140CPyCppyy::ComplexDConverter::ComplexDConverter(
bool keepControl) :
1141 InstanceConverter(Cppyy::GetScope(
"std::complex<double>"), keepControl) {}
1144bool CPyCppyy::ComplexDConverter::SetArg(
1147 const Py_complex& pc = PyComplex_AsCComplex(pyobject);
1148 if (pc.real != -1.0 || !PyErr_Occurred()) {
1156 return this->InstanceConverter::SetArg(pyobject, para, ctxt);
1159PyObject* CPyCppyy::ComplexDConverter::FromMemory(
void* address)
1161 std::complex<double>* dc = (std::complex<double>*)address;
1162 return PyComplex_FromDoubles(dc->real(), dc->imag());
1165bool CPyCppyy::ComplexDConverter::ToMemory(
PyObject* value,
void* address,
PyObject* ctxt)
1167 const Py_complex& pc = PyComplex_AsCComplex(value);
1168 if (pc.real != -1.0 || !PyErr_Occurred()) {
1169 std::complex<double>* dc = (std::complex<double>*)address;
1174 return this->InstanceConverter::ToMemory(value, address, ctxt);
1178bool CPyCppyy::DoubleRefConverter::SetArg(
1182#if PY_VERSION_HEX < 0x03000000
1184 para.
fValue.
fVoidp = (
void*)&((PyFloatObject*)pyobject)->ob_fval;
1190#if PY_VERSION_HEX >= 0x02050000
1192 para.
fValue.
fVoidp = (
void*)((CPyCppyy_tagCDataObject*)pyobject)->b_ptr;
1205#if PY_VERSION_HEX < 0x02050000
1206 PyErr_SetString(PyExc_TypeError,
"use cppyy.Double for pass-by-ref of doubles");
1208 PyErr_SetString(PyExc_TypeError,
"use ctypes.c_double for pass-by-ref of doubles");
1222 PyErr_SetString(PyExc_SystemError,
"void/unknown arguments can\'t be set");
1227bool CPyCppyy::LLongConverter::SetArg(
1235 if (PyErr_Occurred())
1241PyObject* CPyCppyy::LLongConverter::FromMemory(
void* address)
1247bool CPyCppyy::LLongConverter::ToMemory(
PyObject* value,
void* address,
PyObject* )
1251 if (ll == -1 && PyErr_Occurred()) {
1263bool CPyCppyy::ULLongConverter::SetArg(
1271 if (PyErr_Occurred())
1277PyObject* CPyCppyy::ULLongConverter::FromMemory(
void* address)
1280 return PyLong_FromUnsignedLongLong(*(
PY_ULONG_LONG*)address);
1283bool CPyCppyy::ULLongConverter::ToMemory(
PyObject* value,
void* address,
PyObject* )
1287 if (PyErr_Occurred()) {
1299bool CPyCppyy::CStringConverter::SetArg(
1310 para.
fValue.
fVoidp = (
void*)((CPyCppyy_tagCDataObject*)pyobject)->b_ptr;
1319 if (fMaxSize != std::string::npos && fMaxSize <
fBuffer.size())
1320 if (PyErr_WarnEx(PyExc_RuntimeWarning, (
char*)
"string too long for char array (truncated)", 1) < 0)
1325 fBuffer = std::string(cstr, len);
1326 if (fMaxSize != std::string::npos)
1327 fBuffer.resize(fMaxSize,
'\0');
1338PyObject* CPyCppyy::CStringConverter::FromMemory(
void* address)
1341 if (address && *(
void**)address) {
1342 if (fMaxSize != std::string::npos)
1345 if (*(
void**)address == (
void*)
fBuffer.data())
1357bool CPyCppyy::CStringConverter::ToMemory(
PyObject* value,
void* address,
PyObject* ctxt)
1362 if (!cstr)
return false;
1365 if (fMaxSize != std::string::npos && fMaxSize < (std::string::size_type)len)
1366 if (PyErr_WarnEx(PyExc_RuntimeWarning, (
char*)
"string too long for char array (truncated)", 1) < 0)
1372 void* ptrval = *(
void**)address;
1373 if (ptrval == (
void*)
fBuffer.data()) {
1374 fBuffer = std::string(cstr, len);
1375 *(
void**)address = (
void*)
fBuffer.data();
1377 }
else if (ptrval &&
HasLifeLine(ctxt, (intptr_t)ptrval)) {
1385 *(
void**)address = (
void*)cstr;
1390 if (fMaxSize != std::string::npos)
1391 strncpy(*(
char**)address, cstr, fMaxSize);
1394 strcpy(*(
char**)address, cstr);
1400bool CPyCppyy::WCStringConverter::SetArg(
1404 Py_ssize_t len = PyUnicode_GetSize(pyobject);
1405 if (len == (
Py_ssize_t)-1 && PyErr_Occurred())
1420PyObject* CPyCppyy::WCStringConverter::FromMemory(
void* address)
1423 if (address && *(
wchar_t**)address) {
1424 if (fMaxSize != std::wstring::npos)
1425 return PyUnicode_FromWideChar(*(
wchar_t**)address, (
Py_ssize_t)fMaxSize);
1427 return PyUnicode_FromWideChar(*(
wchar_t**)address, wcslen(*(
wchar_t**)address));
1432 return PyUnicode_FromWideChar(&w, 0);
1435bool CPyCppyy::WCStringConverter::ToMemory(
PyObject* value,
void* address,
PyObject* )
1439 if (len == (
Py_ssize_t)-1 && PyErr_Occurred())
1443 if (fMaxSize != std::wstring::npos && fMaxSize < (std::wstring::size_type)len)
1444 if (PyErr_WarnEx(PyExc_RuntimeWarning, (
char*)
"string too long for wchar_t array (truncated)", 1) < 0)
1448 if (fMaxSize != std::wstring::npos)
1454 if (res == -1)
return false;
1459#define CPYCPPYY_WIDESTRING_CONVERTER(name, type, encode, decode, snull) \
1460bool CPyCppyy::name##Converter::SetArg( \
1461 PyObject* pyobject, Parameter& para, CallContext* ) \
1464 PyObject* bstr = encode(pyobject); \
1465 if (!bstr) return false; \
1467 Py_ssize_t len = PyBytes_GET_SIZE(bstr) - sizeof(type) ; \
1468 fBuffer = (type*)realloc(fBuffer, len + sizeof(type)); \
1469 memcpy(fBuffer, PyBytes_AS_STRING(bstr) + sizeof(type) , len); \
1472 fBuffer[len/sizeof(type)] = snull; \
1473 para.fValue.fVoidp = (void*)fBuffer; \
1474 para.fTypeCode = 'p'; \
1478PyObject* CPyCppyy::name##Converter::FromMemory(void* address) \
1481 if (address && *(type**)address) { \
1482 if (fMaxSize != std::wstring::npos) \
1483 return decode(*(const char**)address, (Py_ssize_t)fMaxSize*sizeof(type), nullptr, nullptr);\
1484 return decode(*(const char**)address, \
1485 std::char_traits<type>::length(*(type**)address)*sizeof(type), nullptr, nullptr);\
1490 return decode((const char*)&w, 0, nullptr, nullptr); \
1493bool CPyCppyy::name##Converter::ToMemory(PyObject* value, void* address, PyObject* )\
1496 PyObject* bstr = encode(value); \
1497 if (!bstr) return false; \
1499 Py_ssize_t len = PyBytes_GET_SIZE(bstr) - sizeof(type) ; \
1500 Py_ssize_t maxbytes = (Py_ssize_t)fMaxSize*sizeof(type); \
1503 if (fMaxSize != std::wstring::npos && maxbytes < len) { \
1504 if (PyErr_WarnEx(PyExc_RuntimeWarning, (char*)"string too long for "#type" array (truncated)", 1) < 0) { \
1511 memcpy(*((void**)address), PyBytes_AS_STRING(bstr) + sizeof(type) , len);\
1514 if (len/sizeof(type) < fMaxSize) (*(type**)address)[len/sizeof(type)] = snull;\
1522bool CPyCppyy::NonConstCStringConverter::SetArg(
1526 if (this->CStringConverter::SetArg(pyobject, para, ctxt))
1531 return CArraySetArg(pyobject, para,
'c',
sizeof(
char));
1535PyObject* CPyCppyy::NonConstCStringConverter::FromMemory(
void* address)
1538 if (fMaxSize != std::string::npos)
1540 return this->CStringConverter::FromMemory(address);
1553 if (PyInt_CheckExact(pyobject) || PyLong_CheckExact(pyobject)) {
1554 intptr_t val = (intptr_t)PyLong_AsLongLong(pyobject);
1556 address = (
void*)val;
1599 para.
fValue.
fVoidp = (
void*)((CPyCppyy_tagCDataObject*)pyobject)->b_ptr;
1606 void** payload = (
void**)((CPyCppyy_tagCDataObject*)pyobject)->b_ptr;
1631 if (!address || *(uintptr_t*)address == 0) {
1654 void* ptr =
nullptr;
1656 *(
void**)address = ptr;
1661 void* buf =
nullptr;
1663 if (!buf || buflen == 0)
1666 *(
void**)address = buf;
1670#if __cplusplus >= 202002L
1674class StdSpanConverter :
public InstanceConverter {
1676 StdSpanConverter(std::string
const &typeName,
Cppyy::TCppType_t klass,
bool keepControl =
false)
1677 : InstanceConverter{klass, keepControl}, fTypeName{typeName}
1684 PyBuffer_Release(&fBufinfo);
1689 bool HasState()
override {
return true; }
1692 std::string fTypeName;
1693 std::span<std::size_t>
fBuffer;
1694 bool fHasBuffer =
false;
1708 return this->InstanceConverter::SetArg(pyobject, para, ctxt);
1712 char typecode = typecodeFound->second;
1713 memset(&fBufinfo, 0,
sizeof(Py_buffer));
1715 if (PyObject_GetBuffer(pyobject, &fBufinfo, PyBUF_FORMAT) == 0) {
1716 if (!strchr(fBufinfo.format, typecode)) {
1717 PyErr_Format(PyExc_TypeError,
1718 "buffer has incompatible type: expected '%c' for C++ type '%s', but got format '%s'", typecode,
1719 fTypeName.c_str(), fBufinfo.format ? fBufinfo.format :
"<null>");
1720 PyBuffer_Release(&fBufinfo);
1730 fBuffer = std::span<std::size_t>{(std::size_t *)para.
fValue.
fVoidp,
static_cast<std::size_t
>(buflen)};
1759 oldsz *= shape[idim];
1762 PyErr_SetString(PyExc_ValueError,
"buffer too large for value");
1767 memcpy(*(type**)address, buf, (0 < buflen ? buflen : 1)*
sizeof(type));
1769 *(
type**)address = (type*)buf;
1780#define CPPYY_IMPL_ARRAY_CONVERTER(name, ctype, type, code, suffix) \
1781CPyCppyy::name##ArrayConverter::name##ArrayConverter(cdims_t dims) : \
1783 fIsFixed = dims ? fShape[0] != UNKNOWN_SIZE : false; \
1786bool CPyCppyy::name##ArrayConverter::SetArg( \
1787 PyObject* pyobject, Parameter& para, CallContext* ctxt) \
1790 bool convOk = false; \
1793 if (fShape.ndim() == 2) { \
1794 if (Py_TYPE(pyobject) == GetCTypesPtrType(ct_##ctype)) { \
1795 para.fValue.fVoidp = (void*)((CPyCppyy_tagCDataObject*)pyobject)->b_ptr;\
1796 para.fTypeCode = 'p'; \
1798 } else if (Py_TYPE(pyobject) == GetCTypesType(ct_c_void_p)) { \
1800 para.fValue.fVoidp = (void*)((CPyCppyy_tagCDataObject*)pyobject)->b_ptr;\
1801 para.fTypeCode = 'p'; \
1803 } else if (LowLevelView_Check(pyobject) && \
1804 ((LowLevelView*)pyobject)->fBufInfo.ndim == 2 && \
1805 strchr(((LowLevelView*)pyobject)->fBufInfo.format, code)) { \
1806 para.fValue.fVoidp = ((LowLevelView*)pyobject)->get_buf(); \
1807 para.fTypeCode = 'p'; \
1814 PyTypeObject* ctypes_type = GetCTypesType(ct_##ctype); \
1815 if (Py_TYPE(pyobject) == ctypes_type) { \
1816 para.fValue.fVoidp = (void*)((CPyCppyy_tagCDataObject*)pyobject)->b_ptr;\
1817 para.fTypeCode = 'p'; \
1819 } else if (Py_TYPE(pyobject) == GetCTypesPtrType(ct_##ctype)) { \
1820 para.fValue.fVoidp = (void*)((CPyCppyy_tagCDataObject*)pyobject)->b_ptr;\
1821 para.fTypeCode = 'V'; \
1823 } else if (IsPyCArgObject(pyobject)) { \
1824 CPyCppyy_tagPyCArgObject* carg = (CPyCppyy_tagPyCArgObject*)pyobject;\
1825 if (carg->obj && Py_TYPE(carg->obj) == ctypes_type) { \
1826 para.fValue.fVoidp = (void*)((CPyCppyy_tagCDataObject*)carg->obj)->b_ptr;\
1827 para.fTypeCode = 'p'; \
1835 bool ismulti = fShape.ndim() > 1; \
1836 convOk = CArraySetArg(pyobject, para, code, ismulti ? sizeof(void*) : sizeof(type), true);\
1840 if (convOk) SetLifeLine(ctxt->fPyContext, pyobject, (intptr_t)this); \
1845PyObject* CPyCppyy::name##ArrayConverter::FromMemory(void* address) \
1848 return CreateLowLevelView##suffix((type**)address, fShape); \
1849 return CreateLowLevelView##suffix(*(type**)address, fShape); \
1852bool CPyCppyy::name##ArrayConverter::ToMemory( \
1853 PyObject* value, void* address, PyObject* ctxt) \
1855 if (fShape.ndim() <= 1 || fIsFixed) { \
1856 void* buf = nullptr; \
1857 Py_ssize_t buflen = Utility::GetBuffer(value, code, sizeof(type), buf);\
1858 return ToArrayFromBuffer<type>(value, address, ctxt, buf, buflen, fShape, fIsFixed);\
1860 void* buf = nullptr; \
1861 Py_ssize_t buflen = Utility::GetBuffer(value, code, sizeof(void*), buf);\
1862 if (buflen == 0) return false; \
1863 *(type**)address = (type*)buf; \
1864 SetLifeLine(ctxt, value, (intptr_t)address); \
1897bool CPyCppyy::CStringArrayConverter::SetArg(
1905 para.fTypeCode =
'V';
1909#
if PY_VERSION_HEX >= 0x03000000
1916 size_t len = (size_t)PySequence_Size(pyobject);
1917 if (len == (
size_t)-1) {
1918 PyErr_SetString(PyExc_ValueError,
"can not convert sequence object of unknown length");
1923 for (
size_t i = 0; i < len; ++i) {
1924 PyObject* item = PySequence_GetItem(pyobject, i);
1932 PyErr_Format(PyExc_TypeError,
"could not convert item %d to string", (
int)i);
1940 para.fValue.fVoidp = (
void*)
fBuffer.data();
1941 para.fTypeCode =
'p';
1945 return SCharArrayConverter::SetArg(pyobject, para, ctxt);
1950PyObject* CPyCppyy::CStringArrayConverter::FromMemory(
void* address)
1960bool CPyCppyy::CStringArrayConverter::ToMemory(
PyObject* value,
void* address,
PyObject* ctxt)
1966 return ToArrayFromBuffer<char>(value, address, ctxt, cstr, len, fShape, fIsFixed);
1968 return SCharArrayConverter::ToMemory(value, address, ctxt);
1972PyObject* CPyCppyy::NonConstCStringArrayConverter::FromMemory(
void* address)
1999 Py_INCREF(pyobject);
2001 }
else if (PyUnicode_Check(pyobject)) {
2002#if PY_VERSION_HEX < 0x03030000
2003 pybytes = PyUnicode_EncodeUTF8(
2006 pybytes = PyUnicode_AsUTF8String(pyobject);
2012 const char* cstr =
nullptr;
2014 if (cstr) buffer = T{cstr, (
typename T::size_type)len};
2022#define CPPYY_IMPL_STRING_AS_PRIMITIVE_CONVERTER(name, type, F1, F2) \
2023CPyCppyy::name##Converter::name##Converter(bool keepControl) : \
2024 InstanceConverter(Cppyy::GetScope(#type), keepControl) {} \
2026bool CPyCppyy::name##Converter::SetArg( \
2027 PyObject* pyobject, Parameter& para, CallContext* ctxt) \
2029 if (CPyCppyy_PyUnicodeAsBytes2Buffer(pyobject, fBuffer)) { \
2030 para.fValue.fVoidp = &fBuffer; \
2031 para.fTypeCode = 'V'; \
2036 if (!(PyInt_Check(pyobject) || PyLong_Check(pyobject))) { \
2037 bool result = InstanceConverter::SetArg(pyobject, para, ctxt); \
2038 para.fTypeCode = 'V'; \
2045PyObject* CPyCppyy::name##Converter::FromMemory(void* address) \
2048 return InstanceConverter::FromMemory(address); \
2049 auto* empty = new type(); \
2050 return BindCppObjectNoCast(empty, fClass, CPPInstance::kIsOwner); \
2053bool CPyCppyy::name##Converter::ToMemory( \
2054 PyObject* value, void* address, PyObject* ctxt) \
2056 if (CPyCppyy_PyUnicodeAsBytes2Buffer(value, *((type*)address))) \
2058 return InstanceConverter::ToMemory(value, address, ctxt); \
2064CPyCppyy::STLWStringConverter::STLWStringConverter(
bool keepControl) :
2065 InstanceConverter(
Cppyy::GetScope(
"std::wstring"), keepControl) {}
2067bool CPyCppyy::STLWStringConverter::SetArg(
2070 if (PyUnicode_Check(pyobject)) {
2078#if PY_VERSION_HEX < 0x03000000
2079 else if (PyString_Check(pyobject)) {
2081 std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> cnv;
2082 fBuffer = cnv.from_bytes(PyString_AS_STRING(pyobject));
2084 PyObject* pyu = PyUnicode_FromString(PyString_AS_STRING(pyobject));
2085 if (!pyu)
return false;
2096 if (!(PyInt_Check(pyobject) || PyLong_Check(pyobject))) {
2105PyObject* CPyCppyy::STLWStringConverter::FromMemory(
void* address)
2108 return PyUnicode_FromWideChar(((std::wstring*)address)->c_str(), ((std::wstring*)address)->
size());
2110 return PyUnicode_FromWideChar(&w, 0);
2113bool CPyCppyy::STLWStringConverter::ToMemory(
PyObject* value,
void* address,
PyObject* ctxt)
2115 if (PyUnicode_Check(value)) {
2117 wchar_t* buf =
new wchar_t[len+1];
2119 *((std::wstring*)address) = std::wstring(buf, len);
2123 return InstanceConverter::ToMemory(value, address, ctxt);
2127CPyCppyy::STLStringViewConverter::STLStringViewConverter(
bool keepControl) :
2128 InstanceConverter(Cppyy::
GetScope(
"std::string_view"), keepControl) {}
2130bool CPyCppyy::STLStringViewConverter::SetArg(
2134 if (!PyInt_Check(pyobject) && !PyLong_Check(pyobject)) {
2135 CallContextRAII<CallContext::kNoImplicit> noimp(ctxt);
2136 if (InstanceConverter::SetArg(pyobject, para, ctxt)) {
2148 fBuffer = std::string_view(cstr, (std::string_view::size_type)len);
2161 CPPInstance* pyobj = (CPPInstance*)pyobject;
2169 fBuffer = *((std::string*)ptr);
2179PyObject* CPyCppyy::STLStringViewConverter::FromMemory(
void* address)
2182 return InstanceConverter::FromMemory(address);
2183 auto* empty =
new std::string_view();
2187bool CPyCppyy::STLStringViewConverter::ToMemory(
2191 if (InstanceConverter::ToMemory(value, address, ctxt))
2199 *
reinterpret_cast<std::string_view*
>(address) = \
2200 std::string_view(cstr, (std::string_view::size_type)len);
2208bool CPyCppyy::STLStringMoveConverter::SetArg(
2212 int moveit_reason = 3;
2214 CPPInstance* pyobj = (CPPInstance*)pyobject;
2216 pyobj->
fFlags &= ~CPPInstance::kIsRValue;
2224 if (moveit_reason) {
2225 bool result = this->STLStringConverter::SetArg(pyobject, para, ctxt);
2226 if (!result && moveit_reason == 2)
2231 PyErr_SetString(PyExc_ValueError,
"object is not an rvalue");
2237template <
bool ISCONST>
2280template <
bool ISCONST>
2290template <
bool ISCONST>
2296 void* ptr =
nullptr;
2298 *(
void**)address = ptr;