112#define ct_c_uint32 10
115#define ct_c_longlong 13
116#define ct_c_ulonglong 14
118#define ct_c_double 16
119#define ct_c_longdouble 17
120#define ct_c_char_p 18
121#define ct_c_wchar_p 19
122#define ct_c_void_p 20
123#define ct_c_fcomplex 21
124#define ct_c_complex 22
125#define ct_c_pointer 23
129 "c_bool",
"c_char",
"c_wchar",
"c_byte",
"c_ubyte",
"c_short",
"c_ushort",
"c_uint16",
130 "c_int",
"c_uint",
"c_uint32",
"c_long",
"c_ulong",
"c_longlong",
"c_ulonglong",
131 "c_float",
"c_double",
"c_longdouble",
132 "c_char_p",
"c_wchar_p",
"c_void_p",
"c_fcomplex",
"c_complex",
"_Pointer" };
142 static PyObject* ctmod = PyImport_ImportModule(
"ctypes");
149 ct_t = (PyTypeObject*)PyObject_GetAttrString(ctmod,
gCTypesNames[nidx]);
150 if (!ct_t) PyErr_Clear();
161 static PyObject* ctmod = PyImport_ImportModule(
"ctypes");
169 cpt_t = (PyTypeObject*)PyObject_GetAttrString(ctmod,
"c_char_p");
173 PyObject* ptrcreat = PyObject_GetAttrString(ctmod,
"POINTER");
174 cpt_t = (PyTypeObject*)PyObject_CallFunctionObjArgs(ptrcreat, ct_t, NULL);
188 static PyTypeObject* pycarg_type =
nullptr;
190 PyObject* ctmod = PyImport_ImportModule(
"ctypes");
191 if (!ctmod) PyErr_Clear();
193 PyTypeObject* ct_t = (PyTypeObject*)PyObject_GetAttrString(ctmod,
"c_int");
194 PyObject* cobj = ct_t->tp_new(ct_t,
nullptr,
nullptr);
195 PyObject* byref = PyObject_GetAttrString(ctmod,
"byref");
196 PyObject* pyptr = PyObject_CallFunctionObjArgs(byref, cobj, NULL);
197 Py_DECREF(byref); Py_DECREF(cobj); Py_DECREF(ct_t);
203 return Py_TYPE(pyobject) == pycarg_type;
208 static PyTypeObject* cstgdict_type =
nullptr;
209 if (!cstgdict_type) {
212 if (ct_int && ct_int->tp_dict) {
213 cstgdict_type =
Py_TYPE(ct_int->tp_dict);
217 PyTypeObject* pytype =
Py_TYPE(pyobject);
218 if (pytype->tp_dict &&
Py_TYPE(pytype->tp_dict) == cstgdict_type)
228 if (!holder)
return false;
233 std::ostringstream attr_name;
234 attr_name <<
"__" << ref;
235 auto res = PyObject_SetAttrString(holder, (
char*)attr_name.str().c_str(),
target);
242 if (!holder)
return false;
244 std::ostringstream attr_name;
245 attr_name <<
"__" << ref;
246 PyObject* res = PyObject_GetAttrString(holder, (
char*)attr_name.str().c_str());
273 else if (klass && PyTuple_CheckExact(castobj)) {
322 long l = PyLong_AsLong(pyobject);
324 if (!(
l == 0||
l == 1) || PyFloat_Check(pyobject)) {
325 PyErr_SetString(PyExc_ValueError,
"boolean value should be bool, or integer 1 or 0");
333#define CPPYY_PYLONG_AS_TYPE(name, type, limit_low, limit_high) \
334static inline type CPyCppyy_PyLong_As##name(PyObject* pyobject) \
336 if (!(PyLong_Check(pyobject) || PyInt_Check(pyobject))) { \
337 if (pyobject == CPyCppyy::gDefaultObject) \
339 PyErr_SetString(PyExc_TypeError, #type" conversion expects an integer object");\
342 long l = PyLong_AsLong(pyobject); \
343 if (l < limit_low || limit_high < l) { \
344 PyErr_Format(PyExc_ValueError, "integer %ld out of range for "#type, l);\
361 if (!(PyLong_Check(pyobject) || PyInt_Check(pyobject))) {
364 PyErr_SetString(PyExc_TypeError,
"int/long conversion expects an integer object");
368 return (
long)PyLong_AsLong(pyobject);
376 if (!(PyLong_Check(pyobject) || PyInt_Check(pyobject))) {
379 PyErr_SetString(PyExc_TypeError,
"int/long conversion expects an integer object");
383 return PyLong_AsLongLong(pyobject);
401 PyErr_Format(PyExc_TypeError,
402 "could not convert argument to buffer or nullptr");
426 PyTypeObject* pytype = (PyTypeObject*)
Py_TYPE(pyobject);
427 if (!(pytype == &PyList_Type || pytype == &PyTuple_Type)) {
443 Py_INCREF(pyobject); PyTuple_SET_ITEM(args, 0, pyobject);
447 if (!pytmp && PyTuple_CheckExact(pyobject)) {
450 pytmp = (
CPPInstance*)PyObject_Call(pyscope, pyobject, NULL);
480 PyErr_SetString(PyExc_TypeError,
"C++ type cannot be converted from memory");
488 PyErr_SetString(PyExc_TypeError,
"C++ type cannot be converted to memory");
494#define CPPYY_IMPL_BASIC_CONVERTER_BODY(name, type, stype, ctype, F1, F2, tc)\
496 type val = (type)F2(pyobject); \
497 if (val == (type)-1 && PyErr_Occurred()) { \
498 static PyTypeObject* ctypes_type = nullptr; \
499 if (!ctypes_type) { \
500 PyObject* pytype = 0, *pyvalue = 0, *pytrace = 0; \
501 PyErr_Fetch(&pytype, &pyvalue, &pytrace); \
502 ctypes_type = GetCTypesType(ct_##ctype); \
503 PyErr_Restore(pytype, pyvalue, pytrace); \
505 if (Py_TYPE(pyobject) == ctypes_type) { \
507 val = *((type*)((CPyCppyy_tagCDataObject*)pyobject)->b_ptr); \
508 } else if (pyobject == CPyCppyy::gDefaultObject) { \
514 para.fValue.f##name = val; \
515 para.fTypeCode = tc; \
518#define CPPYY_IMPL_BASIC_CONVERTER_METHODS(name, type, stype, ctype, F1, F2) \
519PyObject* CPyCppyy::name##Converter::FromMemory(void* address) \
521 return F1((stype)*((type*)address)); \
524bool CPyCppyy::name##Converter::ToMemory( \
525 PyObject* value, void* address, PyObject* ) \
527 type s = (type)F2(value); \
528 if (s == (type)-1 && PyErr_Occurred()) { \
529 if (value == CPyCppyy::gDefaultObject) { \
535 *((type*)address) = (type)s; \
539#define CPPYY_IMPL_BASIC_CONVERTER_NI(name, type, stype, ctype, F1, F2, tc) \
540bool CPyCppyy::name##Converter::SetArg( \
541 PyObject* pyobject, Parameter& para, CallContext* ctxt) \
543 if (!StrictBool(pyobject, ctxt)) \
545 CPPYY_IMPL_BASIC_CONVERTER_BODY(name, type, stype, ctype, F1, F2, tc) \
547CPPYY_IMPL_BASIC_CONVERTER_METHODS(name, type, stype, ctype, F1, F2)
549#define CPPYY_IMPL_BASIC_CONVERTER_IB(name, type, stype, ctype, F1, F2, tc) \
550bool CPyCppyy::name##Converter::SetArg( \
551 PyObject* pyobject, Parameter& para, CallContext* ctxt) \
553 if (!ImplicitBool(pyobject, ctxt)) \
555 CPPYY_IMPL_BASIC_CONVERTER_BODY(name, type, stype, ctype, F1, F2, tc) \
557CPPYY_IMPL_BASIC_CONVERTER_METHODS(name, type, stype, ctype, F1, F2)
559#define CPPYY_IMPL_BASIC_CONVERTER_NB(name, type, stype, ctype, F1, F2, tc) \
560bool CPyCppyy::name##Converter::SetArg( \
561 PyObject* pyobject, Parameter& para, CallContext* ) \
563 if (PyBool_Check(pyobject)) \
565 CPPYY_IMPL_BASIC_CONVERTER_BODY(name, type, stype, ctype, F1, F2, tc) \
567CPPYY_IMPL_BASIC_CONVERTER_METHODS(name, type, stype, ctype, F1, F2)
577 PyErr_Format(PyExc_ValueError,
"%s expected, got bytes of size " PY_SSIZE_T_FORMAT,
583 PyErr_Format(PyExc_ValueError,
"%s expected, got str of size " PY_SSIZE_T_FORMAT,
587 }
else if (!PyFloat_Check(pyobject)) {
588 lchar = (
int)PyLong_AsLong(pyobject);
589 if (lchar == -1 && PyErr_Occurred())
591 else if (!(low <= lchar && lchar <= high)) {
592 PyErr_Format(PyExc_ValueError,
593 "integer to character: value %d not in range [%d,%d]", lchar, low, high);
597 PyErr_SetString(PyExc_TypeError,
"char or small int type expected");
603#define CPPYY_IMPL_REFCONVERTER_FROM_MEMORY(name, ctype) \
604PyObject* CPyCppyy::name##RefConverter::FromMemory(void* ptr) \
607 PyTypeObject* ctypes_type = GetCTypesType(ct_##ctype); \
608 if (!ctypes_type) { \
609 PyErr_SetString(PyExc_RuntimeError, "no ctypes available"); \
612 PyObject* ref = ctypes_type->tp_new(ctypes_type, nullptr, nullptr); \
613 ((CPyCppyy_tagCDataObject*)ref)->b_ptr = (char*)ptr; \
614 ((CPyCppyy_tagCDataObject*)ref)->b_needsfree = 0; \
619#define CPPYY_IMPL_BASIC_CONST_REFCONVERTER(name, type, ctype, F1) \
620bool CPyCppyy::Const##name##RefConverter::SetArg( \
621 PyObject* pyobject, Parameter& para, CallContext* ) \
623 type val = (type)F1(pyobject); \
624 if (val == (type)-1 && PyErr_Occurred()) { \
625 if (pyobject == CPyCppyy::gDefaultObject) { \
631 para.fValue.f##name = val; \
632 para.fRef = ¶.fValue.f##name; \
633 para.fTypeCode = 'r'; \
636CPPYY_IMPL_REFCONVERTER_FROM_MEMORY(Const##name, ctype)
639#define CPPYY_IMPL_BASIC_CONST_CHAR_REFCONVERTER(name, type, ctype, low, high)\
640bool CPyCppyy::Const##name##RefConverter::SetArg( \
641 PyObject* pyobject, Parameter& para, CallContext* ) \
644 type val = (type)ExtractChar(pyobject, #type, low, high); \
645 if (val == (type)-1 && PyErr_Occurred()) \
647 para.fValue.fLong = val; \
648 para.fTypeCode = 'l'; \
651CPPYY_IMPL_REFCONVERTER_FROM_MEMORY(Const##name, ctype)
655#define CPPYY_IMPL_BASIC_CHAR_CONVERTER(name, type, low, high) \
656bool CPyCppyy::name##Converter::SetArg( \
657 PyObject* pyobject, Parameter& para, CallContext* ) \
660 long val = ExtractChar(pyobject, #type, low, high); \
661 if (val == -1 && PyErr_Occurred()) \
663 para.fValue.fLong = val; \
664 para.fTypeCode = 'l'; \
668PyObject* CPyCppyy::name##Converter::FromMemory(void* address) \
671 return CPyCppyy_PyText_FromFormat("%c", *((type*)address)); \
674bool CPyCppyy::name##Converter::ToMemory( \
675 PyObject* value, void* address, PyObject* ) \
678 const char* cstr = nullptr; \
679 if (PyBytes_Check(value)) \
680 PyBytes_AsStringAndSize(value, (char**)&cstr, &len); \
682 cstr = CPyCppyy_PyText_AsStringAndSize(value, &len); \
685 PyErr_Format(PyExc_TypeError, #type" expected, got string of size %zd", len);\
688 *((type*)address) = (type)cstr[0]; \
691 long l = PyLong_AsLong(value); \
692 if (l == -1 && PyErr_Occurred()) { \
693 if (value == CPyCppyy::gDefaultObject) { \
699 if (!(low <= l && l <= high)) { \
700 PyErr_Format(PyExc_ValueError, \
701 "integer to character: value %ld not in range [%d,%d]", l, low, high);\
704 *((type*)address) = (type)l; \
718#if PY_VERSION_HEX < 0x03000000
720 para.fValue.fVoidp = (
void*)&((PyIntObject*)pyobject)->ob_ival;
721 para.fTypeCode =
'V';
728 para.fTypeCode =
'V';
733 para.fTypeCode =
'V';
737 PyErr_SetString(PyExc_TypeError,
"use ctypes.c_long for pass-by-ref of longs");
758bool CPyCppyy::IntRefConverter::SetArg(
762#if PY_VERSION_HEX < 0x03000000
764 para.
fValue.
fVoidp = (
void*)&((PyIntObject*)pyobject)->ob_ival;
770#if PY_VERSION_HEX >= 0x02050000
772 para.
fValue.
fVoidp = (
void*)((CPyCppyy_tagCDataObject*)pyobject)->b_ptr;
785#if PY_VERSION_HEX < 0x02050000
786 PyErr_SetString(PyExc_TypeError,
"use cppyy.Long for pass-by-ref of ints");
788 PyErr_SetString(PyExc_TypeError,
"use ctypes.c_int for pass-by-ref of ints");
794#define CPPYY_IMPL_REFCONVERTER(name, ctype, type, code) \
795bool CPyCppyy::name##RefConverter::SetArg( \
796 PyObject* pyobject, Parameter& para, CallContext* ) \
799 if (Py_TYPE(pyobject) == GetCTypesType(ct_##ctype)) { \
800 para.fValue.fVoidp = (void*)((CPyCppyy_tagCDataObject*)pyobject)->b_ptr;\
801 para.fTypeCode = 'V'; \
804 bool res = CArraySetArg(pyobject, para, code, sizeof(type)); \
806 PyErr_SetString(PyExc_TypeError, "use ctypes."#ctype" for pass-by-ref of "#type);\
809 para.fTypeCode = 'V'; \
812CPPYY_IMPL_REFCONVERTER_FROM_MEMORY(name, ctype)
849 return PyInt_FromLong((
long)*((
unsigned char*)address));
853bool CPyCppyy::WCharConverter::SetArg(
858 PyErr_SetString(PyExc_ValueError,
"single wchar_t character expected");
870PyObject* CPyCppyy::WCharConverter::FromMemory(
void* address)
872 return PyUnicode_FromWideChar((
const wchar_t*)address, 1);
878 PyErr_SetString(PyExc_ValueError,
"single wchar_t character expected");
885 *((
wchar_t*)address) = val;
890bool CPyCppyy::Char16Converter::SetArg(
895 PyErr_SetString(PyExc_ValueError,
"single char16_t character expected");
899 PyObject* bstr = PyUnicode_AsUTF16String(pyobject);
900 if (!bstr)
return false;
909PyObject* CPyCppyy::Char16Converter::FromMemory(
void* address)
911 return PyUnicode_DecodeUTF16((
const char*)address,
sizeof(
char16_t),
nullptr,
nullptr);
917 PyErr_SetString(PyExc_ValueError,
"single char16_t character expected");
922 if (!bstr)
return false;
924 *((
char16_t*)address) = *(
char16_t*)(
PyBytes_AS_STRING(bstr) +
sizeof(
char16_t) );
930bool CPyCppyy::Char32Converter::SetArg(
935 PyErr_SetString(PyExc_ValueError,
"single char32_t character expected");
939 PyObject* bstr = PyUnicode_AsUTF32String(pyobject);
940 if (!bstr)
return false;
949PyObject* CPyCppyy::Char32Converter::FromMemory(
void* address)
951 return PyUnicode_DecodeUTF32((
const char*)address,
sizeof(
char32_t),
nullptr,
nullptr);
957 PyErr_SetString(PyExc_ValueError,
"single char32_t character expected");
962 if (!bstr)
return false;
964 *((
char32_t*)address) = *(
char32_t*)(
PyBytes_AS_STRING(bstr) +
sizeof(
char32_t) );
982bool CPyCppyy::ULongConverter::SetArg(
990 if (para.fValue.fULong == (
unsigned long)-1 && PyErr_Occurred())
992 para.fTypeCode =
'L';
996PyObject* CPyCppyy::ULongConverter::FromMemory(
void* address)
999 return PyLong_FromUnsignedLong(*((
unsigned long*)address));
1006 if (u == (
unsigned long)-1 && PyErr_Occurred()) {
1009 u = (
unsigned long)0;
1013 *((
unsigned long*)address) = u;
1018PyObject* CPyCppyy::UIntConverter::FromMemory(
void* address)
1021 return PyLong_FromUnsignedLong(*((
unsigned int*)address));
1028 if (u == (
unsigned long)-1 && PyErr_Occurred())
1031 if (u > (
unsigned long)UINT_MAX) {
1032 PyErr_SetString(PyExc_OverflowError,
"value too large for unsigned int");
1036 *((
unsigned int*)address) = (
unsigned int)u;
1042 Float,
float,
double, c_float, PyFloat_FromDouble, PyFloat_AsDouble,
'f')
1044 Double,
double,
double, c_double, PyFloat_FromDouble, PyFloat_AsDouble,
'd')
1049CPyCppyy::ComplexDConverter::ComplexDConverter(
bool keepControl) :
1050 InstanceConverter(Cppyy::GetScope(
"std::complex<double>"), keepControl) {}
1053bool CPyCppyy::ComplexDConverter::SetArg(
1056 const Py_complex& pc = PyComplex_AsCComplex(pyobject);
1057 if (pc.real != -1.0 || !PyErr_Occurred()) {
1065 return this->InstanceConverter::SetArg(pyobject, para, ctxt);
1068PyObject* CPyCppyy::ComplexDConverter::FromMemory(
void* address)
1070 std::complex<double>* dc = (std::complex<double>*)address;
1071 return PyComplex_FromDoubles(dc->real(), dc->imag());
1076 const Py_complex& pc = PyComplex_AsCComplex(
value);
1077 if (pc.real != -1.0 || !PyErr_Occurred()) {
1078 std::complex<double>* dc = (std::complex<double>*)address;
1083 return this->InstanceConverter::ToMemory(
value, address, ctxt);
1087bool CPyCppyy::DoubleRefConverter::SetArg(
1091#if PY_VERSION_HEX < 0x03000000
1093 para.
fValue.
fVoidp = (
void*)&((PyFloatObject*)pyobject)->ob_fval;
1099#if PY_VERSION_HEX >= 0x02050000
1101 para.
fValue.
fVoidp = (
void*)((CPyCppyy_tagCDataObject*)pyobject)->b_ptr;
1114#if PY_VERSION_HEX < 0x02050000
1115 PyErr_SetString(PyExc_TypeError,
"use cppyy.Double for pass-by-ref of doubles");
1117 PyErr_SetString(PyExc_TypeError,
"use ctypes.c_double for pass-by-ref of doubles");
1131 PyErr_SetString(PyExc_SystemError,
"void/unknown arguments can\'t be set");
1136bool CPyCppyy::LLongConverter::SetArg(
1144 if (PyErr_Occurred())
1150PyObject* CPyCppyy::LLongConverter::FromMemory(
void* address)
1160 if (ll == -1 && PyErr_Occurred()) {
1172bool CPyCppyy::ULLongConverter::SetArg(
1180 if (PyErr_Occurred())
1186PyObject* CPyCppyy::ULLongConverter::FromMemory(
void* address)
1189 return PyLong_FromUnsignedLongLong(*(
PY_ULONG_LONG*)address);
1196 if (PyErr_Occurred()) {
1208bool CPyCppyy::CStringConverter::SetArg(
1216 PyObject* pytype = 0, *pyvalue = 0, *pytrace = 0;
1217 PyErr_Fetch(&pytype, &pyvalue, &pytrace);
1220 para.
fValue.
fVoidp = (
void*)((CPyCppyy_tagCDataObject*)pyobject)->b_ptr;
1222 Py_XDECREF(pytype); Py_XDECREF(pyvalue); Py_XDECREF(pytrace);
1225 PyErr_Restore(pytype, pyvalue, pytrace);
1230 if (fMaxSize != std::string::npos && fMaxSize <
fBuffer.size())
1231 PyErr_Warn(PyExc_RuntimeWarning, (
char*)
"string too long for char array (truncated)");
1236 if (fMaxSize != std::string::npos)
1237 fBuffer.resize(fMaxSize,
'\0');
1248PyObject* CPyCppyy::CStringConverter::FromMemory(
void* address)
1251 if (address && *(
void**)address) {
1252 if (fMaxSize != std::string::npos)
1255 if (*(
void**)address == (
void*)
fBuffer.data())
1272 if (!cstr)
return false;
1275 if (fMaxSize != std::string::npos && fMaxSize < (std::string::size_type)
len)
1276 PyErr_Warn(PyExc_RuntimeWarning, (
char*)
"string too long for char array (truncated)");
1281 void* ptrval = *(
void**)address;
1282 if (ptrval == (
void*)
fBuffer.data()) {
1284 *(
void**)address = (
void*)
fBuffer.data();
1286 }
else if (ptrval &&
HasLifeLine(ctxt, (intptr_t)ptrval)) {
1294 *(
void**)address = (
void*)cstr;
1299 if (fMaxSize != std::string::npos)
1300 strncpy(*(
char**)address, cstr, fMaxSize);
1303 strcpy(*(
char**)address, cstr);
1309bool CPyCppyy::WCStringConverter::SetArg(
1329PyObject* CPyCppyy::WCStringConverter::FromMemory(
void* address)
1332 if (address && *(
wchar_t**)address) {
1333 if (fMaxSize != std::wstring::npos)
1334 return PyUnicode_FromWideChar(*(
wchar_t**)address, (
Py_ssize_t)fMaxSize);
1336 return PyUnicode_FromWideChar(*(
wchar_t**)address, wcslen(*(
wchar_t**)address));
1341 return PyUnicode_FromWideChar(&
w, 0);
1352 if (fMaxSize != std::wstring::npos && fMaxSize < (std::wstring::size_type)
len)
1353 PyErr_Warn(PyExc_RuntimeWarning, (
char*)
"string too long for wchar_t array (truncated)");
1356 if (fMaxSize != std::wstring::npos)
1362 if (res == -1)
return false;
1367#define CPYCPPYY_WIDESTRING_CONVERTER(name, type, encode, decode, snull) \
1368bool CPyCppyy::name##Converter::SetArg( \
1369 PyObject* pyobject, Parameter& para, CallContext* ) \
1372 PyObject* bstr = encode(pyobject); \
1373 if (!bstr) return false; \
1375 Py_ssize_t len = PyBytes_GET_SIZE(bstr) - sizeof(type) ; \
1376 fBuffer = (type*)realloc(fBuffer, len + sizeof(type)); \
1377 memcpy(fBuffer, PyBytes_AS_STRING(bstr) + sizeof(type) , len); \
1380 fBuffer[len/sizeof(type)] = snull; \
1381 para.fValue.fVoidp = (void*)fBuffer; \
1382 para.fTypeCode = 'p'; \
1386PyObject* CPyCppyy::name##Converter::FromMemory(void* address) \
1389 if (address && *(type**)address) { \
1390 if (fMaxSize != std::wstring::npos) \
1391 return decode(*(const char**)address, (Py_ssize_t)fMaxSize*sizeof(type), nullptr, nullptr);\
1392 return decode(*(const char**)address, \
1393 std::char_traits<type>::length(*(type**)address)*sizeof(type), nullptr, nullptr);\
1398 return decode((const char*)&w, 0, nullptr, nullptr); \
1401bool CPyCppyy::name##Converter::ToMemory(PyObject* value, void* address, PyObject* )\
1404 PyObject* bstr = encode(value); \
1405 if (!bstr) return false; \
1407 Py_ssize_t len = PyBytes_GET_SIZE(bstr) - sizeof(type) ; \
1408 Py_ssize_t maxbytes = (Py_ssize_t)fMaxSize*sizeof(type); \
1411 if (fMaxSize != std::wstring::npos && maxbytes < len) { \
1412 PyErr_Warn(PyExc_RuntimeWarning, (char*)"string too long for "#type" array (truncated)");\
1416 memcpy(*((void**)address), PyBytes_AS_STRING(bstr) + sizeof(type) , len);\
1419 if (len/sizeof(type) < fMaxSize) (*(type**)address)[len/sizeof(type)] = snull;\
1427bool CPyCppyy::NonConstCStringConverter::SetArg(
1431 if (this->CStringConverter::SetArg(pyobject, para, ctxt))
1436 return CArraySetArg(pyobject, para,
'c',
sizeof(
char));
1440PyObject* CPyCppyy::NonConstCStringConverter::FromMemory(
void* address)
1443 if (fMaxSize != std::string::npos)
1445 return this->CStringConverter::FromMemory(address);
1458 if (PyInt_CheckExact(pyobject) || PyLong_CheckExact(pyobject)) {
1459 intptr_t val = (intptr_t)PyLong_AsLongLong(pyobject);
1461 address = (
void*)val;
1504 para.
fValue.
fVoidp = (
void*)((CPyCppyy_tagCDataObject*)pyobject)->b_ptr;
1511 void** payload = (
void**)((CPyCppyy_tagCDataObject*)pyobject)->b_ptr;
1536 if (!address || *(uintptr_t*)address == 0) {
1559 void* ptr =
nullptr;
1561 *(
void**)address = ptr;
1566 void* buf =
nullptr;
1568 if (!buf || buflen == 0)
1571 *(
void**)address = buf;
1592 oldsz *= shape[idim];
1595 PyErr_SetString(PyExc_ValueError,
"buffer too large for value");
1600 memcpy(*(
type**)address, buf, (0 < buflen ? buflen : 1)*
sizeof(
type));
1613#define CPPYY_IMPL_ARRAY_CONVERTER(name, ctype, type, code, suffix) \
1614CPyCppyy::name##ArrayConverter::name##ArrayConverter(cdims_t dims) : \
1616 fIsFixed = dims ? fShape[0] != UNKNOWN_SIZE : false; \
1619bool CPyCppyy::name##ArrayConverter::SetArg( \
1620 PyObject* pyobject, Parameter& para, CallContext* ctxt) \
1623 bool convOk = false; \
1626 if (fShape.ndim() == 2) { \
1627 if (Py_TYPE(pyobject) == GetCTypesPtrType(ct_##ctype)) { \
1628 para.fValue.fVoidp = (void*)((CPyCppyy_tagCDataObject*)pyobject)->b_ptr;\
1629 para.fTypeCode = 'p'; \
1631 } else if (Py_TYPE(pyobject) == GetCTypesType(ct_c_void_p)) { \
1633 para.fValue.fVoidp = (void*)((CPyCppyy_tagCDataObject*)pyobject)->b_ptr;\
1634 para.fTypeCode = 'p'; \
1636 } else if (LowLevelView_Check(pyobject) && \
1637 ((LowLevelView*)pyobject)->fBufInfo.ndim == 2 && \
1638 strchr(((LowLevelView*)pyobject)->fBufInfo.format, code)) { \
1639 para.fValue.fVoidp = ((LowLevelView*)pyobject)->get_buf(); \
1640 para.fTypeCode = 'p'; \
1647 PyTypeObject* ctypes_type = GetCTypesType(ct_##ctype); \
1648 if (Py_TYPE(pyobject) == ctypes_type) { \
1649 para.fValue.fVoidp = (void*)((CPyCppyy_tagCDataObject*)pyobject)->b_ptr;\
1650 para.fTypeCode = 'p'; \
1652 } else if (Py_TYPE(pyobject) == GetCTypesPtrType(ct_##ctype)) { \
1653 para.fValue.fVoidp = (void*)((CPyCppyy_tagCDataObject*)pyobject)->b_ptr;\
1654 para.fTypeCode = 'V'; \
1656 } else if (IsPyCArgObject(pyobject)) { \
1657 CPyCppyy_tagPyCArgObject* carg = (CPyCppyy_tagPyCArgObject*)pyobject;\
1658 if (carg->obj && Py_TYPE(carg->obj) == ctypes_type) { \
1659 para.fValue.fVoidp = (void*)((CPyCppyy_tagCDataObject*)carg->obj)->b_ptr;\
1660 para.fTypeCode = 'p'; \
1668 bool ismulti = fShape.ndim() > 1; \
1669 convOk = CArraySetArg(pyobject, para, code, ismulti ? sizeof(void*) : sizeof(type), true);\
1673 if (convOk) SetLifeLine(ctxt->fPyContext, pyobject, (intptr_t)this); \
1678PyObject* CPyCppyy::name##ArrayConverter::FromMemory(void* address) \
1681 return CreateLowLevelView##suffix((type**)address, fShape); \
1682 return CreateLowLevelView##suffix(*(type**)address, fShape); \
1685bool CPyCppyy::name##ArrayConverter::ToMemory( \
1686 PyObject* value, void* address, PyObject* ctxt) \
1688 if (fShape.ndim() <= 1 || fIsFixed) { \
1689 void* buf = nullptr; \
1690 Py_ssize_t buflen = Utility::GetBuffer(value, code, sizeof(type), buf);\
1691 return ToArrayFromBuffer<type>(value, address, ctxt, buf, buflen, fShape, fIsFixed);\
1693 void* buf = nullptr; \
1694 Py_ssize_t buflen = Utility::GetBuffer(value, code, sizeof(void*), buf);\
1695 if (buflen == 0) return false; \
1696 *(type**)address = (type*)buf; \
1697 SetLifeLine(ctxt, value, (intptr_t)address); \
1707#if __cplusplus > 201402L
1728bool CPyCppyy::CStringArrayConverter::SetArg(
1736 para.fTypeCode =
'V';
1740#
if PY_VERSION_HEX >= 0x03000000
1747 size_t len = (size_t)PySequence_Size(pyobject);
1748 if (
len == (
size_t)-1) {
1749 PyErr_SetString(PyExc_ValueError,
"can not convert sequence object of unknown length");
1754 for (
size_t i = 0;
i <
len; ++
i) {
1755 PyObject* item = PySequence_GetItem(pyobject,
i);
1763 PyErr_Format(PyExc_TypeError,
"could not convert item %d to string", (
int)
i);
1771 para.fValue.fVoidp = (
void*)
fBuffer.data();
1772 para.fTypeCode =
'p';
1776 return SCharArrayConverter::SetArg(pyobject, para, ctxt);
1781PyObject* CPyCppyy::CStringArrayConverter::FromMemory(
void* address)
1797 return ToArrayFromBuffer<char>(
value, address, ctxt, cstr,
len, fShape, fIsFixed);
1799 return SCharArrayConverter::ToMemory(
value, address, ctxt);
1803PyObject* CPyCppyy::NonConstCStringArrayConverter::FromMemory(
void* address)
1830 Py_INCREF(pyobject);
1832 }
else if (PyUnicode_Check(pyobject)) {
1833#if PY_VERSION_HEX < 0x03030000
1834 pybytes = PyUnicode_EncodeUTF8(
1837 pybytes = PyUnicode_AsUTF8String(pyobject);
1843 const char* cstr =
nullptr;
1845 if (cstr) buffer = T{cstr, (
typename T::size_type)
len};
1853#define CPPYY_IMPL_STRING_AS_PRIMITIVE_CONVERTER(name, type, F1, F2) \
1854CPyCppyy::name##Converter::name##Converter(bool keepControl) : \
1855 InstanceConverter(Cppyy::GetScope(#type), keepControl) {} \
1857bool CPyCppyy::name##Converter::SetArg( \
1858 PyObject* pyobject, Parameter& para, CallContext* ctxt) \
1860 if (CPyCppyy_PyUnicodeAsBytes2Buffer(pyobject, fBuffer)) { \
1861 para.fValue.fVoidp = &fBuffer; \
1862 para.fTypeCode = 'V'; \
1867 if (!(PyInt_Check(pyobject) || PyLong_Check(pyobject))) { \
1868 bool result = InstanceConverter::SetArg(pyobject, para, ctxt); \
1869 para.fTypeCode = 'V'; \
1876PyObject* CPyCppyy::name##Converter::FromMemory(void* address) \
1879 return InstanceConverter::FromMemory(address); \
1880 auto* empty = new type(); \
1881 return BindCppObjectNoCast(empty, fClass, CPPInstance::kIsOwner); \
1884bool CPyCppyy::name##Converter::ToMemory( \
1885 PyObject* value, void* address, PyObject* ctxt) \
1887 if (CPyCppyy_PyUnicodeAsBytes2Buffer(value, *((type*)address))) \
1889 return InstanceConverter::ToMemory(value, address, ctxt); \
1896CPyCppyy::STLWStringConverter::STLWStringConverter(
bool keepControl) :
1897 InstanceConverter(
Cppyy::GetScope(
"std::wstring"), keepControl) {}
1899bool CPyCppyy::STLWStringConverter::SetArg(
1902 if (PyUnicode_Check(pyobject)) {
1910#if PY_VERSION_HEX < 0x03000000
1911 else if (PyString_Check(pyobject)) {
1913 std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> cnv;
1914 fBuffer = cnv.from_bytes(PyString_AS_STRING(pyobject));
1916 PyObject* pyu = PyUnicode_FromString(PyString_AS_STRING(pyobject));
1917 if (!pyu)
return false;
1928 if (!(PyInt_Check(pyobject) || PyLong_Check(pyobject))) {
1937PyObject* CPyCppyy::STLWStringConverter::FromMemory(
void* address)
1940 return PyUnicode_FromWideChar(((std::wstring*)address)->c_str(), ((std::wstring*)address)->
size());
1942 return PyUnicode_FromWideChar(&
w, 0);
1947 if (PyUnicode_Check(
value)) {
1949 wchar_t* buf =
new wchar_t[
len+1];
1951 *((std::wstring*)address) = std::wstring(buf,
len);
1955 return InstanceConverter::ToMemory(
value, address, ctxt);
1959#if __cplusplus > 201402L
1960CPyCppyy::STLStringViewConverter::STLStringViewConverter(
bool keepControl) :
1961 InstanceConverter(Cppyy::
GetScope(
"std::string_view"), keepControl) {}
1963bool CPyCppyy::STLStringViewConverter::SetArg(
1967 if (!PyInt_Check(pyobject) && !PyLong_Check(pyobject)) {
1969 if (InstanceConverter::SetArg(pyobject, para, ctxt)) {
1981 fBuffer = std::string_view(cstr, (std::string_view::size_type)
len);
2002 fBuffer = *((std::string*)ptr);
2012PyObject* CPyCppyy::STLStringViewConverter::FromMemory(
void* address)
2015 return InstanceConverter::FromMemory(address);
2016 auto* empty =
new std::string_view();
2020bool CPyCppyy::STLStringViewConverter::ToMemory(
2024 if (InstanceConverter::ToMemory(
value, address, ctxt))
2032 *
reinterpret_cast<std::string_view*
>(address) = \
2033 std::string_view(cstr, (std::string_view::size_type)
len);
2042bool CPyCppyy::STLStringMoveConverter::SetArg(
2046 int moveit_reason = 3;
2048 CPPInstance* pyobj = (CPPInstance*)pyobject;
2050 pyobj->
fFlags &= ~CPPInstance::kIsRValue;
2058 if (moveit_reason) {
2059 bool result = this->STLStringConverter::SetArg(pyobject, para, ctxt);
2060 if (!
result && moveit_reason == 2)
2065 PyErr_SetString(PyExc_ValueError,
"object is not an rvalue");
2071template <
bool ISCONST>
2114template <
bool ISCONST>
2124template <
bool ISCONST>
2130 void* ptr =
nullptr;
2132 *(
void**)address = ptr;
3139 return (
h->second)(dims);
3146 if (resolvedType != fullType) {
3149 return (
h->second)(dims);
3153 bool isConst = strncmp(resolvedType.c_str(),
"const", 5) == 0;
3160 return (
h->second)(dims);
3167 return (
h->second)(dims);
3171 if (cpd.compare(0, 3,
"*[]") == 0) {
3177 if (realType !=
"void" && realType !=
"char") {
3185 for (
int i = 2;
i < (newdim-1); ++
i)
3186 newdims[
i] = dims[
i-1];
3189 return (
h->second)(newdims);
3191 return (
h->second)(dims);
3194 }
else if (!cpd.empty() && (std::string::size_type)std::count(cpd.begin(), cpd.end(),
'*') == cpd.size()) {
3198 return (
h->second)((!dims && 1 < cpd.size()) ?
dims_t(cpd.size()) : dims);
3200 }
else if (2 <= cpd.size() && (std::string::size_type)std::count(cpd.begin(), cpd.end(),
'[') == cpd.size() / 2) {
3204 return (
h->second)(dims);
3208 if (realType.compare(0, 16,
"initializer_list") == 0) {
3210 auto pos = realType.find(
'<');
3211 std::string value_type = realType.substr(pos+1, realType.size()-pos-2);
3212 return new InitializerListConverter(
Cppyy::GetScope(realType), value_type);
3216 bool control = cpd ==
"&" || isConst;
3219 auto pos = resolvedType.find(
"function<");
3220 if (pos == 0 || pos == 5 ||
3221 pos == 6 || pos == 11 ) {
3229 auto pos1 = resolvedType.find(
"(", pos+9);
3230 auto pos2 = resolvedType.rfind(
")");
3231 if (pos1 != std::string::npos && pos2 != std::string::npos) {
3232 auto sz1 = pos1-pos-9;
3233 if (resolvedType[pos+9+sz1-1] ==
' ') sz1 -= 1;
3235 return new StdFunctionConverter(cnv,
3236 resolvedType.substr(pos+9, sz1), resolvedType.substr(pos1, pos2-pos1+1));
3248 result =
new SmartPtrConverter(klass, raw, control);
3249 }
else if (cpd ==
"&") {
3250 result =
new SmartPtrConverter(klass, raw);
3252 result =
new SmartPtrConverter(klass, raw, control,
true);
3259 static STLIteratorConverter
c;
3267 if (std::regex_search(resolvedType, sm,
s_fnptr)) {
3269 auto pos1 = sm.position(0);
3270 auto pos2 = resolvedType.rfind(
')');
3271 result =
new FunctionPointerConverter(
3272 resolvedType.substr(0, pos1), resolvedType.substr(pos1+sm.length(), pos2-1));
3276 if (!
result && cpd ==
"&&") {
3280 return (
h->second)(dims);
3282 result =
new NotImplementedConverter();
3290 if (cpd.size() == 2 && cpd !=
"&&")
3291 result =
new VoidPtrPtrConverter(dims.
ndim());
3292 else if (!cpd.empty())
3295 result =
new NotImplementedConverter();