Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
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 std::ostringstream errmsg;
258 if (!InsertDispatcher(result, PyTuple_GET_ITEM(args, 1), dct, errmsg)) {
259 PyErr_Format(PyExc_TypeError, "no python-side overrides supported (%s)", errmsg.str().c_str());
260 return nullptr;
261 } else {
262 // the direct base can be useful for some templates, such as shared_ptrs,
263 // so make it accessible (the __cpp_cross__ data member also signals that
264 // this is a cross-inheritance class)
266 if (PyObject_SetAttrString((PyObject*)result, "__cpp_cross__", bname) == -1)
267 PyErr_Clear();
268 Py_DECREF(bname);
269 }
270 } else if (sz == (Py_ssize_t)-1)
271 PyErr_Clear();
272 }
273 }
274
275// maps for using namespaces and tracking objects
276 if (!Cppyy::IsNamespace(result->fCppType)) {
277 static Cppyy::TCppType_t exc_type = (Cppyy::TCppType_t)Cppyy::GetScope("std::exception");
278 if (Cppyy::IsSubtype(result->fCppType, exc_type))
280 if (!(result->fFlags & CPPScope::kIsPython))
281 result->fImp.fCppObjects = new CppToPyMap_t;
282 else {
283 // special case: the C++ objects should be stored with the associated C++, not Python, type
284 CPPClass* kls = (CPPClass*)GetScopeProxy(result->fCppType);
285 if (kls) {
286 result->fImp.fCppObjects = kls->fImp.fCppObjects;
287 Py_DECREF(kls);
288 } else
289 result->fImp.fCppObjects = nullptr;
290 }
291 } else {
292 result->fImp.fUsing = nullptr;
294 }
295
296 if (PyErr_Occurred()) {
297 Py_DECREF((PyObject*)result);
298 return nullptr;
299 }
300 return (PyObject*)result;
301}
302
303
304//----------------------------------------------------------------------------
306{
307// normal type-based lookup
308 PyObject* attr = PyType_Type.tp_getattro(pyclass, pyname);
309 if (attr || pyclass == (PyObject*)&CPPInstance_Type)
310 return attr;
311
313 return nullptr;
314
315// filter for python specials
316 std::string name = CPyCppyy_PyText_AsString(pyname);
317 if (name.size() >= 2 && name.compare(0, 2, "__") == 0 &&
318 name.compare(name.size()-2, name.size(), "__") == 0)
319 return nullptr;
320
321// more elaborate search in case of failure (eg. for inner classes on demand)
322 std::vector<Utility::PyError_t> errors;
323 Utility::FetchError(errors);
324 attr = CreateScopeProxy(name, pyclass);
325 if (CPPScope_Check(attr) && (((CPPScope*)attr)->fFlags & CPPScope::kIsException)) {
326 // Instead of the CPPScope, return a fresh exception class derived from CPPExcInstance.
327 return CreateExcScopeProxy(attr, pyname, pyclass);
328 }
329
330 CPPScope* klass = ((CPPScope*)pyclass);
331 if (!attr) {
332 Utility::FetchError(errors);
333 Cppyy::TCppScope_t scope = klass->fCppType;
334
335 // namespaces may have seen updates in their list of global functions, which
336 // are available as "methods" even though they're not really that
337 if (klass->fFlags & CPPScope::kIsNamespace) {
338 // tickle lazy lookup of functions
339 const std::vector<Cppyy::TCppIndex_t> methods =
341 if (!methods.empty()) {
342 // function exists, now collect overloads
343 std::vector<PyCallable*> overloads;
344 for (auto idx : methods) {
345 overloads.push_back(
346 new CPPFunction(scope, Cppyy::GetMethod(scope, idx)));
347 }
348
349 // Note: can't re-use Utility::AddClass here, as there's the risk of
350 // a recursive call. Simply add method directly, as we're guaranteed
351 // that it doesn't exist yet.
353 attr = add_template(pyclass, name, &overloads);
354
355 if (!attr) // add_template can fail if the method can not be added
356 attr = (PyObject*)CPPOverload_New(name, overloads);
357 }
358
359 // tickle lazy lookup of data members
360 if (!attr) {
362 if (dmi != (Cppyy::TCppIndex_t)-1) attr = (PyObject*)CPPDataMember_New(scope, dmi);
363 }
364 }
365
366 // this may be a typedef that resolves to a sugared type
367 if (!attr) {
368 const std::string& lookup = Cppyy::GetScopedFinalName(klass->fCppType) + "::" + name;
369 const std::string& resolved = Cppyy::ResolveName(lookup);
370 if (resolved != lookup) {
371 const std::string& cpd = Utility::Compound(resolved);
372 if (cpd == "*") {
373 const std::string& clean = TypeManip::clean_type(resolved, false, true);
375 if (tcl) {
378 tpc->fType = tcl;
379 attr = (PyObject*)tpc;
380 }
381 }
382 }
383 }
384
385 // function templates that have not been instantiated
386 if (!attr) {
388 attr = add_template(pyclass, name);
389 else {
390 // for completeness in error reporting
391 PyErr_Format(PyExc_TypeError, "\'%s\' is not a known C++ template", name.c_str());
392 Utility::FetchError(errors);
393 }
394 }
395
396 // enums types requested as type (rather than the constants)
397 if (!attr) {
398 // TODO: IsEnum should deal with the scope, using klass->GetListOfEnums()->FindObject()
400 // enum types (incl. named and class enums)
401 Cppyy::TCppEnum_t etype = Cppyy::GetEnum(scope, name);
402 if (etype) {
403 // create new enum type with labeled values in place, with a meta-class
404 // to make sure the enum values are read-only
405 PyObject* pymetabases = PyTuple_New(1);
406 PyObject* btype = (PyObject*)Py_TYPE(&PyInt_Type);
407 Py_INCREF(btype);
408 PyTuple_SET_ITEM(pymetabases, 0, btype);
409
410 PyObject* args = Py_BuildValue((char*)"sO{}", (name+"_meta").c_str(), pymetabases);
411 Py_DECREF(pymetabases);
412 PyObject* pymeta = PyType_Type.tp_new(Py_TYPE(&PyInt_Type), args, nullptr);
413 ((PyTypeObject*)pymeta)->tp_setattro = enum_setattro;
414 Py_DECREF(args);
415
416 // prepare the base class
417 PyObject* pybases = PyTuple_New(1);
418 Py_INCREF(&PyInt_Type);
419 PyTuple_SET_ITEM(pybases, 0, (PyObject*)&PyInt_Type);
420
421 // collect the enum values
423 PyObject* dct = PyDict_New();
424 for (Cppyy::TCppIndex_t idata = 0; idata < ndata; ++idata) {
425 PyObject* val = PyLong_FromLongLong(Cppyy::GetEnumDataValue(etype, idata));
426 PyDict_SetItemString(dct, Cppyy::GetEnumDataName(etype, idata).c_str(), val);
427 Py_DECREF(val);
428 }
429
430 // add the __cpp_name__ for templates
431 PyObject* cppname = nullptr;
432 if (scope == Cppyy::gGlobalScope) {
433 Py_INCREF(pyname);
434 cppname = pyname;
435 } else
436 cppname = CPyCppyy_PyText_FromString((Cppyy::GetScopedFinalName(scope)+"::"+name).c_str());
437 PyDict_SetItem(dct, PyStrings::gCppName, cppname);
438 Py_DECREF(cppname);
439
440 // create the actual enum class
441 args = Py_BuildValue((char*)"sOO", name.c_str(), pybases, dct);
442 Py_DECREF(pybases);
443 Py_DECREF(dct);
444 attr = ((PyTypeObject*)pymeta)->tp_new((PyTypeObject*)pymeta, args, nullptr);
445
446 // final cleanup
447 Py_DECREF(args);
448 Py_DECREF(pymeta);
449
450 } else {
451 // presumably not a class enum; simply pretend int
452 Py_INCREF(&PyInt_Type);
453 attr = (PyObject*)&PyInt_Type;
454 }
455 } else {
456 // for completeness in error reporting
457 PyErr_Format(PyExc_TypeError, "\'%s\' is not a known C++ enum", name.c_str());
458 Utility::FetchError(errors);
459 }
460 }
461
462 if (attr) {
463 // cache the result
464 if (CPPDataMember_Check(attr)) {
465 PyType_Type.tp_setattro((PyObject*)Py_TYPE(pyclass), pyname, attr);
466 Py_DECREF(attr);
467 attr = PyType_Type.tp_getattro(pyclass, pyname);
468 } else
469 PyType_Type.tp_setattro(pyclass, pyname, attr);
470
471 } else {
472 Utility::FetchError(errors);
473 }
474 }
475
476 if (!attr && (klass->fFlags & CPPScope::kIsNamespace)) {
477 // refresh using list as necessary
478 const std::vector<Cppyy::TCppScope_t>& uv = Cppyy::GetUsingNamespaces(klass->fCppType);
479 if (!klass->fImp.fUsing || uv.size() != klass->fImp.fUsing->size()) {
480 if (klass->fImp.fUsing) {
481 for (auto pyref : *klass->fImp.fUsing) Py_DECREF(pyref);
482 klass->fImp.fUsing->clear();
483 } else
484 klass->fImp.fUsing = new std::vector<PyObject*>;
485
486 // reload and reset weak refs
487 for (auto uid : uv) {
488 std::string uname = Cppyy::GetScopedFinalName(uid);
489 PyObject* pyuscope = CreateScopeProxy(uname);
490 if (pyuscope) {
491 klass->fImp.fUsing->push_back(PyWeakref_NewRef(pyuscope, nullptr));
492 // the namespace may not otherwise be held, so tie the lifetimes
493 PyObject* llname = CPyCppyy_PyText_FromString(("__lifeline_"+uname).c_str());
494 PyType_Type.tp_setattro(pyclass, llname, pyuscope);
495 Py_DECREF(llname);
496 Py_DECREF(pyuscope);
497 }
498 }
499 }
500
501 // try all outstanding using namespaces in turn to find the attribute (will cache
502 // locally later; TODO: doing so may cause pathological cases)
503 for (auto pyref : *klass->fImp.fUsing) {
504 PyObject* pyuscope = PyWeakref_GetObject(pyref);
505 if (pyuscope) {
506 attr = PyObject_GetAttr(pyuscope, pyname);
507 if (attr) break;
508 PyErr_Clear();
509 }
510 }
511 }
512
513 if (attr) {
514 std::for_each(errors.begin(), errors.end(), Utility::PyError_t::Clear);
515 PyErr_Clear();
516 } else {
517 // not found: prepare a full error report
518 PyObject* topmsg = nullptr;
519 PyObject* sklass = PyObject_Str(pyclass);
520 if (sklass) {
521 topmsg = CPyCppyy_PyText_FromFormat("%s has no attribute \'%s\'. Full details:",
523 Py_DECREF(sklass);
524 } else {
525 topmsg = CPyCppyy_PyText_FromFormat("no such attribute \'%s\'. Full details:",
527 }
528 SetDetailedException(errors, topmsg /* steals */, PyExc_AttributeError /* default error */);
529 }
530
531 return attr;
532}
533
534//----------------------------------------------------------------------------
535static int meta_setattro(PyObject* pyclass, PyObject* pyname, PyObject* pyval)
536{
537// Global data and static data in namespaces is found lazily, thus if the first
538// use is setting of the global data by the user, it will not be reflected on
539// the C++ side, b/c there is no descriptor yet. This triggers the creation for
540// for such data as necessary. The many checks to narrow down the specific case
541// are needed to prevent unnecessary lookups and recursion.
542 if (((CPPScope*)pyclass)->fFlags & CPPScope::kIsNamespace) {
543 // skip if the given pyval is a descriptor already, or an unassignable class
545 std::string name = CPyCppyy_PyText_AsString(pyname);
546 Cppyy::TCppIndex_t dmi = Cppyy::GetDatamemberIndex(((CPPScope*)pyclass)->fCppType, name);
547 if (dmi != (Cppyy::TCppIndex_t)-1)
548 meta_getattro(pyclass, pyname); // triggers creation
549 }
550 }
551
552 return PyType_Type.tp_setattro(pyclass, pyname, pyval);
553}
554
555
556//----------------------------------------------------------------------------
557// p2.7 does not have a __dir__ in object, and object.__dir__ in p3 does not
558// quite what I'd expected of it, so the following pulls in the internal code
559#include "PyObjectDir27.inc"
560
562{
563// Collect a list of everything (currently) available in the namespace.
564// The backend can filter by returning empty strings. Special care is
565// taken for functions, which need not be unique (overloading).
566 using namespace Cppyy;
567
568 if ((void*)klass == (void*)&CPPInstance_Type)
569 return PyList_New(0);
570
571 if (!CPyCppyy::CPPScope_Check((PyObject*)klass)) {
572 PyErr_SetString(PyExc_TypeError, "C++ proxy scope expected");
573 return nullptr;
574 }
575
576 PyObject* dirlist = _generic_dir((PyObject*)klass);
577 if (!(klass->fFlags & CPPScope::kIsNamespace))
578 return dirlist;
579
580 std::set<std::string> cppnames;
581 Cppyy::GetAllCppNames(klass->fCppType, cppnames);
582
583// get rid of duplicates
584 for (Py_ssize_t i = 0; i < PyList_GET_SIZE(dirlist); ++i)
585 cppnames.insert(CPyCppyy_PyText_AsString(PyList_GET_ITEM(dirlist, i)));
586
587 Py_DECREF(dirlist);
588 dirlist = PyList_New(cppnames.size());
589
590// copy total onto python list
591 Py_ssize_t i = 0;
592 for (const auto& name : cppnames) {
593 PyList_SET_ITEM(dirlist, i++, CPyCppyy_PyText_FromString(name.c_str()));
594 }
595 return dirlist;
596}
597
598//-----------------------------------------------------------------------------
599static PyMethodDef meta_methods[] = {
600 {(char*)"__dir__", (PyCFunction)meta_dir, METH_NOARGS, nullptr},
601 {(char*)nullptr, nullptr, 0, nullptr}
602};
603
604
605//-----------------------------------------------------------------------------
606static PyGetSetDef meta_getset[] = {
607 {(char*)"__cpp_name__", (getter)meta_getcppname, nullptr, nullptr, nullptr},
608 {(char*)"__module__", (getter)meta_getmodule, (setter)meta_setmodule, nullptr, nullptr},
609 {(char*)nullptr, nullptr, nullptr, nullptr, nullptr}
610};
611
612
613//= CPyCppyy object proxy type type ==========================================
614PyTypeObject CPPScope_Type = {
615 PyVarObject_HEAD_INIT(&PyType_Type, 0)
616 (char*)"cppyy.CPPScope", // tp_name
617 sizeof(CPyCppyy::CPPScope), // tp_basicsize
618 0, // tp_itemsize
619 0, // tp_dealloc
620 0, // tp_print
621 0, // tp_getattr
622 0, // tp_setattr
623 0, // tp_compare
624 (reprfunc)meta_repr, // tp_repr
625 0, // tp_as_number
626 0, // tp_as_sequence
627 0, // tp_as_mapping
628 0, // tp_hash
629 0, // tp_call
630 0, // tp_str
631 (getattrofunc)meta_getattro, // tp_getattro
632 (setattrofunc)meta_setattro, // tp_setattro
633 0, // tp_as_buffer
634 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
635#if PY_VERSION_HEX >= 0x03040000
636 | Py_TPFLAGS_TYPE_SUBCLASS
637#endif
638 , // tp_flags
639 (char*)"CPyCppyy metatype (internal)", // tp_doc
640 0, // tp_traverse
641 0, // tp_clear
642 0, // tp_richcompare
643 0, // tp_weaklistoffset
644 0, // tp_iter
645 0, // tp_iternext
646 meta_methods, // tp_methods
647 0, // tp_members
648 meta_getset, // tp_getset
649 &PyType_Type, // tp_base
650 0, // tp_dict
651 0, // tp_descr_get
652 0, // tp_descr_set
653 0, // tp_dictoffset
654 0, // tp_init
655 0, // tp_alloc
656 (newfunc)pt_new, // tp_new
657 0, // tp_free
658 0, // tp_is_gc
659 0, // tp_bases
660 0, // tp_mro
661 0, // tp_cache
662 0, // tp_subclasses
663 0 // tp_weaklist
664#if PY_VERSION_HEX >= 0x02030000
665 , 0 // tp_del
666#endif
667#if PY_VERSION_HEX >= 0x02060000
668 , 0 // tp_version_tag
669#endif
670#if PY_VERSION_HEX >= 0x03040000
671 , 0 // tp_finalize
672#endif
673};
674
675} // namespace CPyCppyy
#define Py_TYPE(ob)
Definition CPyCppyy.h:217
#define CPyCppyy_PyText_InternFromString
Definition CPyCppyy.h:103
int Py_ssize_t
Definition CPyCppyy.h:236
#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:215
unsigned int fFlags
_object PyObject
char name[80]
Definition TGX11.cxx:110
#define pyname
#define free
Definition civetweb.c:1539
#define malloc
Definition civetweb.c:1536
Utility::PyOperators * fOperators
Definition CPPScope.h:56
union CPyCppyy::CPPScope::@206 fImp
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)
R__EXTERN PyObject * gName
Definition TPython.cxx:105
R__EXTERN PyObject * gCppName
Definition TPython.cxx:103
R__EXTERN PyObject * gModule
Definition TPython.cxx:104
void cppscope_to_pyscope(std::string &cppscope)
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)
size_t FetchError(std::vector< PyError_t > &)
Definition Utility.cxx:879
const std::string Compound(const std::string &name)
Definition Utility.cxx:782
Set of helper functions that are invoked from the pythonizors, on the Python side.
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:561
static PyObject * meta_alloc(PyTypeObject *meta, Py_ssize_t nitems)
Definition CPPScope.cxx:81
PyTypeObject TypedefPointerToClass_Type
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)
static int meta_setattro(PyObject *pyclass, PyObject *pyname, PyObject *pyval)
Definition CPPScope.cxx:535
static PyObject * meta_getmodule(CPPScope *scope, void *)
Definition CPPScope.cxx:112
CPPDataMember * CPPDataMember_New(Cppyy::TCppScope_t scope, Cppyy::TCppIndex_t idata)
static PyGetSetDef meta_getset[]
Definition CPPScope.cxx:606
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:599
bool CPPDataMember_Check(T *object)
static PyObject * meta_getattro(PyObject *pyclass, PyObject *pyname)
Definition CPPScope.cxx:305
static PyObject * meta_getcppname(CPPScope *scope, void *)
Definition CPPScope.cxx:104
bool InsertDispatcher(CPPScope *klass, PyObject *bases, PyObject *dct, std::ostringstream &err)
PyTypeObject CPPScope_Type
Definition CPPScope.cxx:614
static PyObject * meta_repr(CPPScope *scope)
Definition CPPScope.cxx:175
TemplateProxy * TemplateProxy_New(const std::string &cppname, const std::string &pyname, PyObject *pyclass)
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)
static void Clear(PyError_t &e)
Definition Utility.h:82
PyObject_HEAD Cppyy::TCppType_t fType