Logo ROOT  
Reference Guide
CPPScope.cxx
Go to the documentation of this file.
1// Bindings
2#include "CPyCppyy.h"
3#include "CPPScope.h"
4#include "CPPDataMember.h"
5#include "CPPFunction.h"
6#include "CPPOverload.h"
7#include "CustomPyTypes.h"
8#include "Dispatcher.h"
9#include "ProxyWrappers.h"
10#include "PyStrings.h"
11#include "TemplateProxy.h"
12#include "TypeManip.h"
13#include "Utility.h"
14
15// Standard
16#include <string.h>
17#include <algorithm> // for for_each
18#include <set>
19#include <string>
20#include <vector>
21
22
23namespace CPyCppyy {
24
25extern PyTypeObject CPPInstance_Type;
26
27//- helpers ------------------------------------------------------------------
28static inline PyObject* add_template(PyObject* pyclass,
29 const std::string& name, std::vector<PyCallable*>* overloads = nullptr)
30{
31// If templated, the user-facing function must be the template proxy, but the
32// specific lookup must be the current overload, if already found.
33 TemplateProxy* pytmpl = nullptr;
34
35 const std::string& ncl = TypeManip::clean_type(name);
36 if (ncl != name) {
37 PyObject* pyncl = CPyCppyy_PyText_InternFromString(ncl.c_str());
38 pytmpl = (TemplateProxy*)PyType_Type.tp_getattro((PyObject*)Py_TYPE(pyclass), pyncl);
39 if (!pytmpl) {
40 PyErr_Clear();
41 pytmpl = TemplateProxy_New(ncl, ncl, pyclass);
42 // cache the template on its clean name
43 PyType_Type.tp_setattro((PyObject*)Py_TYPE(pyclass), pyncl, (PyObject*)pytmpl);
44 }
45 Py_DECREF(pyncl);
46 }
47
48 if (pytmpl) {
49 if (!TemplateProxy_CheckExact((PyObject*)pytmpl)) {
50 Py_DECREF(pytmpl);
51 return nullptr;
52 }
53 } else
54 pytmpl = TemplateProxy_New(ncl, ncl, pyclass);
55
56 if (overloads) {
57 // adopt the new overloads
58 if (ncl != name)
59 for (auto clb : *overloads) pytmpl->AdoptTemplate(clb);
60 else
61 for (auto clb : *overloads) pytmpl->AdoptMethod(clb);
62 }
63
64 if (ncl == name)
65 return (PyObject*)pytmpl;
66
67 Py_DECREF(pytmpl);
68 return nullptr; // so that caller caches the method on full name
69}
70
71//----------------------------------------------------------------------------
72static int enum_setattro(PyObject* /* pyclass */, PyObject* /* pyname */, PyObject* /* pyval */)
73{
74// Helper to make enums read-only.
75 PyErr_SetString(PyExc_TypeError, "enum values are read-only");
76 return -1;
77}
78
79
80//= CPyCppyy type proxy construction/destruction =============================
81static PyObject* meta_alloc(PyTypeObject* meta, Py_ssize_t nitems)
82{
83// pure memory allocation; object initialization is in pt_new
84 return PyType_Type.tp_alloc(meta, nitems);
85}
86
87//----------------------------------------------------------------------------
88static void meta_dealloc(CPPScope* scope)
89{
90 if (scope->fFlags & CPPScope::kIsNamespace) {
91 if (scope->fImp.fUsing) {
92 for (auto pyobj : *scope->fImp.fUsing) Py_DECREF(pyobj);
93 delete scope->fImp.fUsing; scope->fImp.fUsing = nullptr;
94 }
95 } else if (!(scope->fFlags & CPPScope::kIsPython)) {
96 delete scope->fImp.fCppObjects; scope->fImp.fCppObjects = nullptr;
97 }
98 delete scope->fOperators;
99 free(scope->fModuleName);
100 return PyType_Type.tp_dealloc((PyObject*)scope);
101}
102
103//-----------------------------------------------------------------------------
104static PyObject* meta_getcppname(CPPScope* scope, void*)
105{
106 if ((void*)scope == (void*)&CPPInstance_Type)
107 return CPyCppyy_PyText_FromString("CPPInstance_Type");
109}
110
111//-----------------------------------------------------------------------------
112static PyObject* meta_getmodule(CPPScope* scope, void*)
113{
114 if ((void*)scope == (void*)&CPPInstance_Type)
115 return CPyCppyy_PyText_FromString("cppyy.gbl");
116
117 if (scope->fModuleName)
119
120// get C++ representation of outer scope
121 std::string modname =
123 if (modname.empty())
124 return CPyCppyy_PyText_FromString(const_cast<char*>("cppyy.gbl"));
125
126// now peel scopes one by one, pulling in the python naming (which will
127// simply recurse if not overridden in python)
128 PyObject* pymodule = nullptr;
130 if (pyscope) {
131 // get the module of our module
132 pymodule = PyObject_GetAttr(pyscope, PyStrings::gModule);
133 if (pymodule) {
134 // append name of our module
135 PyObject* pymodname = PyObject_GetAttr(pyscope, PyStrings::gName);
136 if (pymodname) {
138 CPyCppyy_PyText_AppendAndDel(&pymodule, pymodname);
139 }
140 }
141 Py_DECREF(pyscope);
142 }
143
144 if (pymodule)
145 return pymodule;
146 PyErr_Clear();
147
148// lookup through python failed, so simply cook up a '::' -> '.' replacement
150 return CPyCppyy_PyText_FromString(("cppyy.gbl."+modname).c_str());
151}
152
153//-----------------------------------------------------------------------------
154static int meta_setmodule(CPPScope* scope, PyObject* value, void*)
155{
156 if ((void*)scope == (void*)&CPPInstance_Type) {
157 PyErr_SetString(PyExc_AttributeError,
158 "attribute \'__module__\' of 'cppyy.CPPScope\' objects is not writable");
159 return -1;
160 }
161
162 const char* newname = CPyCppyy_PyText_AsStringChecked(value);
163 if (!value)
164 return -1;
165
166 free(scope->fModuleName);
168 scope->fModuleName = (char*)malloc(sz+1);
169 memcpy(scope->fModuleName, newname, sz+1);
170
171 return 0;
172}
173
174//----------------------------------------------------------------------------
176{
177// Specialized b/c type_repr expects __module__ to live in the dictionary,
178// whereas it is a property (to save memory).
179 if ((void*)scope == (void*)&CPPInstance_Type)
181 const_cast<char*>("<class cppyy.CPPInstance at %p>"), scope);
182
184 // either meta type or Python-side derived class: use default type printing
185 return PyType_Type.tp_repr((PyObject*)scope);
186 }
187
188// printing of C++ classes
189 PyObject* modname = meta_getmodule(scope, nullptr);
190 std::string clName = Cppyy::GetFinalName(scope->fCppType);
191 const char* kind = (scope->fFlags & CPPScope::kIsNamespace) ? "namespace" : "class";
192
193 PyObject* repr = CPyCppyy_PyText_FromFormat("<%s %s.%s at %p>",
194 kind, CPyCppyy_PyText_AsString(modname), clName.c_str(), scope);
195
196 Py_DECREF(modname);
197 return repr;
198}
199
200
201//= CPyCppyy type metaclass behavior =========================================
202static PyObject* pt_new(PyTypeObject* subtype, PyObject* args, PyObject* kwds)
203{
204// Called when CPPScope acts as a metaclass; since type_new always resets
205// tp_alloc, and since it does not call tp_init on types, the metaclass is
206// being fixed up here, and the class is initialized here as well.
207
208// fixup of metaclass (left permanent, and in principle only called once b/c
209// cppyy caches python classes)
210 subtype->tp_alloc = (allocfunc)meta_alloc;
211 subtype->tp_dealloc = (destructor)meta_dealloc;
212
213// creation of the python-side class; extend the size if this is a smart ptr
214 Cppyy::TCppType_t raw{0}; Cppyy::TCppMethod_t deref{0};
215 if (CPPScope_CheckExact(subtype)) {
216 if (Cppyy::GetSmartPtrInfo(Cppyy::GetScopedFinalName(((CPPScope*)subtype)->fCppType), &raw, &deref))
217 subtype->tp_basicsize = sizeof(CPPSmartClass);
218 }
219 CPPScope* result = (CPPScope*)PyType_Type.tp_new(subtype, args, kwds);
220 if (!result)
221 return nullptr;
222
223 result->fFlags = CPPScope::kNone;
224 result->fOperators = nullptr;
225 result->fModuleName = nullptr;
226
227 if (raw && deref) {
228 result->fFlags |= CPPScope::kIsSmart;
229 ((CPPSmartClass*)result)->fUnderlyingType = raw;
230 ((CPPSmartClass*)result)->fDereferencer = deref;
231 }
232
233// initialization of class (based on metatype)
234 const char* mp = strstr(subtype->tp_name, "_meta");
235 if (!mp || !CPPScope_CheckExact(subtype)) {
236 // there has been a user meta class override in a derived class, so do
237 // the consistent thing, thus allowing user control over naming
238 result->fCppType = Cppyy::GetScope(
239 CPyCppyy_PyText_AsString(PyTuple_GET_ITEM(args, 0)));
240 } else {
241 // coming here from cppyy or from sub-classing in python; take the
242 // C++ type from the meta class to make sure that the latter category
243 // has fCppType properly set (it inherits the meta class, but has an
244 // otherwise unknown (or wrong) C++ type)
245 result->fCppType = ((CPPScope*)subtype)->fCppType;
246
247 // the following is not robust, but by design, C++ classes get their
248 // dictionaries filled after creation (chicken & egg problem as they
249 // can return themselves in methods), whereas a derived Python class
250 // with method overrides will have a non-empty dictionary (even if it
251 // has no methods, it will at least have a module name)
252 if (3 <= PyTuple_GET_SIZE(args)) {
253 PyObject* dct = PyTuple_GET_ITEM(args, 2);
254 Py_ssize_t sz = PyDict_Size(dct);
255 if (0 < sz && !Cppyy::IsNamespace(result->fCppType)) {
256 result->fFlags |= CPPScope::kIsPython;
257 if (!InsertDispatcher(result, dct)) {
258 if (!PyErr_Occurred())
259 PyErr_Warn(PyExc_RuntimeWarning, (char*)"no python-side overrides supported");
260 } else {
261 // the direct base can be useful for some templates, such as shared_ptrs,
262 // so make it accessible (the __cpp_cross__ data member also signals that
263 // this is a cross-inheritance class)
265 if (PyObject_SetAttrString((PyObject*)result, "__cpp_cross__", bname) == -1)
266 PyErr_Clear();
267 Py_DECREF(bname);
268 }
269 } else if (sz == (Py_ssize_t)-1)
270 PyErr_Clear();
271 }
272 }
273
274// maps for using namespaces and tracking objects
275 if (!Cppyy::IsNamespace(result->fCppType)) {
276 static Cppyy::TCppType_t exc_type = (Cppyy::TCppType_t)Cppyy::GetScope("std::exception");
277 if (Cppyy::IsSubtype(result->fCppType, exc_type))
279 if (!(result->fFlags & CPPScope::kIsPython))
280 result->fImp.fCppObjects = new CppToPyMap_t;
281 else {
282 // special case: the C++ objects should be stored with the associated C++, not Python, type
283 CPPClass* kls = (CPPClass*)GetScopeProxy(result->fCppType);
284 if (kls) {
285 result->fImp.fCppObjects = kls->fImp.fCppObjects;
286 Py_DECREF(kls);
287 } else
288 result->fImp.fCppObjects = nullptr;
289 }
290 } else {
291 result->fImp.fUsing = nullptr;
292 result->fFlags |= CPPScope::kIsNamespace;
293 }
294
295 if (PyErr_Occurred()) {
296 Py_DECREF((PyObject*)result);
297 return nullptr;
298 }
299 return (PyObject*)result;
300}
301
302
303//----------------------------------------------------------------------------
305{
306// normal type-based lookup
307 PyObject* attr = PyType_Type.tp_getattro(pyclass, pyname);
308 if (attr || pyclass == (PyObject*)&CPPInstance_Type)
309 return attr;
310
312 return nullptr;
313
314// filter for python specials
315 std::string name = CPyCppyy_PyText_AsString(pyname);
316 if (name.size() >= 2 && name.compare(0, 2, "__") == 0 &&
317 name.compare(name.size()-2, name.size(), "__") == 0)
318 return nullptr;
319
320// more elaborate search in case of failure (eg. for inner classes on demand)
321 std::vector<Utility::PyError_t> errors;
322 Utility::FetchError(errors);
323 attr = CreateScopeProxy(name, pyclass);
324 if (CPPScope_Check(attr) && (((CPPScope*)attr)->fFlags & CPPScope::kIsException)) {
325 // Instead of the CPPScope, return a fresh exception class derived from CPPExcInstance.
326 return CreateExcScopeProxy(attr, pyname, pyclass);
327 }
328
329 CPPScope* klass = ((CPPScope*)pyclass);
330 if (!attr) {
331 Utility::FetchError(errors);
332 Cppyy::TCppScope_t scope = klass->fCppType;
333
334 // namespaces may have seen updates in their list of global functions, which
335 // are available as "methods" even though they're not really that
336 if (klass->fFlags & CPPScope::kIsNamespace) {
337 // tickle lazy lookup of functions
338 const std::vector<Cppyy::TCppIndex_t> methods =
340 if (!methods.empty()) {
341 // function exists, now collect overloads
342 std::vector<PyCallable*> overloads;
343 for (auto idx : methods) {
344 overloads.push_back(
345 new CPPFunction(scope, Cppyy::GetMethod(scope, idx)));
346 }
347
348 // Note: can't re-use Utility::AddClass here, as there's the risk of
349 // a recursive call. Simply add method directly, as we're guaranteed
350 // that it doesn't exist yet.
352 attr = add_template(pyclass, name, &overloads);
353
354 if (!attr) // add_template can fail if the method can not be added
355 attr = (PyObject*)CPPOverload_New(name, overloads);
356 }
357
358 // tickle lazy lookup of data members
359 if (!attr) {
361 if (dmi != (Cppyy::TCppIndex_t)-1) attr = (PyObject*)CPPDataMember_New(scope, dmi);
362 }
363 }
364
365 // this may be a typedef that resolves to a sugared type
366 if (!attr) {
367 const std::string& lookup = Cppyy::GetScopedFinalName(klass->fCppType) + "::" + name;
368 const std::string& resolved = Cppyy::ResolveName(lookup);
369 if (resolved != lookup) {
370 const std::string& cpd = Utility::Compound(resolved);
371 if (cpd == "*") {
372 const std::string& clean = TypeManip::clean_type(resolved, false, true);
374 if (tcl) {
377 tpc->fType = tcl;
378 attr = (PyObject*)tpc;
379 }
380 }
381 }
382 }
383
384 // function templates that have not been instantiated
385 if (!attr) {
387 attr = add_template(pyclass, name);
388 else {
389 // for completeness in error reporting
390 PyErr_Format(PyExc_TypeError, "\'%s\' is not a known C++ template", name.c_str());
391 Utility::FetchError(errors);
392 }
393 }
394
395 // enums types requested as type (rather than the constants)
396 if (!attr) {
397 // TODO: IsEnum should deal with the scope, using klass->GetListOfEnums()->FindObject()
399 // enum types (incl. named and class enums)
400 Cppyy::TCppEnum_t etype = Cppyy::GetEnum(scope, name);
401 if (etype) {
402 // create new enum type with labeled values in place, with a meta-class
403 // to make sure the enum values are read-only
404 PyObject* pymetabases = PyTuple_New(1);
405 PyObject* btype = (PyObject*)Py_TYPE(&PyInt_Type);
406 Py_INCREF(btype);
407 PyTuple_SET_ITEM(pymetabases, 0, btype);
408
409 PyObject* args = Py_BuildValue((char*)"sO{}", (name+"_meta").c_str(), pymetabases);
410 Py_DECREF(pymetabases);
411 PyObject* pymeta = PyType_Type.tp_new(Py_TYPE(&PyInt_Type), args, nullptr);
412 ((PyTypeObject*)pymeta)->tp_setattro = enum_setattro;
413 Py_DECREF(args);
414
415 // prepare the base class
416 PyObject* pybases = PyTuple_New(1);
417 Py_INCREF(&PyInt_Type);
418 PyTuple_SET_ITEM(pybases, 0, (PyObject*)&PyInt_Type);
419
420 // collect the enum values
422 PyObject* dct = PyDict_New();
423 for (Cppyy::TCppIndex_t idata = 0; idata < ndata; ++idata) {
424 PyObject* val = PyLong_FromLongLong(Cppyy::GetEnumDataValue(etype, idata));
425 PyDict_SetItemString(dct, Cppyy::GetEnumDataName(etype, idata).c_str(), val);
426 Py_DECREF(val);
427 }
428
429 // add the __cpp_name__ for templates
430 PyObject* cppname = nullptr;
431 if (scope == Cppyy::gGlobalScope) {
432 Py_INCREF(pyname);
433 cppname = pyname;
434 } else
435 cppname = CPyCppyy_PyText_FromString((Cppyy::GetScopedFinalName(scope)+"::"+name).c_str());
436 PyDict_SetItem(dct, PyStrings::gCppName, cppname);
437 Py_DECREF(cppname);
438
439 // create the actual enum class
440 args = Py_BuildValue((char*)"sOO", name.c_str(), pybases, dct);
441 Py_DECREF(pybases);
442 Py_DECREF(dct);
443 attr = ((PyTypeObject*)pymeta)->tp_new((PyTypeObject*)pymeta, args, nullptr);
444
445 // final cleanup
446 Py_DECREF(args);
447 Py_DECREF(pymeta);
448
449 } else {
450 // presumably not a class enum; simply pretend int
451 Py_INCREF(&PyInt_Type);
452 attr = (PyObject*)&PyInt_Type;
453 }
454 } else {
455 // for completeness in error reporting
456 PyErr_Format(PyExc_TypeError, "\'%s\' is not a known C++ enum", name.c_str());
457 Utility::FetchError(errors);
458 }
459 }
460
461 if (attr) {
462 // cache the result
463 if (CPPDataMember_Check(attr)) {
464 PyType_Type.tp_setattro((PyObject*)Py_TYPE(pyclass), pyname, attr);
465 Py_DECREF(attr);
466 attr = PyType_Type.tp_getattro(pyclass, pyname);
467 } else
468 PyType_Type.tp_setattro(pyclass, pyname, attr);
469
470 } else {
471 Utility::FetchError(errors);
472 }
473 }
474
475 if (!attr && (klass->fFlags & CPPScope::kIsNamespace)) {
476 // refresh using list as necessary
477 const std::vector<Cppyy::TCppScope_t>& uv = Cppyy::GetUsingNamespaces(klass->fCppType);
478 if (!klass->fImp.fUsing || uv.size() != klass->fImp.fUsing->size()) {
479 if (klass->fImp.fUsing) {
480 for (auto pyref : *klass->fImp.fUsing) Py_DECREF(pyref);
481 klass->fImp.fUsing->clear();
482 } else
483 klass->fImp.fUsing = new std::vector<PyObject*>;
484
485 // reload and reset weak refs
486 for (auto uid : uv) {
487 std::string uname = Cppyy::GetScopedFinalName(uid);
488 PyObject* pyuscope = CreateScopeProxy(uname);
489 if (pyuscope) {
490 klass->fImp.fUsing->push_back(PyWeakref_NewRef(pyuscope, nullptr));
491 // the namespace may not otherwise be held, so tie the lifetimes
492 PyObject* llname = CPyCppyy_PyText_FromString(("__lifeline_"+uname).c_str());
493 PyType_Type.tp_setattro(pyclass, llname, pyuscope);
494 Py_DECREF(llname);
495 Py_DECREF(pyuscope);
496 }
497 }
498 }
499
500 // try all outstanding using namespaces in turn to find the attribute (will cache
501 // locally later; TODO: doing so may cause pathological cases)
502 for (auto pyref : *klass->fImp.fUsing) {
503 PyObject* pyuscope = PyWeakref_GetObject(pyref);
504 if (pyuscope) {
505 attr = PyObject_GetAttr(pyuscope, pyname);
506 if (attr) break;
507 PyErr_Clear();
508 }
509 }
510 }
511
512 if (attr) {
513 std::for_each(errors.begin(), errors.end(), Utility::PyError_t::Clear);
514 PyErr_Clear();
515 } else {
516 // not found: prepare a full error report
517 PyObject* topmsg = nullptr;
518 PyObject* sklass = PyObject_Str(pyclass);
519 if (sklass) {
520 topmsg = CPyCppyy_PyText_FromFormat("%s has no attribute \'%s\'. Full details:",
522 Py_DECREF(sklass);
523 } else {
524 topmsg = CPyCppyy_PyText_FromFormat("no such attribute \'%s\'. Full details:",
526 }
527 SetDetailedException(errors, topmsg /* steals */, PyExc_AttributeError /* default error */);
528 }
529
530 return attr;
531}
532
533//----------------------------------------------------------------------------
534static int meta_setattro(PyObject* pyclass, PyObject* pyname, PyObject* pyval)
535{
536// Global data and static data in namespaces is found lazily, thus if the first
537// use is setting of the global data by the user, it will not be reflected on
538// the C++ side, b/c there is no descriptor yet. This triggers the creation for
539// for such data as necessary. The many checks to narrow down the specific case
540// are needed to prevent unnecessary lookups and recursion.
541 if (((CPPScope*)pyclass)->fFlags & CPPScope::kIsNamespace) {
542 // skip if the given pyval is a descriptor already, or an unassignable class
544 std::string name = CPyCppyy_PyText_AsString(pyname);
545 Cppyy::TCppIndex_t dmi = Cppyy::GetDatamemberIndex(((CPPScope*)pyclass)->fCppType, name);
546 if (dmi != (Cppyy::TCppIndex_t)-1)
547 meta_getattro(pyclass, pyname); // triggers creation
548 }
549 }
550
551 return PyType_Type.tp_setattro(pyclass, pyname, pyval);
552}
553
554
555//----------------------------------------------------------------------------
556// p2.7 does not have a __dir__ in object, and object.__dir__ in p3 does not
557// quite what I'd expected of it, so the following pulls in the internal code
558#include "PyObjectDir27.inc"
559
561{
562// Collect a list of everything (currently) available in the namespace.
563// The backend can filter by returning empty strings. Special care is
564// taken for functions, which need not be unique (overloading).
565 using namespace Cppyy;
566
567 if ((void*)klass == (void*)&CPPInstance_Type)
568 return PyList_New(0);
569
570 if (!CPyCppyy::CPPScope_Check((PyObject*)klass)) {
571 PyErr_SetString(PyExc_TypeError, "C++ proxy scope expected");
572 return nullptr;
573 }
574
575 PyObject* dirlist = _generic_dir((PyObject*)klass);
576 if (!(klass->fFlags & CPPScope::kIsNamespace))
577 return dirlist;
578
579 std::set<std::string> cppnames;
580 Cppyy::GetAllCppNames(klass->fCppType, cppnames);
581
582// get rid of duplicates
583 for (Py_ssize_t i = 0; i < PyList_GET_SIZE(dirlist); ++i)
584 cppnames.insert(CPyCppyy_PyText_AsString(PyList_GET_ITEM(dirlist, i)));
585
586 Py_DECREF(dirlist);
587 dirlist = PyList_New(cppnames.size());
588
589// copy total onto python list
590 Py_ssize_t i = 0;
591 for (const auto& name : cppnames) {
592 PyList_SET_ITEM(dirlist, i++, CPyCppyy_PyText_FromString(name.c_str()));
593 }
594 return dirlist;
595}
596
597//-----------------------------------------------------------------------------
598static PyMethodDef meta_methods[] = {
599 {(char*)"__dir__", (PyCFunction)meta_dir, METH_NOARGS, nullptr},
600 {(char*)nullptr, nullptr, 0, nullptr}
601};
602
603
604//-----------------------------------------------------------------------------
605static PyGetSetDef meta_getset[] = {
606 {(char*)"__cpp_name__", (getter)meta_getcppname, nullptr, nullptr, nullptr},
607 {(char*)"__module__", (getter)meta_getmodule, (setter)meta_setmodule, nullptr, nullptr},
608 {(char*)nullptr, nullptr, nullptr, nullptr, nullptr}
609};
610
611
612//= CPyCppyy object proxy type type ==========================================
613PyTypeObject CPPScope_Type = {
614 PyVarObject_HEAD_INIT(&PyType_Type, 0)
615 (char*)"cppyy.CPPScope", // tp_name
616 sizeof(CPyCppyy::CPPScope), // tp_basicsize
617 0, // tp_itemsize
618 0, // tp_dealloc
619 0, // tp_print
620 0, // tp_getattr
621 0, // tp_setattr
622 0, // tp_compare
623 (reprfunc)meta_repr, // tp_repr
624 0, // tp_as_number
625 0, // tp_as_sequence
626 0, // tp_as_mapping
627 0, // tp_hash
628 0, // tp_call
629 0, // tp_str
630 (getattrofunc)meta_getattro, // tp_getattro
631 (setattrofunc)meta_setattro, // tp_setattro
632 0, // tp_as_buffer
633 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
634#if PY_VERSION_HEX >= 0x03040000
635 | Py_TPFLAGS_TYPE_SUBCLASS
636#endif
637 , // tp_flags
638 (char*)"CPyCppyy metatype (internal)", // tp_doc
639 0, // tp_traverse
640 0, // tp_clear
641 0, // tp_richcompare
642 0, // tp_weaklistoffset
643 0, // tp_iter
644 0, // tp_iternext
645 meta_methods, // tp_methods
646 0, // tp_members
647 meta_getset, // tp_getset
648 &PyType_Type, // tp_base
649 0, // tp_dict
650 0, // tp_descr_get
651 0, // tp_descr_set
652 0, // tp_dictoffset
653 0, // tp_init
654 0, // tp_alloc
655 (newfunc)pt_new, // tp_new
656 0, // tp_free
657 0, // tp_is_gc
658 0, // tp_bases
659 0, // tp_mro
660 0, // tp_cache
661 0, // tp_subclasses
662 0 // tp_weaklist
663#if PY_VERSION_HEX >= 0x02030000
664 , 0 // tp_del
665#endif
666#if PY_VERSION_HEX >= 0x02060000
667 , 0 // tp_version_tag
668#endif
669#if PY_VERSION_HEX >= 0x03040000
670 , 0 // tp_finalize
671#endif
672};
673
674} // namespace CPyCppyy
#define Py_TYPE(ob)
Definition: CPyCppyy.h:209
#define CPyCppyy_PyText_InternFromString
Definition: CPyCppyy.h:103
int Py_ssize_t
Definition: CPyCppyy.h:228
#define CPyCppyy_PyText_AsString
Definition: CPyCppyy.h:97
#define CPyCppyy_PyText_GET_SIZE
Definition: CPyCppyy.h:99
#define CPyCppyy_PyText_AppendAndDel
Definition: CPyCppyy.h:105
#define CPyCppyy_PyText_FromFormat
Definition: CPyCppyy.h:101
#define CPyCppyy_PyText_AsStringChecked
Definition: CPyCppyy.h:98
#define CPyCppyy_PyText_CheckExact
Definition: CPyCppyy.h:96
#define CPyCppyy_PyText_FromString
Definition: CPyCppyy.h:102
#define PyVarObject_HEAD_INIT(type, size)
Definition: CPyCppyy.h:207
unsigned int fFlags
_object PyObject
Definition: PyMethodBase.h:41
@ kIsNamespace
Definition: TDictionary.h:95
char name[80]
Definition: TGX11.cxx:109
#define pyname
Definition: TMCParticle.cxx:19
#define free
Definition: civetweb.c:1539
#define malloc
Definition: civetweb.c:1536
Utility::PyOperators * fOperators
Definition: CPPScope.h:56
union CPyCppyy::CPPScope::@204 fImp
char * fModuleName
Definition: CPPScope.h:57
Cppyy::TCppType_t fCppType
Definition: CPPScope.h:50
std::vector< PyObject * > * fUsing
Definition: CPPScope.h:54
CppToPyMap_t * fCppObjects
Definition: CPPScope.h:53
void AdoptTemplate(PyCallable *pc)
void AdoptMethod(PyCallable *pc)
PyObject * gName
Definition: PyStrings.cxx:26
PyObject * gCppName
Definition: PyStrings.cxx:10
PyObject * gModule
Definition: PyStrings.cxx:24
void cppscope_to_pyscope(std::string &cppscope)
Definition: TypeManip.cxx:148
std::string clean_type(const std::string &cppname, bool template_strip=true, bool const_strip=true)
Definition: TypeManip.cxx:98
std::string extract_namespace(const std::string &name)
Definition: TypeManip.cxx:159
size_t FetchError(std::vector< PyError_t > &)
Definition: Utility.cxx:879
void SetDetailedException(std::vector< PyError_t > &errors, PyObject *topmsg, PyObject *defexc)
Definition: Utility.cxx:891
const std::string Compound(const std::string &name)
Definition: Utility.cxx:782
CPPOverload * CPPOverload_New(const std::string &name, std::vector< PyCallable * > &methods)
Definition: CPPOverload.h:91
PyTypeObject CPPInstance_Type
static PyObject * add_template(PyObject *pyclass, const std::string &name, std::vector< PyCallable * > *overloads=nullptr)
Definition: CPPScope.cxx:28
std::map< Cppyy::TCppObject_t, PyObject * > CppToPyMap_t
Type object to hold class reference (this is only semantically a presentation of CPPScope instances,...
Definition: CPPScope.h:34
PyObject * GetScopeProxy(Cppyy::TCppScope_t)
static int meta_setmodule(CPPScope *scope, PyObject *value, void *)
Definition: CPPScope.cxx:154
static PyObject * meta_dir(CPPScope *klass)
Definition: CPPScope.cxx:560
static PyObject * meta_alloc(PyTypeObject *meta, Py_ssize_t nitems)
Definition: CPPScope.cxx:81
PyTypeObject TypedefPointerToClass_Type
bool InsertDispatcher(CPPScope *klass, PyObject *dct)
Definition: Dispatcher.cxx:55
static int enum_setattro(PyObject *, PyObject *, PyObject *)
Definition: CPPScope.cxx:72
static PyObject * pt_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)
Definition: CPPScope.cxx:202
bool CPPScope_Check(T *object)
Definition: CPPScope.h:76
bool TemplateProxy_CheckExact(T *object)
Definition: TemplateProxy.h:85
static int meta_setattro(PyObject *pyclass, PyObject *pyname, PyObject *pyval)
Definition: CPPScope.cxx:534
static PyObject * meta_getmodule(CPPScope *scope, void *)
Definition: CPPScope.cxx:112
CPPDataMember * CPPDataMember_New(Cppyy::TCppScope_t scope, Cppyy::TCppIndex_t idata)
Definition: CPPDataMember.h:52
static PyGetSetDef meta_getset[]
Definition: CPPScope.cxx:605
static void meta_dealloc(CPPScope *scope)
Definition: CPPScope.cxx:88
PyObject * CreateExcScopeProxy(PyObject *pyscope, PyObject *pyname, PyObject *parent)
PyObject * CreateScopeProxy(Cppyy::TCppScope_t)
bool CPPScope_CheckExact(T *object)
Definition: CPPScope.h:82
static PyMethodDef meta_methods[]
Definition: CPPScope.cxx:598
bool CPPDataMember_Check(T *object)
Definition: CPPDataMember.h:40
static PyObject * meta_getattro(PyObject *pyclass, PyObject *pyname)
Definition: CPPScope.cxx:304
static PyObject * meta_getcppname(CPPScope *scope, void *)
Definition: CPPScope.cxx:104
PyTypeObject CPPScope_Type
Definition: CPPScope.cxx:613
static PyObject * meta_repr(CPPScope *scope)
Definition: CPPScope.cxx:175
TemplateProxy * TemplateProxy_New(const std::string &cppname, const std::string &pyname, PyObject *pyclass)
Definition: TemplateProxy.h:91
size_t TCppIndex_t
Definition: cpp_cppyy.h:24
RPY_EXPORTED std::vector< TCppIndex_t > GetMethodIndicesFromName(TCppScope_t scope, const std::string &name)
RPY_EXPORTED TCppIndex_t GetNumEnumData(TCppEnum_t)
intptr_t TCppMethod_t
Definition: cpp_cppyy.h:22
RPY_EXPORTED bool GetSmartPtrInfo(const std::string &, TCppType_t *raw, TCppMethod_t *deref)
RPY_EXPORTED std::vector< TCppScope_t > GetUsingNamespaces(TCppScope_t)
RPY_EXPORTED std::string GetEnumDataName(TCppEnum_t, TCppIndex_t idata)
TCppScope_t TCppType_t
Definition: cpp_cppyy.h:19
RPY_EXPORTED bool IsEnum(const std::string &type_name)
void * TCppEnum_t
Definition: cpp_cppyy.h:20
RPY_EXPORTED TCppIndex_t GetDatamemberIndex(TCppScope_t scope, const std::string &name)
RPY_EXPORTED TCppMethod_t GetMethod(TCppScope_t scope, TCppIndex_t imeth)
RPY_EXPORTED std::string GetFinalName(TCppType_t type)
RPY_EXPORTED long long GetEnumDataValue(TCppEnum_t, TCppIndex_t idata)
RPY_EXPORTED bool IsSubtype(TCppType_t derived, TCppType_t base)
size_t TCppScope_t
Definition: cpp_cppyy.h:18
RPY_EXPORTED std::string ResolveName(const std::string &cppitem_name)
RPY_EXPORTED std::string GetBaseName(TCppType_t type, TCppIndex_t ibase)
RPY_EXPORTED std::string GetScopedFinalName(TCppType_t type)
RPY_EXPORTED bool IsNamespace(TCppScope_t scope)
RPY_EXPORTED void GetAllCppNames(TCppScope_t scope, std::set< std::string > &cppnames)
RPY_EXPORTED TCppScope_t GetScope(const std::string &scope_name)
RPY_EXPORTED bool ExistsMethodTemplate(TCppScope_t scope, const std::string &name)
RPY_EXPORTED TCppScope_t gGlobalScope
Definition: cpp_cppyy.h:51
RPY_EXPORTED TCppEnum_t GetEnum(TCppScope_t scope, const std::string &enum_name)
PyObject_HEAD Cppyy::TCppType_t fType
Definition: CustomPyTypes.h:43