31#include <unordered_set>
38extern std::unordered_set<interop::TCppScope_t>
gPinnedTypes;
42typedef std::unordered_map<interop::TCppScope_t, PyObject*>
PyClassMap_t;
58 PyObject* pymetabases = PyTuple_New(PyTuple_GET_SIZE(pybases));
59 for (
int i = 0; i < PyTuple_GET_SIZE(pybases); ++i) {
62 PyTuple_SET_ITEM(pymetabases, i, btype);
69 Py_BuildValue((
char*)
"sO{}", (
name +
"_meta").c_str(), pymetabases);
71 Py_DECREF(pymetabases);
83 args = Py_BuildValue((
char*)
"sO{}",
name.c_str(), pybases);
85 ((PyTypeObject*)pymeta)->tp_new((PyTypeObject*)pymeta, args,
nullptr);
97 PyObject* pname = PyUnicode_InternFromString(
98 const_cast<char*
>(
property->GetName().c_str()));
102 if (PyErr_Occurred()) {
114 PyType_Type.tp_setattro((
PyObject*)Py_TYPE(pyclass), pname,
124 PyObject* pyname = PyUnicode_InternFromString((
char*)
name.c_str());
126 PyType_Type.tp_setattro(parent, pyname, newscope);
128 PyObject_SetAttr(parent, pyname, newscope);
149 const std::string& mtCppName,
150 const std::string& mtName) {
152 PyObject* pyname = PyUnicode_FromString(
const_cast<char*
>(mtName.c_str()));
161 PyType_Type.tp_setattro(pyclass, pyname, (
PyObject*)pytmpl);
169 const unsigned int flags) {
176 bool hasConstructor =
false;
180 typedef std::vector<PyCallable*> Callables_t;
181 typedef std::unordered_map<std::string, Callables_t> CallableCache_t;
182 CallableCache_t cache;
185 getattrofunc oldgetattro = Py_TYPE(pyclass)->tp_getattro;
186 Py_TYPE(pyclass)->tp_getattro = PyType_Type.tp_getattro;
190 std::vector<interop::TCppMethod_t> methods;
194 for (
auto& method : methods) {
211 bool setupSetItem =
false;
217 bool isStubbedOperator =
false;
224 if (mtCppName[0] ==
'~')
234 bool isCall = mtName ==
"__call__";
235 if (isCall || mtName ==
"__getitem__") {
236 const std::string& qual_return =
239 if (!cpd.empty() && cpd[cpd.size() - 1] ==
'&' &&
240 qual_return.find(
"const", 0, 5) == std::string::npos) {
241 if (isCall && !potGetItem)
255 bool storeOnTemplate = isTemplate;
256 if (storeOnTemplate) {
266 else if (isNamespace)
268 else if (isConstructor) {
270 hasConstructor =
true;
278 }
else if (isStubbedOperator) {
283 if (storeOnTemplate) {
287 PyObject_GetAttrString(pyclass,
const_cast<char*
>(mtName.c_str()));
301 if (pysi && !precursor)
306 Py_XDECREF(precursor);
307 PyObject_SetAttrString(pyclass,
const_cast<char*
>(
"__setitem__"),
320 (*(cache.insert(std::make_pair(mtName, Callables_t())).first)).second;
321 md.push_back(pycall);
326 Callables_t& setitem =
328 .insert(std::make_pair(std::string(
"__setitem__"),
332 setitem.push_back(
new CPPSetItem(scope, method));
338 std::vector<interop::TCppMethod_t> templ_methods;
340 for (
auto& method : templ_methods) {
341 const std::string mtCppName =
350 std::string mtName0 =
355 if (!isConstructor) {
357 if (mtName0 != mtName1)
363 if (!hasConstructor) {
371 }
else if (isNamespace) {
379 cache[
"__init__"].push_back(defctor);
384 Callables_t& getitem =
387 std::make_pair(std::string(
"__getitem__"), Callables_t()))
390 getitem.push_back(
new CPPGetItem(scope, potGetItem));
395 for (CallableCache_t::iterator imd = cache.begin(); imd != cache.end();
402 PyUnicode_FromString(
const_cast<char*
>(imd->first.c_str()));
407 for (
auto cit : imd->second)
414 PyObject* pymname = PyUnicode_InternFromString(
415 const_cast<char*
>(method->
GetName().c_str()));
416 PyType_Type.tp_setattro(pyclass, pymname, (
PyObject*)method);
426 std::vector<interop::TCppScope_t> datamembers;
428 for (
auto& datamember : datamembers) {
439 PyObject* eset = PyObject_GetAttrString(
452 "(anonymous)") != 0 ||
465 Py_TYPE(pyclass)->tp_getattro = oldgetattro;
473 std::deque<interop::TCppScope_t>& uqb) {
479 for (
size_t ibase = 0; ibase < nbases; ++ibase) {
484 for (
size_t ibase2 = 0; ibase2 < uqb.size(); ++ibase2) {
485 if (uqb[ibase2] == tp) {
499 }
else if (decision == 2) {
509 std::deque<interop::TCppScope_t> uqb;
513 size_t nbases = uqb.size();
515 PyObject* pybases = PyTuple_New(nbases ? nbases : 1);
524 for (std::deque<interop::TCppScope_t>::size_type ibase = 0; ibase < nbases;
532 PyTuple_SET_ITEM(pybases, ibase, pyclass);
537 if (!PyObject_IsSubclass(PyTuple_GET_ITEM(pybases, 0),
539 PyObject* newpybases = PyTuple_New(nbases + 1);
542 for (
int ibase = 0; ibase < (
int)nbases; ++ibase) {
543 PyObject* pyclass = PyTuple_GET_ITEM(pybases, ibase);
545 PyTuple_SET_ITEM(newpybases, ibase + 1, pyclass);
548 pybases = newpybases;
560 PyClassMap_t::iterator pci =
gPyClasses.find(scope);
577 PyDict_GetItemString(
gPyTypeMap, resolved.c_str());
578 if (tc && PyCallable_Check(tc)) {
581 PyObject_CallFunction(tc, (
char*)
"ss",
name.c_str(),
582 scName !=
"<unnamed>" ? scName.c_str() :
"");
600 std::string
cname = PyUnicode_AsUTF8(PyTuple_GetItem(args, 0));
601 if (PyErr_Occurred())
609 const unsigned flags) {
616 parent_scope = ((
CPPScope*)parent)->fCppType;
618 PyObject* parname = PyObject_GetAttr(parent, PyStrings::gName);
620 PyErr_Format(PyExc_SystemError,
"given scope has no name for %s",
626 std::string scName = PyUnicode_AsUTF8(parname);
628 if (PyErr_Occurred())
658 PyErr_Format(PyExc_TypeError,
"\'%s\' is not a known C++ class",
666 const unsigned flags) {
675 parent_scope = ((
CPPScope*)parent)->fCppType;
689 bool is_typedef =
false;
690 std::string typedefed_name =
"";
695 if ((underlying_scope) && (underlying_scope != scope)) {
696 scope = underlying_scope;
702 PyErr_Format(PyExc_TypeError,
"\'%s\' is not a known C++ class",
713 PyObject* cppscope = PyLong_FromVoidPtr(scope.data);
714 PyObject* pytemplate = PyObject_CallFunction(
715 pytcl,
const_cast<char*
>(
"sO"),
762 if (pyscope && !(((
CPPScope*)pyscope)->
fFlags & CPPScope::kIsInComplete)) {
763 gPyClasses[scope] = PyWeakref_NewRef(pyscope,
nullptr);
773 PyObject* pyfullname = PyObject_GetAttr(pyscope, PyStrings::gModule);
774 PyUnicode_AppendAndDel(&pyfullname, PyUnicode_FromString(
"."));
775 PyUnicode_AppendAndDel(&pyfullname,
776 PyObject_GetAttr(pyscope, PyStrings::gName));
777 PyObject* modules = PySys_GetObject(
const_cast<char*
>(
"modules"));
778 if (modules && PyDict_Check(modules))
779 PyDict_SetItem(modules, pyfullname, pyscope);
780 Py_DECREF(pyfullname);
786 if (pyscope && !(((
CPPScope*)pyscope)->
fFlags & CPPScope::kIsInComplete)) {
790 if (is_typedef && !typedefed_name.empty())
809 std::deque<interop::TCppScope_t> uqb;
811 size_t nbases = uqb.size();
832 for (std::deque<interop::TCppScope_t>::size_type ibase = 0; ibase < nbases;
843 PyObject* excbase = PyObject_GetAttrString(
845 Py_DECREF(base_parent);
852 Py_XDECREF(best_base);
863 PyTuple_SET_ITEM(pybases, 0, best_base);
866 PyObject* args = Py_BuildValue((
char*)
"OO{}", pyname, pybases);
870 PyObject* dct = PyTuple_GET_ITEM(args, 2);
871 PyDict_SetItem(dct, PyStrings::gUnderlying, pyscope);
872 PyDict_SetItem(dct, PyStrings::gName,
873 PyObject_GetAttr(pyscope, PyStrings::gName));
874 PyDict_SetItem(dct, PyStrings::gCppName,
875 PyObject_GetAttr(pyscope, PyStrings::gCppName));
876 PyDict_SetItem(dct, PyStrings::gModule,
877 PyObject_GetAttr(pyscope, PyStrings::gModule));
880 PyObject* exc_pyscope = PyType_Type.tp_new(&PyType_Type, args,
nullptr);
885 PyType_Type.tp_setattro(parent, pyname, exc_pyscope);
892 const unsigned flags) {
895 PyErr_SetString(PyExc_TypeError,
"attempt to bind C++ object w/o class");
904 bool noReg = flags & (CPPInstance::kNoMemReg | CPPInstance::kNoWrapConv);
905 bool isRef = flags & CPPInstance::kIsReference;
907 isRef ? (address ? *(
void**)address.data :
nullptr) : address.data;
911 PyObject* smart_type = (!(flags & CPPInstance::kNoWrapConv) &&
912 (((
CPPClass*)pyclass)->fFlags & CPPScope::kIsSmart))
928 if (address && !isRef) {
931 address, 0,
nullptr)) {
934 if (clActual && clActual != underlying &&
938 underlying = clActual;
945 pyclass = smart_type;
946 smart_type =
nullptr;
952 if (address && !(flags & CPPInstance::kIsValue) &&
955 MemoryRegulator::RetrievePyObject(r_address, pyclass);
965 if ((
bool)smart_type == o_pyobj->
IsSmart() &&
968 (!(flags & CPPInstance::kIsPtrPtr) ||
969 (o_pyobj->
fFlags & CPPInstance::kIsReference))) {
973 Py_DECREF(oldPyObject);
981 ->tp_new((PyTypeObject*)pyclass, args,
nullptr);
987 flags & (CPPInstance::kIsReference | CPPInstance::kIsPtrPtr |
988 CPPInstance::kIsValue | CPPInstance::kIsOwner |
989 CPPInstance::kIsActual);
998 if (address && !isRef && !noReg)
999 MemoryRegulator::RegisterPyObject(
1005 if (((
CPPClass*)pyclass)->fFlags & CPPScope::kIsException) {
1020 const unsigned flags) {
1028 PyErr_SetString(PyExc_TypeError,
"attempt to bind C++ object w/o class");
1032 bool isRef = flags & CPPInstance::kIsReference;
1038 unsigned new_flags = flags;
1044 if (clActual != klass) {
1049 address = (
void*)((intptr_t)address.data +
offset);
1053 new_flags |= CPPInstance::kIsActual;
static PyClassMap_t gPyClasses
std::unordered_map< interop::TCppScope_t, PyObject * > PyClassMap_t
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void data
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 ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h offset
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 result
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
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t attr
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 ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t type
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 ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t property
void SetSmart(PyObject *smart_type)
void Set(void *address, EFlags flags=kDefault)
const std::string & GetName() const
void AdoptTemplate(PyCallable *pc)
void AdoptMethod(PyCallable *pc)
void MergeOverload(CPPOverload *mp)
static PyObject * cpyrt_GetWeakRef(PyObject *ref)
std::string compound(const std::string &name)
std::string MapOperatorName(const std::string &name, bool bTakesParames, bool *stubbed=nullptr)
bool CPPOverload_Check(T *object)
bool TemplateProxy_Check(T *object)
TemplateProxy * TemplateProxy_New(const std::string &cppname, const std::string &pyname, PyObject *pyclass)
PyObject * CppType_To_PyObject(interop::TCppType_t type, std::string name, interop::TCppScope_t parent_scope, PyObject *parent)
CPPScope * CPPScopeMeta_New(interop::TCppScope_t klass, PyObject *args)
static void AddPropertyToClass(PyObject *pyclass, interop::TCppScope_t scope, interop::TCppScope_t data)
static void sync_templates(PyObject *pyclass, const std::string &mtCppName, const std::string &mtName)
PyObject * CreateExcScopeProxy(PyObject *pyscope, PyObject *pyname, PyObject *parent)
static PyObject * BuildCppClassBases(interop::TCppScope_t klass)
PyTypeObject CPPInstance_Type
PyObject * GetScopeProxy(interop::TCppScope_t)
PyObject * BindCppObject(interop::TCppObject_t object, interop::TCppScope_t klass, const unsigned flags=0)
PyObject * BindCppObjectArray(interop::TCppObject_t address, interop::TCppScope_t klass, cdims_t dims)
static void AddScopeToParent(PyObject *parent, const std::string &name, PyObject *newscope)
std::unordered_set< interop::TCppScope_t > gPinnedTypes
PyObject * TupleOfInstances_New(interop::TCppObject_t address, interop::TCppScope_t klass, cdims_t dims)
PyObject * CreateScopeProxy(PyObject *, PyObject *args)
static int BuildScopeProxyDict(interop::TCppScope_t scope, PyObject *pyclass, const unsigned int flags)
PyTypeObject CPPExcInstance_Type
PyObject * BindCppObjectNoCast(interop::TCppObject_t object, interop::TCppScope_t klass, const unsigned flags=0)
static PyObject * CreateNewCppProxyClass(interop::TCppScope_t klass, PyObject *pybases)
bool CPPScope_Check(T *object)
CPPOverload * CPPOverload_New(const std::string &name, std::vector< PyCallable * > &methods)
bool Pythonize(PyObject *pyclass, interop::TCppScope_t scope)
CPPDataMember * CPPDataMember_New(interop::TCppScope_t scope, interop::TCppScope_t var)
static void CollectUniqueBases(interop::TCppScope_t klass, std::deque< interop::TCppScope_t > &uqb)
static PyObject * GetAttrDirect(PyObject *pyclass, PyObject *pyname)
void GetDatamembers(TCppScope_t scope, std::vector< TCppScope_t > &datamembers)
Cpp::ObjectRef TCppObject_t
TCppType_t GetTypeFromScope(TCppScope_t klass)
std::string GetTypeAsString(TCppType_t type)
TCppType_t GetDatamemberType(TCppScope_t data)
bool IsBuiltin(const std::string &type_name)
std::string GetName(TCppScope_t)
bool IsTemplateInstantiation(TCppScope_t scope)
bool IsConstructor(TCppMethod_t method)
TCppScope_t GetActualClass(TCppScope_t klass, TCppObject_t obj)
void GetTemplatedMethods(TCppScope_t scope, std::vector< TCppMethod_t > &methods)
bool IsAbstract(TCppScope_t scope)
TCppScope_t GetParentScope(TCppScope_t scope)
std::string GetMethodReturnTypeAsString(TCppMethod_t)
TCppIndex_t GetMethodNumArgs(TCppMethod_t)
bool IsStaticDatamember(TCppScope_t var)
bool IsClass(TCppScope_t scope)
TCppIndex_t GetNumBases(TCppScope_t klass)
bool IsSubclass(TCppScope_t derived, TCppScope_t base)
Cpp::FuncRef TCppMethod_t
bool IsPublicData(TCppScope_t var)
TCppScope_t GetBaseScope(TCppScope_t klass, TCppIndex_t ibase)
bool IsTypedefed(TCppScope_t scope)
bool IsEnumScope(TCppScope_t scope)
void GetClassMethods(TCppScope_t scope, std::vector< TCppMethod_t > &methods)
bool IsPointerType(TCppType_t type)
TCppType_t ResolveType(TCppType_t cppitem_name)
TCppScope_t GetUnderlyingScope(TCppScope_t scope)
TCppScope_t GetGlobalScope()
std::string GetFullName(TCppScope_t)
bool IsTemplate(TCppScope_t scope)
void * CallR(TCppMethod_t method, TCppObject_t self, size_t nargs, void *args)
bool IsNamespace(TCppScope_t scope)
bool IsTemplatedMethod(TCppMethod_t method)
TCppScope_t GetScope(const std::string &scope_name, TCppScope_t parent_scope=TCppScope_t{})
bool IsEnumConstant(TCppScope_t scope)
std::string GetFinalName(TCppScope_t type)
ptrdiff_t GetBaseOffset(TCppScope_t derived, TCppScope_t base, TCppObject_t address, int direction, bool rerror=false)
bool IsStaticMethod(TCppMethod_t method)
bool IsPublicMethod(TCppMethod_t method)
TCppType_t GetType(const std::string &name, bool enable_slow_lookup=false)
std::string GetScopedFinalName(TCppScope_t type)
std::string GetDatamemberTypeAsString(TCppScope_t var)
bool IsEnumType(TCppType_t type)
bool IsComplete(TCppScope_t type)
PyObject_HEAD PyObject * dict