48 ExtendedData() : fObject(nullptr), fSmartClass(nullptr), fTypeSize(0), fLastState(nullptr), fDispatchPtr(nullptr) {}
50 for (
auto&
pc : fDatamemberCache)
51 Py_XDECREF(
pc.second);
52 fDatamemberCache.clear();
73#define EXT_OBJECT(pyobj) ((ExtendedData*)((pyobj)->fObject))->fObject
74#define SMART_CLS(pyobj) ((ExtendedData*)((pyobj)->fObject))->fSmartClass
75#define SMART_TYPE(pyobj) SMART_CLS(pyobj)->fCppType
76#define DISPATCHPTR(pyobj) ((ExtendedData*)((pyobj)->fObject))->fDispatchPtr
77#define DATA_CACHE(pyobj) ((ExtendedData*)((pyobj)->fObject))->fDatamemberCache
83 fObject = (
void*)
new ExtendedData{};
104 PyTypeObject* pytype =
Py_TYPE(self);
105 PyObject* newinst = pytype->tp_new(pytype,
nullptr,
nullptr);
112 PyObject* cpy = PyObject_GetAttrString(self, (
char*)
"__cpp_copy__");
113 if (cpy && PyCallable_Check(cpy)) {
116 PyTuple_SET_ITEM(args, 0, newinst);
117 PyObject* res = PyObject_CallObject(cpy, args);
136 bool bMergeOk = PyDict_Merge(newdct, selfdct, 1) == 0;
171 Py_INCREF(smart_type);
247 int result = PyObject_IsTrue(pylen);
268 PyObject *mname =
nullptr, *sigarg =
nullptr;
269 if (!PyArg_ParseTuple(args,
const_cast<char*
>(
"O!O!:__dispatch__"),
274 PyObject* pymeth = PyObject_GetAttr(self, mname);
279 PyObject* pydisp = PyObject_GetAttrString(pymeth,
const_cast<char*
>(
"__overload__"));
286 PyObject* oload = PyObject_CallFunctionObjArgs(pydisp, sigarg,
nullptr);
306 {(
char*)
"__destruct__", (PyCFunction)
op_destruct, METH_NOARGS,
nullptr},
307 {(
char*)
"__dispatch__", (PyCFunction)
op_dispatch, METH_VARARGS,
308 (
char*)
"dispatch to selected overload"},
310 (
char*)
"get associated smart pointer, if any"},
311 {(
char*)
nullptr,
nullptr, 0,
nullptr}
330 PyObject_GC_UnTrack((
PyObject*)pyobj);
349 using namespace Utility;
357 const char* cppop = op == Py_EQ ?
"==" :
"!=";
369 if (binop == Py_None) {
371 if (binop && binop != Py_None) flipit =
true;
374 if (!binop || binop == Py_None)
return nullptr;
377 Py_INCREF(obj); PyTuple_SET_ITEM(args, 0, obj);
390 if (!flipit)
return result;
392 int istrue = PyObject_IsTrue(result);
403 if (op != Py_EQ && op != Py_NE) {
404 Py_INCREF(Py_NotImplemented);
405 return Py_NotImplemented;
418 if (result)
return result;
427 if ((op == Py_EQ && bIsEq) || (op == Py_NE && !bIsEq)) {
450 const_cast<char*
>(
"<%s.%s object at %p held by %s at %p>"),
467 if (
sizeof(
unsigned long) >=
sizeof(
size_t))
468 return (
Py_hash_t)PyLong_AsUnsignedLong(obj);
469 return (
Py_hash_t)PyLong_AsUnsignedLongLong(obj);
490 bool isValid = PyMapping_HasKeyString(dct, (
char*)
"__call__");
493 PyObject* hashobj = PyObject_CallObject(hashcls,
nullptr);
499 PyObject* hashval = PyObject_CallFunctionObjArgs(hashobj, (
PyObject*)self,
nullptr);
510 ((PyTypeObject*)
Py_TYPE(self))->tp_hash = PyBaseObject_Type.tp_hash;
511 return PyBaseObject_Type.tp_hash((
PyObject*)self);
518 std::ostringstream
s;
521 if (isBound) res = PyObject_CallFunctionObjArgs(lshift, pys, NULL);
522 else res = PyObject_CallFunctionObjArgs(lshift, pys, pyobj, NULL);
557 }
else if (lshift == Py_None) {
581 long shouldown = PyLong_AsLong(value);
582 if (shouldown == -1 && PyErr_Occurred()) {
583 PyErr_SetString(PyExc_ValueError,
"__python_owns__ should be either True or False");
596 (
char*)
"If true, python manages the life time of this object",
nullptr},
597 {(
char*)
nullptr,
nullptr,
nullptr,
nullptr,
nullptr}
602#define CPYCPPYY_STUB_BODY(name, op) \
605 PyCallable* pyfunc = Utility::FindBinaryOperator(left, right, #op); \
606 if (pyfunc) meth = (PyObject*)CPPOverload_New(#name, pyfunc); \
608 PyErr_SetString(PyExc_NotImplementedError, ""); \
612 PyObject* res = PyObject_CallFunctionObjArgs(meth, cppobj, other, nullptr);\
616 PyCallable* pyfunc = Utility::FindBinaryOperator(left, right, #op); \
617 if (pyfunc) ((CPPOverload*&)meth)->AdoptMethod(pyfunc); \
619 PyErr_SetString(PyExc_NotImplementedError, ""); \
623 res = PyObject_CallFunctionObjArgs(meth, cppobj, other, nullptr); \
628#define CPYCPPYY_OPERATOR_STUB(name, op, ometh) \
629static PyObject* op_##name##_stub(PyObject* left, PyObject* right) \
632 CPPClass* klass = (CPPClass*)Py_TYPE(left); \
633 if (!klass->fOperators) klass->fOperators = new Utility::PyOperators{}; \
634 PyObject*& meth = ometh; \
635 PyObject *cppobj = left, *other = right; \
636 CPYCPPYY_STUB_BODY(name, op) \
639#define CPYCPPYY_ASSOCIATIVE_OPERATOR_STUB(name, op, lmeth, rmeth) \
640static PyObject* op_##name##_stub(PyObject* left, PyObject* right) \
643 CPPClass* klass; PyObject** pmeth; \
644 PyObject *cppobj, *other; \
645 if (CPPInstance_Check(left)) { \
646 klass = (CPPClass*)Py_TYPE(left); \
647 if (!klass->fOperators) klass->fOperators = new Utility::PyOperators{};\
648 pmeth = &lmeth; cppobj = left; other = right; \
649 } else if (CPPInstance_Check(right)) { \
650 klass = (CPPClass*)Py_TYPE(right); \
651 if (!klass->fOperators) klass->fOperators = new Utility::PyOperators{};\
652 pmeth = &rmeth; cppobj = right; other = left; \
654 PyErr_SetString(PyExc_NotImplementedError, ""); \
657 PyObject*& meth = *pmeth; \
658 CPYCPPYY_STUB_BODY(name, op) \
661#define CPYCPPYY_UNARY_OPERATOR(name, op, label) \
662static PyObject* op_##name##_stub(PyObject* pyobj) \
665 PyCallable* pyfunc = Utility::FindUnaryOperator((PyObject*)Py_TYPE(pyobj), #op);\
666 if (pyfunc && Utility::AddToClass((PyObject*)Py_TYPE(pyobj), #label, pyfunc))\
667 return PyObject_CallMethod(pyobj, (char*)#label, nullptr); \
668 PyErr_SetString(PyExc_NotImplementedError, ""); \
682 (binaryfunc)op_add_stub,
683 (binaryfunc)op_sub_stub,
684 (binaryfunc)op_mul_stub,
685#
if PY_VERSION_HEX < 0x03000000
686 (binaryfunc)op_div_stub,
691 (unaryfunc)op_neg_stub,
692 (unaryfunc)op_pos_stub,
695 (unaryfunc)op_invert_stub,
701#if PY_VERSION_HEX < 0x03000000
707#if PY_VERSION_HEX < 0x03000000
714#if PY_VERSION_HEX < 0x03000000
724#if PY_VERSION_HEX >= 0x02020000
726#if PY_VERSION_HEX < 0x03000000
729 , (binaryfunc)op_div_stub
734#
if PY_VERSION_HEX >= 0x02050000
737#
if PY_VERSION_HEX >= 0x03050000
747 (
char*)
"cppyy.CPPInstance",
766 Py_TPFLAGS_BASETYPE |
768 Py_TPFLAGS_CHECKTYPES,
769 (
char*)
"cppyy object proxy (internal)",
794#if PY_VERSION_HEX >= 0x02030000
797#if PY_VERSION_HEX >= 0x02060000
800#if PY_VERSION_HEX >= 0x03040000
#define CPYCPPYY_UNARY_OPERATOR(name, op, label)
#define EXT_OBJECT(pyobj)
#define SMART_TYPE(pyobj)
#define CPYCPPYY_OPERATOR_STUB(name, op, ometh)
#define DATA_CACHE(pyobj)
#define DISPATCHPTR(pyobj)
#define CPYCPPYY_ASSOCIATIVE_OPERATOR_STUB(name, op, lmeth, rmeth)
#define CPyCppyy_PyText_AsString
#define CPyCppyy_PyText_FromFormat
#define CPyCppyy_PyText_Type
#define CPyCppyy_PyText_FromString
#define PyVarObject_HEAD_INIT(type, size)
Cppyy::TCppType_t GetSmartIsA() const
CPPInstance * Copy(void *cppinst)
CI_DatamemberCache_t & GetDatamemberCache()
void SetSmart(PyObject *smart_type)
PyObject_HEAD void * fObject
void * GetExtendedObject()
Cppyy::TCppType_t ObjectIsA(bool check_smart=true) const
void SetDispatchPtr(void *)
Utility::PyOperators * fOperators
static bool RegisterPyObject(CPPInstance *pyobj, void *cppobj)
static bool UnregisterPyObject(CPPInstance *pyobj, PyObject *pyclass)
std::string extract_namespace(const std::string &name)
PyCallable * FindBinaryOperator(PyObject *left, PyObject *right, const char *op, Cppyy::TCppScope_t scope=0)
bool AddToClass(PyObject *pyclass, const char *label, PyCFunction cfunc, int flags=METH_VARARGS)
std::string ClassName(PyObject *pyobj)
CPPOverload * CPPOverload_New(const std::string &name, std::vector< PyCallable * > &methods)
PyTypeObject CPPInstance_Type
static PyObject * op_str_internal(PyObject *pyobj, PyObject *lshift, bool isBound)
static Py_hash_t CPyCppyy_PyLong_AsHash_t(PyObject *obj)
static int op_nonzero(CPPInstance *self)
static PyMethodDef op_methods[]
static PyObject * op_repr(CPPInstance *self)
PyObject * BindCppObjectNoCast(Cppyy::TCppObject_t object, Cppyy::TCppType_t klass, const unsigned flags=0)
static PyObject * op_richcompare(CPPInstance *self, PyObject *other, int op)
std::vector< std::pair< ptrdiff_t, PyObject * > > CI_DatamemberCache_t
static int op_setownership(CPPInstance *pyobj, PyObject *value, void *)
static PyObject * eqneq_binop(CPPClass *klass, PyObject *self, PyObject *obj, int op)
static PyObject * op_getownership(CPPInstance *pyobj, void *)
static int op_clear(CPPInstance *pyobj)
void op_dealloc_nofree(CPPInstance *)
bool CPPInstance_Check(T *object)
PyObject * CreateScopeProxy(Cppyy::TCppScope_t)
static PyGetSetDef op_getset[]
PyTypeObject CPPOverload_Type
static PyNumberMethods op_as_number
static PyObject * op_str(CPPInstance *self)
static void op_dealloc(CPPInstance *pyobj)
static Py_hash_t op_hash(CPPInstance *self)
static PyObject * op_dispatch(PyObject *self, PyObject *args, PyObject *)
PyTypeObject CPPScope_Type
static PyObject * op_get_smartptr(CPPInstance *self)
static CPPInstance * op_new(PyTypeObject *subtype, PyObject *, PyObject *)
static PyObject * op_destruct(CPPInstance *self)
RPY_EXPORTED void * CallR(TCppMethod_t method, TCppObject_t self, size_t nargs, void *args)
RPY_EXPORTED void CallDestructor(TCppType_t type, TCppObject_t self)
RPY_EXPORTED std::string GetFinalName(TCppType_t type)
RPY_EXPORTED std::string GetScopedFinalName(TCppType_t type)
RPY_EXPORTED TCppScope_t GetScope(const std::string &scope_name)
RPY_EXPORTED void Destruct(TCppType_t type, TCppObject_t instance)
RPY_EXPORTED void Deallocate(TCppType_t type, TCppObject_t instance)
static constexpr double s
static constexpr double pc