26#if PY_VERSION_HEX < 0x030b0000
46 struct InitOperatorMapping_t {
48 InitOperatorMapping_t() {
117#if PY_VERSION_HEX < 0x03000000
123 } initOperatorMapping_;
125 inline std::string full_scope(
const std::string& tpname) {
126 return tpname[0] ==
':' ? tpname :
"::"+tpname;
136 if (PyFloat_Check(pyobject)) {
137 PyErr_SetString(PyExc_TypeError,
"can\'t convert float to unsigned long");
138 return (
unsigned long)-1;
140 return (
unsigned long)0;
143 unsigned long ul = PyLong_AsUnsignedLong(pyobject);
144 if (PyErr_Occurred() && PyInt_Check(pyobject)) {
146 long i = PyInt_AS_LONG(pyobject);
148 ul = (
unsigned long)i;
150 PyErr_SetString(PyExc_ValueError,
151 "can\'t convert negative value to unsigned long");
152 return (
unsigned long)-1;
163 if (PyFloat_Check(pyobject)) {
164 PyErr_SetString(PyExc_TypeError,
"can\'t convert float to unsigned long long");
167 return (
unsigned long)0;
171 if (PyErr_Occurred() && PyInt_Check(pyobject)) {
173 long i = PyInt_AS_LONG(pyobject);
177 PyErr_SetString(PyExc_ValueError,
178 "can\'t convert negative value to unsigned long long");
187 PyObject* pyclass,
const char* label, PyCFunction cfunc,
int flags)
192 static std::list<PyMethodDef> s_pymeths;
194 s_pymeths.push_back(PyMethodDef());
195 PyMethodDef* pdef = &s_pymeths.back();
196 pdef->ml_name =
const_cast<char*
>(label);
197 pdef->ml_meth = cfunc;
198 pdef->ml_flags = flags;
199 pdef->ml_doc =
nullptr;
201 PyObject* func = PyCFunction_New(pdef,
nullptr);
204 bool isOk = PyType_Type.tp_setattro(pyclass,
name, method) == 0;
209 if (PyErr_Occurred())
213 PyErr_Format(PyExc_TypeError,
"could not add method %s", label);
224 PyObject* pyfunc = PyObject_GetAttrString(pyclass,
const_cast<char*
>(func));
229 bool isOk = PyType_Type.tp_setattro(pyclass, pylabel, pyfunc) == 0;
241 (
CPPOverload*)PyObject_GetAttrString(pyclass,
const_cast<char*
>(label));
245 if (PyErr_Occurred())
250 bool isOk = PyType_Type.tp_setattro(pyclass, pylabel, (
PyObject*)method) == 0;
269 std::string opname =
"operator";
304 bool reverse =
false;
313 const std::string& lcname =
ClassName(left);
314 const std::string& rcname =
ClassName(right);
320 const std::string& lcname,
const std::string& rcname,
327 if (rcname ==
"<unknown>" || lcname ==
"<unknown>")
335 if (lcname ==
"str" || lcname ==
"unicode" || lcname ==
"complex")
362 && lcname.find(
"__wrap_iter") == std::string::npos
375 std::stringstream fname,
proto;
376 if (strncmp(op,
"==", 2) == 0) { fname <<
"is_equal<"; }
377 else if (strncmp(op,
"!=", 2) == 0) { fname <<
"is_not_equal<"; }
378 else { fname <<
"not_implemented<"; }
379 fname << lcname <<
", " << rcname <<
">";
380 proto <<
"const " << lcname <<
"&, const " << rcname;
382 if (method) pyfunc =
new CPPFunction(s_intern, method);
396 pystr = PyObject_Str(pyobj);
416#if PY_VERSION_HEX < 0x03000000
417 long l = PyInt_AS_LONG(arg);
418 tmpl_name.append((
l < INT_MIN || INT_MAX <
l) ?
"long" :
"int");
426 tmpl_name.append(
"int");
428 tmpl_name.append(
"unsigned long long");
430 tmpl_name.append((ll < INT_MIN || INT_MAX < ll) ? \
431 ((ll < LONG_MIN || LONG_MAX < ll) ?
"long long" :
"long") :
"int");
434 tmpl_name.append(
"int");
439#if PY_VERSION_HEX < 0x03000000
440 if (tn == (
PyObject*)&PyLong_Type) {
448 tmpl_name.append(
"long");
450 tmpl_name.append(
"unsigned long long");
452 tmpl_name.append((ll < LONG_MIN || LONG_MAX < ll) ?
"long long" :
"long");
454 tmpl_name.append(
"long");
460 if (tn == (
PyObject*)&PyFloat_Type) {
462 tmpl_name.append(arg ?
"double" :
"float");
466#if PY_VERSION_HEX < 0x03000000
467 if (tn == (
PyObject*)&PyString_Type) {
469 if (tn == (
PyObject*)&PyUnicode_Type) {
471 tmpl_name.append(
"std::string");
476 if (arg && PySequence_Size(arg)) {
477 std::string subtype{
"std::initializer_list<"};
478 PyObject* item = PySequence_GetItem(arg, 0);
481 tmpl_name.append(subtype);
482 tmpl_name.append(
">");
490 if (CPPScope_Check(tn)) {
495 if (CPPInstance_Check(pyobj)) {
496 if (pyobj->
fFlags & CPPInstance::kIsRValue)
497 tmpl_name.append(
"&&");
499 if (pcnt) *pcnt += 1;
500 if ((pyobj->
fFlags & CPPInstance::kIsReference) || pref ==
kPointer)
501 tmpl_name.push_back(
'*');
503 tmpl_name.push_back(
'&');
511 if (tn == (
PyObject*)&CPPOverload_Type) {
513 PyObject_GetAttr(arg, PyStrings::gCppName) : \
514 CPyCppyy_PyText_FromString(
"void* (*)(...)");
521 if (arg && PyCallable_Check(arg)) {
522 PyObject* annot = PyObject_GetAttr(arg, PyStrings::gAnnotations);
524 if (PyDict_Check(annot) && 1 < PyDict_Size(annot)) {
525 PyObject* ret = PyDict_GetItemString(annot,
"return");
528 std::ostringstream tpn;
532 PyObject* values = PyDict_Values(annot);
533 for (
Py_ssize_t i = 0; i < (PyList_GET_SIZE(values)-1); ++i) {
535 PyObject* item = PyList_GET_ITEM(values, i);
541 tmpl_name.append(tpn.str());
552 PyObject* tpName = PyObject_GetAttr(arg, PyStrings::gCppName);
555 tmpl_name.append(CPPScope_Check(arg) ? full_scope(
cname) :
cname);
562 for (
auto nn : {PyStrings::gCppName, PyStrings::gName}) {
563 PyObject* tpName = PyObject_GetAttr(tn, nn);
572 if (PyInt_Check(tn) || PyLong_Check(tn) || PyFloat_Check(tn)) {
590 bool justOne = !PyTuple_CheckExact(tpArgs);
593 std::string tmpl_name;
594 tmpl_name.reserve(128);
597 tmpl_name.push_back(
'<');
601 Py_ssize_t nArgs = justOne ? 1 : PyTuple_GET_SIZE(tpArgs);
602 for (
int i = argoff; i < nArgs; ++i) {
604 PyObject* tn = justOne ? tpArgs : PyTuple_GET_ITEM(tpArgs, i);
610 if (!
AddTypeName(tmpl_name, tn, (args ? PyTuple_GET_ITEM(args, i) :
nullptr), pref, pcnt)) {
611 PyErr_SetString(PyExc_SyntaxError,
612 "could not construct C++ name from provided template argument.");
619 tmpl_name.push_back(
',');
623 tmpl_name.push_back(
'>');
635 const std::vector<std::string>& argtypes, std::ostringstream& code)
638 int nArgs = (
int)argtypes.size();
641 bool isVoid = retType ==
"void";
643 code <<
" CPYCPPYY_STATIC std::unique_ptr<CPyCppyy::Converter, std::function<void(CPyCppyy::Converter*)>> "
644 "retconv{CPyCppyy::CreateConverter(\""
645 << retType <<
"\"), CPyCppyy::DestroyConverter};\n";
646 std::vector<bool> arg_is_ptr;
648 arg_is_ptr.reserve(nArgs);
649 code <<
" CPYCPPYY_STATIC std::vector<std::unique_ptr<CPyCppyy::Converter, std::function<void(CPyCppyy::Converter*)>>> argcvs;\n"
650 <<
" if (argcvs.empty()) {\n"
651 <<
" argcvs.reserve(" << nArgs <<
");\n";
652 for (
int i = 0; i < nArgs; ++i) {
653 arg_is_ptr[i] =
false;
654 code <<
" argcvs.emplace_back(CPyCppyy::CreateConverter(\"";
655 const std::string& at = argtypes[i];
657 const std::string& cpd = TypeManip::compound(res_at);
664 arg_is_ptr[i] = cpd.back() ==
'*';
665 if (arg_is_ptr[i] || cpd.back() ==
'&') {
666 code << res_at.substr(0, res_at.size()-1);
670 code <<
"\"), CPyCppyy::DestroyConverter);\n";
677 code <<
" " << retType <<
" ret{};\n";
680 code <<
" PyGILState_STATE state = PyGILState_Ensure();\n";
684 code <<
" std::vector<PyObject*> pyargs;\n";
685 code <<
" pyargs.reserve(" << nArgs <<
");\n"
687 for (
int i = 0; i < nArgs; ++i) {
688 code <<
" pyargs.emplace_back(argcvs[" << i <<
"]->FromMemory((void*)";
689 if (!arg_is_ptr[i]) code <<
'&';
690 code <<
"arg" << i <<
"));\n"
691 <<
" if (!pyargs.back()) throw " << i <<
";\n";
693 code <<
" } catch(int) {\n"
694 <<
" for (auto pyarg : pyargs) Py_XDECREF(pyarg);\n"
695 <<
" CPyCppyy::PyException pyexc; PyGILState_Release(state); throw pyexc;\n"
703 bool isVoid = retType ==
"void";
707 code <<
" for (auto pyarg : pyargs) Py_DECREF(pyarg);\n";
708 code <<
" bool cOk = (bool)pyresult;\n"
709 " if (pyresult) {\n";
713 code <<
" if (!CPyCppyy::Instance_IsLively(pyresult))\n"
717 code << (isVoid ?
"" :
" cOk = retconv->ToMemory(pyresult, (void*)&ret);\n")
718 <<
" Py_DECREF(pyresult);\n }\n";
719 if (isPtr) code <<
" }\n";
720 code <<
" if (!cOk) {"
724 " /* do nothing */ }\n"
726 " CPyCppyy::PyException pyexc; PyGILState_Release(state); throw pyexc; }\n"
728 " PyGILState_Release(state);\n"
730 code << (isVoid ?
";\n }\n" :
" ret;\n }\n");
738 const std::string& retType,
const std::string& signature,
void* address)
741 static int maker_count = 0;
745 Py_INCREF(pf->second);
753 std::ostringstream fname;
754 fname <<
"ptr2func" << ++maker_count;
756 std::ostringstream code;
757 code <<
"namespace __cppyy_internal { std::function<"
758 << retType << signature <<
"> " << fname.str()
759 <<
"(intptr_t faddr) { return (" << retType <<
"(*)" << signature <<
")faddr;} }";
762 PyErr_SetString(PyExc_TypeError,
"conversion to std::function failed");
767 maker = PyObject_GetAttrString(pyscope, fname.str().c_str());
778 PyTuple_SET_ITEM(args, 0, PyLong_FromLongLong((intptr_t)address));
779 PyObject* func = PyObject_Call(maker, args, NULL);
783 ((
CPPInstance*)func)->fFlags |= CPPInstance::kIsLValue;
798 if (PyType_Ready(pytype) < 0)
803 if (PyModule_AddObject(module, (
char*)
name, (
PyObject*)pytype) < 0) {
822 if ((!check || tc ==
'*' || tc ==
'B') && PyByteArray_CheckExact(pyobject)) {
823 buf = PyByteArray_AS_STRING(pyobject);
824 return PyByteArray_GET_SIZE(pyobject);
828 if (PyObject_CheckBuffer(pyobject)) {
829 if (PySequence_Check(pyobject) && !PySequence_Size(pyobject))
833 memset(&bufinfo, 0,
sizeof(Py_buffer));
834 if (PyObject_GetBuffer(pyobject, &bufinfo, PyBUF_FORMAT) == 0) {
835 if (tc ==
'*' || strchr(bufinfo.format, tc)
839 || (
sizeof(
long int) ==
sizeof(
int) && ((tc ==
'I' && strchr(bufinfo.format,
'L')) ||
840 (tc ==
'i' && strchr(bufinfo.format,
'l'))))
842 || (tc ==
'z' && strstr(bufinfo.format,
"Zf"))
844 || (tc ==
'?' && strchr(bufinfo.format,
'b'))
848 if (check && bufinfo.itemsize !=
size) {
849 PyErr_Format(PyExc_TypeError,
850 "buffer itemsize (%ld) does not match expected size (%d)", bufinfo.itemsize,
size);
856 if (buf && bufinfo.ndim == 0)
857 buflen = bufinfo.len/bufinfo.itemsize;
858 else if (buf && bufinfo.ndim == 1)
859 buflen = bufinfo.shape ? bufinfo.shape[0] : bufinfo.len/bufinfo.itemsize;
869 }
else if (bufinfo.obj)
875 PyBufferProcs* bufprocs =
Py_TYPE(pyobject)->tp_as_buffer;
877 PySequenceMethods* seqmeths =
Py_TYPE(pyobject)->tp_as_sequence;
878 if (seqmeths != 0 && bufprocs != 0
879#
if PY_VERSION_HEX < 0x03000000
880 && bufprocs->bf_getwritebuffer != 0
881 && (*(bufprocs->bf_getsegcount))(pyobject, 0) == 1
883 && bufprocs->bf_getbuffer != 0
888#if PY_VERSION_HEX < 0x03000000
889 Py_ssize_t buflen = (*(bufprocs->bf_getwritebuffer))(pyobject, 0, &buf);
892 (*(bufprocs->bf_getbuffer))(pyobject, &bufinfo, PyBUF_WRITABLE);
893 buf = (
char*)bufinfo.buf;
898 if (buf && check ==
true) {
900 PyObject* pytc = tc !=
'*' ? PyObject_GetAttr(pyobject, PyStrings::gTypeCode) :
nullptr;
903 if (!(cpytc == tc || (tc ==
'?' && cpytc ==
'b')))
906 }
else if (seqmeths->sq_length &&
907 (
int)(buflen/(*(seqmeths->sq_length))(pyobject)) ==
size) {
910 }
else if (buflen ==
size) {
917 PyObject* pytype = 0, *pyvalue = 0, *pytrace = 0;
918 PyErr_Fetch(&pytype, &pyvalue, &pytrace);
920 (
char*)
"%s and given element size (%ld) do not match needed (%d)",
922 seqmeths->sq_length ? (
long)(buflen/(*(seqmeths->sq_length))(pyobject)) : (long)buflen,
925 PyErr_Restore(pytype, pyvalue2, pytrace);
940 if (8 <
name.size() &&
name.substr(0, 8) ==
"operator") {
941 std::string op =
name.substr(8, std::string::npos);
944 std::string::size_type start = 0, end = op.size();
945 while (start < end && isspace(op[start])) ++start;
946 while (start < end && isspace(op[end-1])) --end;
947 op = op.substr(start, end - start);
964 }
else if (op ==
"*") {
966 if (!bTakesParams)
return "__deref__";
967 if (stubbed) *stubbed =
true;
970 }
else if (op ==
"/") {
974 }
else if (op ==
"+") {
976 if (!bTakesParams)
return "__pos__";
977 if (stubbed) *stubbed =
true;
980 }
else if (op ==
"-") {
982 if (!bTakesParams)
return "__neg__";
983 if (stubbed) *stubbed =
true;
986 }
else if (op ==
"++") {
988 return bTakesParams ?
"__postinc__" :
"__preinc__";
990 }
else if (op ==
"--") {
992 return bTakesParams ?
"__postdec__" :
"__predec__";
1005 std::string clname =
"<unknown>";
1007 PyObject* pyname = PyObject_GetAttr(pyclass, PyStrings::gCppName);
1010 pyname = PyObject_GetAttr(pyclass, PyStrings::gName);
1031 std::string
tt =
"<int>::";
1032 for (
auto c : {
"std::vector",
"std::list",
"std::deque"}) {
1033 for (
auto i : {
"iterator",
"const_iterator"}) {
1035 auto pos = itname.find(
'<');
1036 if (pos != std::string::npos)
1042 auto pos = classname.find(
'<');
1043 if (pos != std::string::npos)
1068#if PY_VERSION_HEX >= 0x02030000
1069 PyGILState_STATE gstate = PyGILState_Ensure();
1071 PyGILState_Release(gstate);
1073 if (PyThreadState_GET())
1074 return PyErr_Occurred();
1086 if (PyErr_Occurred()) {
1088 PyErr_Fetch(&
e.fType, &
e.fValue, &
e.fTrace);
1089 errors.push_back(
e);
1091 return errors.size();
1098 if (errors.empty()) {
1107 for (
auto&
e : errors) {
1109 if (!unique_from_cpp)
1110 unique_from_cpp = &
e;
1113 unique_from_cpp =
nullptr;
1119 if (unique_from_cpp) {
1126 Py_INCREF(unique_from_cpp->
fType); Py_INCREF(unique_from_cpp->
fValue); Py_XINCREF(unique_from_cpp->
fTrace);
1127 PyErr_Restore(unique_from_cpp->
fType, unique_from_cpp->
fValue, unique_from_cpp->
fTrace);
1131 for (
auto&
e : errors) {
1132 if (!exc_type) exc_type =
e.fType;
1133 else if (exc_type !=
e.fType) {
1141 for (
auto&
e : errors) {
1145 }
else if (
e.fValue) {
1146 PyObject* excstr = PyObject_Str(
e.fValue);
1158 Py_DECREF(separator);
1178 "#include \"CPyCppyy/API.h\"\n"
1181 "#include \"CPyCppyy/DispatchPtr.h\"\n"
1182 "#include \"CPyCppyy/PyException.h\"\n"
PyDictEntry *(* dict_lookup_func)(PyDictObject *, PyObject *, long)
#define CPyCppyy_PyText_InternFromString
#define CPyCppyy_PyText_Append
#define CPyCppyy_PyText_AsString
#define CPyCppyy_PyText_AppendAndDel
void CPyCppyy_PyBuffer_Release(PyObject *, Py_buffer *view)
#define CPyCppyy_PyText_FromFormat
#define CPyCppyy_PyText_FromString
#define CPyCppyy_PyText_Check
unsigned long long PY_ULONG_LONG
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char cname
static std::set< std::string > sIteratorTypes
static TC2POperatorMapping_t gC2POperatorMapping
static CPyCppyy::PyCallable * BuildOperator(const std::string &lcname, const std::string &rcname, const char *op, Cppyy::TCppScope_t scope, bool reverse=false)
static std::set< std::string > gOpRemove
static std::map< std::string, PyObject * > sStdFuncMakerLookup
static std::set< std::string > gOpSkip
static std::map< void *, PyObject * > sStdFuncLookup
static bool AddTypeName(std::string &tmpl_name, PyObject *tn, PyObject *arg, CPyCppyy::Utility::ArgPreference pref, int *pcnt=nullptr)
static bool check_scope(const std::string &name)
std::map< std::string, std::string > TC2POperatorMapping_t
static std::string AnnotationAsText(PyObject *pyobj)
void AdoptMethod(PyCallable *pc)
Cppyy::TCppType_t fCppType
std::string clean_type(const std::string &cppname, bool template_strip=true, bool const_strip=true)
PyCallable * FindBinaryOperator(PyObject *left, PyObject *right, const char *op, Cppyy::TCppScope_t scope=0)
void ConstructCallbackPreamble(const std::string &retType, const std::vector< std::string > &argtypes, std::ostringstream &code)
void ConstructCallbackReturn(const std::string &retType, int nArgs, std::ostringstream &code)
Py_ssize_t GetBuffer(PyObject *pyobject, char tc, int size, void *&buf, bool check=true)
std::string ConstructTemplateArgs(PyObject *pyname, PyObject *tpArgs, PyObject *args=nullptr, ArgPreference=kNone, int argoff=0, int *pcnt=nullptr)
PyObject * FuncPtr2StdFunction(const std::string &retType, const std::string &signature, void *address)
PyCallable * FindUnaryOperator(PyObject *pyclass, const char *op)
size_t FetchError(std::vector< PyError_t > &, bool is_cpp=false)
std::string MapOperatorName(const std::string &name, bool bTakesParames, bool *stubbed=nullptr)
void SetDetailedException(std::vector< PyError_t > &errors, PyObject *topmsg, PyObject *defexc)
bool InitProxy(PyObject *module, PyTypeObject *pytype, const char *name)
bool AddToClass(PyObject *pyclass, const char *label, PyCFunction cfunc, int flags=METH_VARARGS)
bool IsSTLIterator(const std::string &classname)
std::string ClassName(PyObject *pyobj)
PyObject * PyErr_Occurred_WithGIL()
CPPOverload * CPPOverload_New(const std::string &name, std::vector< PyCallable * > &methods)
unsigned long PyLongOrInt_AsULong(PyObject *pyobject)
PyObject * gDefaultObject
PyObject * CustomInstanceMethod_New(PyObject *func, PyObject *self, PyObject *pyclass)
dict_lookup_func gDictLookupOrg
PyObject * CreateScopeProxy(Cppyy::TCppScope_t, const unsigned flags=0)
bool CPPOverload_Check(T *object)
bool CPPScope_Check(T *object)
PY_ULONG_LONG PyLongOrInt_AsULong64(PyObject *pyobject)
bool CPPInstance_Check(T *object)
PyObject * gNullPtrObject
RPY_EXPORTED bool Compile(const std::string &code, bool silent=false)
RPY_EXPORTED TCppScope_t gGlobalScope
RPY_EXPORTED TCppMethod_t GetMethodTemplate(TCppScope_t scope, const std::string &name, const std::string &proto)
RPY_EXPORTED std::string ResolveName(const std::string &cppitem_name)
RPY_EXPORTED std::string GetScopedFinalName(TCppType_t type)
RPY_EXPORTED TCppMethod_t GetMethod(TCppScope_t scope, TCppIndex_t imeth)
RPY_EXPORTED TCppScope_t GetScope(const std::string &scope_name)
RPY_EXPORTED TCppIndex_t GetGlobalOperator(TCppType_t scope, const std::string &lc, const std::string &rc, const std::string &op)
static void Clear(PyError_t &e)