Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
clingwrapper.cxx
Go to the documentation of this file.
1// Bindings
2#include "capi.h"
3#include "cpp_cppyy.h"
4#include "callcontext.h"
5
6// ROOT
7#include "TBaseClass.h"
8#include "TClass.h"
9#include "TClassRef.h"
10#include "TClassTable.h"
11#include "TClassEdit.h"
12#include "TCollection.h"
13#include "TDataMember.h"
14#include "TDataType.h"
15#include "TEnum.h"
16#include "TEnumConstant.h"
17#include "TEnv.h"
18#include "TError.h"
19#include "TException.h"
20#include "TFunction.h"
21#include "TFunctionTemplate.h"
22#include "TGlobal.h"
23#include "THashList.h"
24#include "TInterpreter.h"
25#include "TList.h"
26#include "TListOfDataMembers.h"
27#include "TListOfEnums.h"
28#include "TMethod.h"
29#include "TMethodArg.h"
30#include "TROOT.h"
31#include "TSystem.h"
32
33// Standard
34#include <assert.h>
35#include <algorithm> // for std::count, std::remove
36#include <climits>
37#include <stdexcept>
38#include <map>
39#include <new>
40#include <set>
41#include <sstream>
42#include <signal.h>
43#include <stdlib.h> // for getenv
44#include <string.h>
45#include <typeinfo>
46
47// temp
48#include <iostream>
50// --temp
51
52
53// small number that allows use of stack for argument passing
54const int SMALL_ARGS_N = 8;
55
56// convention to pass flag for direct calls (similar to Python's vector calls)
57#define DIRECT_CALL ((size_t)1 << (8 * sizeof(size_t) - 1))
58static inline size_t CALL_NARGS(size_t nargs) {
59 return nargs & ~DIRECT_CALL;
60}
61
62// data for life time management ---------------------------------------------
63typedef std::vector<TClassRef> ClassRefs_t;
65static const ClassRefs_t::size_type GLOBAL_HANDLE = 1;
66static const ClassRefs_t::size_type STD_HANDLE = GLOBAL_HANDLE + 1;
67
68typedef std::map<std::string, ClassRefs_t::size_type> Name2ClassRefIndex_t;
70
71namespace {
72
73static inline Cppyy::TCppType_t find_memoized(const std::string& name)
74{
75 auto icr = g_name2classrefidx.find(name);
76 if (icr != g_name2classrefidx.end())
77 return (Cppyy::TCppType_t)icr->second;
78 return (Cppyy::TCppType_t)0;
79}
80
81class CallWrapper {
82public:
83 typedef const void* DeclId_t;
84
85public:
86 CallWrapper(TFunction* f) : fDecl(f->GetDeclId()), fName(f->GetName()), fTF(nullptr) {}
87 CallWrapper(DeclId_t fid, const std::string& n) : fDecl(fid), fName(n), fTF(nullptr) {}
88 ~CallWrapper() {
89 if (fTF && fDecl == fTF->GetDeclId())
90 delete fTF;
91 }
92
93public:
95 DeclId_t fDecl;
96 std::string fName;
97 TFunction* fTF;
98};
99
100}
101
102static std::vector<CallWrapper*> gWrapperHolder;
103static inline CallWrapper* new_CallWrapper(TFunction* f)
104{
105 CallWrapper* wrap = new CallWrapper(f);
106 gWrapperHolder.push_back(wrap);
107 return wrap;
108}
109
110static inline CallWrapper* new_CallWrapper(CallWrapper::DeclId_t fid, const std::string& n)
111{
112 CallWrapper* wrap = new CallWrapper(fid, n);
113 gWrapperHolder.push_back(wrap);
114 return wrap;
115}
116
117typedef std::vector<TGlobal*> GlobalVars_t;
119
120static std::set<std::string> gSTLNames;
121
122
123// data ----------------------------------------------------------------------
125
126// builtin types (including a few common STL templates as long as they live in
127// the global namespace b/c of choices upstream)
128static std::set<std::string> g_builtins =
129 {"bool", "char", "signed char", "unsigned char", "wchar_t", "short", "unsigned short",
130 "int", "unsigned int", "long", "unsigned long", "long long", "unsigned long long",
131 "float", "double", "long double", "void",
132 "allocator", "array", "basic_string", "complex", "initializer_list", "less", "list",
133 "map", "pair", "set", "vector"};
134
135// smart pointer types
136static std::set<std::string> gSmartPtrTypes =
137 {"auto_ptr", "std::auto_ptr", "shared_ptr", "std::shared_ptr",
138 "unique_ptr", "std::unique_ptr", "weak_ptr", "std::weak_ptr"};
139
140// to filter out ROOT names
141static std::set<std::string> gInitialNames;
142static std::set<std::string> gRootSOs;
143
144// configuration
145static bool gEnableFastPath = true;
146
147
148// global initialization -----------------------------------------------------
149namespace {
150
151// names copied from TUnixSystem
152#ifdef WIN32
153const int SIGBUS = 0; // simple placeholders for ones that don't exist
154const int SIGSYS = 0;
155const int SIGPIPE = 0;
156const int SIGQUIT = 0;
157const int SIGWINCH = 0;
158const int SIGALRM = 0;
159const int SIGCHLD = 0;
160const int SIGURG = 0;
161const int SIGUSR1 = 0;
162const int SIGUSR2 = 0;
163#endif
164
165static struct Signalmap_t {
166 int fCode;
167 const char *fSigName;
168} gSignalMap[kMAXSIGNALS] = { // the order of the signals should be identical
169 { SIGBUS, "bus error" }, // to the one in TSysEvtHandler.h
170 { SIGSEGV, "segmentation violation" },
171 { SIGSYS, "bad argument to system call" },
172 { SIGPIPE, "write on a pipe with no one to read it" },
173 { SIGILL, "illegal instruction" },
174 { SIGABRT, "abort" },
175 { SIGQUIT, "quit" },
176 { SIGINT, "interrupt" },
177 { SIGWINCH, "window size change" },
178 { SIGALRM, "alarm clock" },
179 { SIGCHLD, "death of a child" },
180 { SIGURG, "urgent data arrived on an I/O channel" },
181 { SIGFPE, "floating point exception" },
182 { SIGTERM, "termination signal" },
183 { SIGUSR1, "user-defined signal 1" },
184 { SIGUSR2, "user-defined signal 2" }
185};
186
187static void inline do_trace(int sig) {
188 std::cerr << " *** Break *** " << (sig < kMAXSIGNALS ? gSignalMap[sig].fSigName : "") << std::endl;
190}
191
192class TExceptionHandlerImp : public TExceptionHandler {
193public:
194 void HandleException(Int_t sig) override {
195 if (TROOT::Initialized()) {
196 if (gException) {
197 gInterpreter->RewindDictionary();
198 gInterpreter->ClearFileBusy();
199 }
200
201 if (!getenv("CPPYY_CRASH_QUIET"))
202 do_trace(sig);
203
204 // jump back, if catch point set
205 Throw(sig);
206 }
207
208 do_trace(sig);
209 gSystem->Exit(128 + sig);
210 }
211};
212
213class ApplicationStarter {
214public:
215 ApplicationStarter() {
216 // initialize ROOT early to guarantee proper order of shutdown later on (gROOT is a
217 // macro that resolves to the ROOT::GetROOT() function call)
218 (void)gROOT;
219
220 // setup dummy holders for global and std namespaces
221 assert(g_classrefs.size() == GLOBAL_HANDLE);
223 g_classrefs.push_back(TClassRef(""));
224
225 // aliases for std (setup already in pythonify)
227 g_name2classrefidx["::std"] = g_name2classrefidx["std"];
228 g_classrefs.push_back(TClassRef("std"));
229
230 // add a dummy global to refer to as null at index 0
231 g_globalvars.push_back(nullptr);
232
233 // disable fast path if requested
234 if (getenv("CPPYY_DISABLE_FASTPATH")) gEnableFastPath = false;
235
236 // fill the set of STL names
237 const char* stl_names[] = {"allocator", "auto_ptr", "bad_alloc", "bad_cast",
238 "bad_exception", "bad_typeid", "basic_filebuf", "basic_fstream", "basic_ifstream",
239 "basic_ios", "basic_iostream", "basic_istream", "basic_istringstream",
240 "basic_ofstream", "basic_ostream", "basic_ostringstream", "basic_streambuf",
241 "basic_string", "basic_stringbuf", "basic_stringstream", "binary_function",
242 "binary_negate", "bitset", "byte", "char_traits", "codecvt_byname", "codecvt", "collate",
243 "collate_byname", "compare", "complex", "ctype_byname", "ctype", "default_delete",
244 "deque", "divides", "domain_error", "equal_to", "exception", "forward_list", "fpos",
245 "function", "greater_equal", "greater", "gslice_array", "gslice", "hash", "indirect_array",
246 "integer_sequence", "invalid_argument", "ios_base", "istream_iterator", "istreambuf_iterator",
247 "istrstream", "iterator_traits", "iterator", "length_error", "less_equal", "less",
248 "list", "locale", "localedef utility", "locale utility", "logic_error", "logical_and",
249 "logical_not", "logical_or", "map", "mask_array", "mem_fun", "mem_fun_ref", "messages",
250 "messages_byname", "minus", "modulus", "money_get", "money_put", "moneypunct",
251 "moneypunct_byname", "multimap", "multiplies", "multiset", "negate", "not_equal_to",
252 "num_get", "num_put", "numeric_limits", "numpunct", "numpunct_byname",
253 "ostream_iterator", "ostreambuf_iterator", "ostrstream", "out_of_range",
254 "overflow_error", "pair", "plus", "pointer_to_binary_function",
255 "pointer_to_unary_function", "priority_queue", "queue", "range_error",
256 "raw_storage_iterator", "reverse_iterator", "runtime_error", "set", "shared_ptr",
257 "slice_array", "slice", "stack", "string", "strstream", "strstreambuf",
258 "time_get_byname", "time_get", "time_put_byname", "time_put", "unary_function",
259 "unary_negate", "unique_ptr", "underflow_error", "unordered_map", "unordered_multimap",
260 "unordered_multiset", "unordered_set", "valarray", "vector", "weak_ptr", "wstring"};
261 for (auto& name : stl_names)
262 gSTLNames.insert(name);
263
264 // set opt level (default to 2 if not given; Cling itself defaults to 0)
265 int optLevel = 2;
266 if (getenv("CPPYY_OPT_LEVEL")) optLevel = atoi(getenv("CPPYY_OPT_LEVEL"));
267 if (optLevel != 0) {
268 std::ostringstream s;
269 s << "#pragma cling optimize " << optLevel;
270 gInterpreter->ProcessLine(s.str().c_str());
271 }
272
273 // load frequently used headers
274 const char* code =
275 "#include <iostream>\n"
276 "#include <string>\n"
277 "#include <DllImport.h>\n" // defines R__EXTERN
278 "#include <vector>\n"
279 "#include <utility>";
280 gInterpreter->ProcessLine(code);
281
282 // create helpers for comparing thingies
283 gInterpreter->Declare(
284 "namespace __cppyy_internal { template<class C1, class C2>"
285 " bool is_equal(const C1& c1, const C2& c2) { return (bool)(c1 == c2); } }");
286 gInterpreter->Declare(
287 "namespace __cppyy_internal { template<class C1, class C2>"
288 " bool is_not_equal(const C1& c1, const C2& c2) { return (bool)(c1 != c2); } }");
289
290 // retrieve all initial (ROOT) C++ names in the global scope to allow filtering later
291 if (!getenv("CPPYY_NO_ROOT_FILTER")) {
292 gROOT->GetListOfGlobals(true); // force initialize
293 gROOT->GetListOfGlobalFunctions(true); // id.
294 std::set<std::string> initial;
296 gInitialNames = initial;
297
298#ifndef WIN32
299 gRootSOs.insert("libCore.so ");
300 gRootSOs.insert("libRIO.so ");
301 gRootSOs.insert("libThread.so ");
302 gRootSOs.insert("libMathCore.so ");
303#else
304 gRootSOs.insert("libCore.dll ");
305 gRootSOs.insert("libRIO.dll ");
306 gRootSOs.insert("libThread.dll ");
307 gRootSOs.insert("libMathCore.dll ");
308#endif
309 }
310
311 // start off with a reasonable size placeholder for wrappers
312 gWrapperHolder.reserve(1024);
313
314 // create an exception handler to process signals
315 gExceptionHandler = new TExceptionHandlerImp{};
316 }
317
318 ~ApplicationStarter() {
319 for (auto wrap : gWrapperHolder)
320 delete wrap;
321 delete gExceptionHandler; gExceptionHandler = nullptr;
322 }
323} _applicationStarter;
324
325} // unnamed namespace
326
327
328// local helpers -------------------------------------------------------------
329static inline
331{
332 assert((ClassRefs_t::size_type)scope < g_classrefs.size());
333 return g_classrefs[(ClassRefs_t::size_type)scope];
334}
335
336static inline
338 CallWrapper* wrap = ((CallWrapper*)method);
339 if (!wrap->fTF || wrap->fTF->GetDeclId() != wrap->fDecl) {
340 MethodInfo_t* mi = gInterpreter->MethodInfo_Factory(wrap->fDecl);
341 wrap->fTF = new TFunction(mi);
342 }
343 return wrap->fTF;
344}
345
346static inline
347CallWrapper::DeclId_t m2d(Cppyy::TCppMethod_t method) {
348 CallWrapper* wrap = ((CallWrapper*)method);
349 if (!wrap->fTF || wrap->fTF->GetDeclId() != wrap->fDecl) {
350 MethodInfo_t* mi = gInterpreter->MethodInfo_Factory(wrap->fDecl);
351 wrap->fTF = new TFunction(mi);
352 }
353 return wrap->fDecl;
354}
355
356static inline
357char* cppstring_to_cstring(const std::string& cppstr)
358{
359 char* cstr = (char*)malloc(cppstr.size()+1);
360 memcpy(cstr, cppstr.c_str(), cppstr.size()+1);
361 return cstr;
362}
363
364static inline
365bool match_name(const std::string& tname, const std::string fname)
366{
367// either match exactly, or match the name as template
368 if (fname.rfind(tname, 0) == 0) {
369 if ((tname.size() == fname.size()) ||
370 (tname.size() < fname.size() && fname[tname.size()] == '<'))
371 return true;
372 }
373 return false;
374}
375
376static inline
377bool is_missclassified_stl(const std::string& name)
378{
379 std::string::size_type pos = name.find('<');
380 if (pos != std::string::npos)
381 return gSTLNames.find(name.substr(0, pos)) != gSTLNames.end();
382 return gSTLNames.find(name) != gSTLNames.end();
383}
384
385
386// direct interpreter access -------------------------------------------------
387bool Cppyy::Compile(const std::string& code, bool /*silent*/)
388{
389 return gInterpreter->Declare(code.c_str());
390}
391
393{
394 if (klass && obj && !IsNamespace((TCppScope_t)klass))
395 return gInterpreter->ToString(GetScopedFinalName(klass).c_str(), (void*)obj);
396 return "";
397}
398
399
400// name to opaque C++ scope representation -----------------------------------
401std::string Cppyy::ResolveName(const std::string& cppitem_name)
402{
403// Fully resolve the given name to the final type name.
404
405// try memoized type cache, in case seen before
406 TCppType_t klass = find_memoized(cppitem_name);
407 if (klass) return GetScopedFinalName(klass);
408
409// remove global scope '::' if present
410 std::string tclean = cppitem_name.compare(0, 2, "::") == 0 ?
411 cppitem_name.substr(2, std::string::npos) : cppitem_name;
412
413// classes (most common)
414 tclean = TClassEdit::CleanType(tclean.c_str());
415 if (tclean.empty() /* unknown, eg. an operator */) return cppitem_name;
416
417// reduce [N] to []
418 if (tclean[tclean.size()-1] == ']')
419 tclean = tclean.substr(0, tclean.rfind('[')) + "[]";
420
421 if (tclean.rfind("byte", 0) == 0 || tclean.rfind("std::byte", 0) == 0)
422 return tclean;
423
424// check data types list (accept only builtins as typedefs will
425// otherwise not be resolved)
426 TDataType* dt = gROOT->GetType(tclean.c_str());
427 if (dt && dt->GetType() != kOther_t) return dt->GetFullTypeName();
428
429// special case for enums
430 if (IsEnum(cppitem_name))
431 return ResolveEnum(cppitem_name);
432
433// special case for clang's builtin __type_pack_element (which does not resolve)
434 if (cppitem_name.rfind("__type_pack_element", 0) != std::string::npos) {
435 // shape is "__type_pack_element<index,type1,type2,...,typeN>cpd": extract
436 // first the index, and from there the indexed type; finally, restore the
437 // qualifiers
438 const char* str = cppitem_name.c_str();
439 char* endptr = nullptr;
440 unsigned long index = strtoul(str+20, &endptr, 0);
441
442 std::string tmplvars{endptr};
443 auto start = tmplvars.find(',') + 1;
444 auto end = tmplvars.find(',', start);
445 while (index != 0) {
446 start = end+1;
447 end = tmplvars.find(',', start);
448 if (end == std::string::npos) end = tmplvars.rfind('>');
449 --index;
450 }
451
452 std::string resolved = tmplvars.substr(start, end-start);
453 auto cpd = tmplvars.rfind('>');
454 if (cpd != std::string::npos && cpd+1 != tmplvars.size())
455 return resolved + tmplvars.substr(cpd+1, std::string::npos);
456 return resolved;
457 }
458
459// typedefs
460 return TClassEdit::ResolveTypedef(tclean.c_str(), true);
461}
462
463static std::map<std::string, std::string> resolved_enum_types;
464std::string Cppyy::ResolveEnum(const std::string& enum_type)
465{
466// The underlying type of a an enum may be any kind of integer.
467// Resolve that type via a workaround (note: this function assumes
468// that the enum_type name is a valid enum type name)
469 auto res = resolved_enum_types.find(enum_type);
470 if (res != resolved_enum_types.end())
471 return res->second;
472
473// desugar the type before resolving
474 std::string et_short = TClassEdit::ShortType(enum_type.c_str(), 1);
475 if (et_short.find("(unnamed") == std::string::npos) {
476 std::ostringstream decl;
477 // TODO: now presumed fixed with https://sft.its.cern.ch/jira/browse/ROOT-6988
478 for (auto& itype : {"unsigned int"}) {
479 decl << "std::is_same<"
480 << itype
481 << ", std::underlying_type<"
482 << et_short
483 << ">::type>::value;";
484 if (gInterpreter->ProcessLine(decl.str().c_str())) {
485 // TODO: "re-sugaring" like this is brittle, but the top
486 // should be re-translated into AST-based code anyway
487 std::string resugared;
488 if (et_short.size() != enum_type.size()) {
489 auto pos = enum_type.find(et_short);
490 if (pos != std::string::npos) {
491 resugared = enum_type.substr(0, pos) + itype;
492 if (pos+et_short.size() < enum_type.size())
493 resugared += enum_type.substr(pos+et_short.size(), std::string::npos);
494 }
495 }
496 if (resugared.empty()) resugared = itype;
497 resolved_enum_types[enum_type] = resugared;
498 return resugared;
499 }
500 }
501 }
502
503// failed or anonymous ... signal upstream to special case this
504 int ipos = (int)enum_type.size()-1;
505 for (; 0 <= ipos; --ipos) {
506 char c = enum_type[ipos];
507 if (isspace(c)) continue;
508 if (isalnum(c) || c == '_' || c == '>' || c == ')') break;
509 }
510 bool isConst = enum_type.find("const ", 6) != std::string::npos;
511 std::string restype = isConst ? "const " : "";
512 restype += "internal_enum_type_t"+enum_type.substr((std::string::size_type)ipos+1, std::string::npos);
513 resolved_enum_types[enum_type] = restype;
514 return restype; // should default to some int variant
515}
516
517Cppyy::TCppScope_t Cppyy::GetScope(const std::string& sname)
518{
519// First, try cache
520 TCppType_t result = find_memoized(sname);
521 if (result) return result;
522
523// Second, skip builtins before going through the more expensive steps of resolving
524// typedefs and looking up TClass
525 if (g_builtins.find(sname) != g_builtins.end())
526 return (TCppScope_t)0;
527
528// TODO: scope_name should always be final already?
529// Resolve name fully before lookup to make sure all aliases point to the same scope
530 std::string scope_name = ResolveName(sname);
531 bool bHasAlias = sname != scope_name;
532 if (bHasAlias) {
533 result = find_memoized(scope_name);
534 if (result) return result;
535 }
536
537// both failed, but may be STL name that's missing 'std::' now, but didn't before
538 bool b_scope_name_missclassified = is_missclassified_stl(scope_name);
539 if (b_scope_name_missclassified) {
540 result = find_memoized("std::"+scope_name);
541 if (result) g_name2classrefidx["std::"+scope_name] = (ClassRefs_t::size_type)result;
542 }
543 bool b_sname_missclassified = bHasAlias ? is_missclassified_stl(sname) : false;
544 if (b_sname_missclassified) {
545 if (!result) result = find_memoized("std::"+sname);
546 if (result) g_name2classrefidx["std::"+sname] = (ClassRefs_t::size_type)result;
547 }
548
549 if (result) return result;
550
551// use TClass directly, to enable auto-loading; class may be stubbed (eg. for
552// function returns) or forward declared, leading to a non-null TClass that is
553// otherwise invalid/unusable
554 TClassRef cr(TClass::GetClass(scope_name.c_str(), true /* load */, true /* silent */));
555 if (!cr.GetClass())
556 return (TCppScope_t)0;
557
558// memoize found/created TClass
559 ClassRefs_t::size_type sz = g_classrefs.size();
560 g_name2classrefidx[scope_name] = sz;
561 if (bHasAlias) g_name2classrefidx[sname] = sz;
562 g_classrefs.push_back(TClassRef(scope_name.c_str()));
563
564// TODO: make ROOT/meta NOT remove std :/
565 if (b_scope_name_missclassified)
566 g_name2classrefidx["std::"+scope_name] = sz;
567 if (b_sname_missclassified)
568 g_name2classrefidx["std::"+sname] = sz;
569
570 return (TCppScope_t)sz;
571}
572
573bool Cppyy::IsTemplate(const std::string& template_name)
574{
575 return (bool)gInterpreter->CheckClassTemplate(template_name.c_str());
576}
577
578namespace {
579 class AutoCastRTTI {
580 public:
581 virtual ~AutoCastRTTI() {}
582 };
583}
584
586{
587 TClassRef& cr = type_from_handle(klass);
588 if (!cr.GetClass() || !obj) return klass;
589
590#ifdef _WIN64
591// Cling does not provide a consistent ImageBase address for calculating relative addresses
592// as used in Windows 64b RTTI. So, check for our own RTTI extension instead. If that fails,
593// see whether the unmangled raw_name is available (e.g. if this is an MSVC compiled rather
594// than JITed class) and pass on if it is.
595 volatile const char* raw = nullptr; // to prevent too aggressive reordering
596 try {
597 // this will filter those objects that do not have RTTI to begin with (throws)
598 AutoCastRTTI* pcst = (AutoCastRTTI*)obj;
599 raw = typeid(*pcst).raw_name();
600
601 // check the signature id (0 == absolute, 1 == relative, 2 == ours)
602 void* vfptr = *(void**)((intptr_t)obj);
603 void* meta = (void*)((intptr_t)*((void**)((intptr_t)vfptr-sizeof(void*))));
604 if (*(intptr_t*)meta == 2) {
605 // access the extra data item which is an absolute pointer to the RTTI
606 void* ptdescr = (void*)((intptr_t)meta + 4*sizeof(unsigned long)+sizeof(void*));
607 if (ptdescr && *(void**)ptdescr) {
608 auto rtti = *(std::type_info**)ptdescr;
609 raw = rtti->raw_name();
610 if (raw && raw[0] != '\0') // likely unnecessary
611 return (TCppType_t)GetScope(rtti->name());
612 }
613
614 return klass; // do not fall through if no RTTI info available
615 }
616
617 // if the raw name is the empty string (no guarantees that this is so as truly, the
618 // address is corrupt, but it is common to be empty), then there is no accessible RTTI
619 // and getting the unmangled name will crash ...
620 if (!raw)
621 return klass;
622 } catch (std::bad_typeid) {
623 return klass; // can't risk passing to ROOT/meta as it may do RTTI
624 }
625#endif
626
627 TClass* clActual = cr->GetActualClass((void*)obj);
628 // The additional check using TClass::GetClassInfo is to prevent returning classes of which the Interpreter has no info
629 if (clActual && clActual != cr.GetClass() && clActual->GetClassInfo()) {
630 auto itt = g_name2classrefidx.find(clActual->GetName());
631 if (itt != g_name2classrefidx.end())
632 return (TCppType_t)itt->second;
633 return (TCppType_t)GetScope(clActual->GetName());
634 }
635
636 return klass;
637}
638
640{
641 TClassRef& cr = type_from_handle(klass);
642 if (cr.GetClass() && cr->GetClassInfo())
643 return (size_t)gInterpreter->ClassInfo_Size(cr->GetClassInfo());
644 return (size_t)0;
645}
646
647size_t Cppyy::SizeOf(const std::string& type_name)
648{
649 TDataType* dt = gROOT->GetType(type_name.c_str());
650 if (dt) return dt->Size();
651 return SizeOf(GetScope(type_name));
652}
653
654bool Cppyy::IsBuiltin(const std::string& type_name)
655{
656 TDataType* dt = gROOT->GetType(TClassEdit::CleanType(type_name.c_str(), 1).c_str());
657 if (dt) return dt->GetType() != kOther_t;
658 return false;
659}
660
661bool Cppyy::IsComplete(const std::string& type_name)
662{
663// verify whether the dictionary of this class is fully available
664 bool b = false;
665
666 int oldEIL = gErrorIgnoreLevel;
667 gErrorIgnoreLevel = 3000;
668 TClass* klass = TClass::GetClass(TClassEdit::ShortType(type_name.c_str(), 1).c_str());
669 if (klass && klass->GetClassInfo()) // works for normal case w/ dict
670 b = gInterpreter->ClassInfo_IsLoaded(klass->GetClassInfo());
671 else { // special case for forward declared classes
672 ClassInfo_t* ci = gInterpreter->ClassInfo_Factory(type_name.c_str());
673 if (ci) {
674 b = gInterpreter->ClassInfo_IsLoaded(ci);
675 gInterpreter->ClassInfo_Delete(ci); // we own the fresh class info
676 }
677 }
678 gErrorIgnoreLevel = oldEIL;
679 return b;
680}
681
682// memory management ---------------------------------------------------------
684{
686 return (TCppObject_t)::operator new(gInterpreter->ClassInfo_Size(cr->GetClassInfo()));
687}
688
690{
691 ::operator delete(instance);
692}
693
695{
697 if (arena)
698 return (TCppObject_t)cr->New(arena, TClass::kRealNew);
699 return (TCppObject_t)cr->New(TClass::kRealNew);
700}
701
702static std::map<Cppyy::TCppType_t, bool> sHasOperatorDelete;
704{
707 cr->Destructor((void*)instance);
708 else {
709 ROOT::DelFunc_t fdel = cr->GetDelete();
710 if (fdel) fdel((void*)instance);
711 else {
712 auto ib = sHasOperatorDelete.find(type);
713 if (ib == sHasOperatorDelete.end()) {
714 TFunction *f = (TFunction *)cr->GetMethodAllAny("operator delete");
715 sHasOperatorDelete[type] = (bool)(f && (f->Property() & kIsPublic));
716 ib = sHasOperatorDelete.find(type);
717 }
718 ib->second ? cr->Destructor((void *)instance) : ::operator delete((void *)instance);
719 }
720 }
721}
722
723
724// method/function dispatching -----------------------------------------------
726{
727// TODO: method should be a callfunc, so that no mapping would be needed.
728 CallWrapper* wrap = (CallWrapper*)method;
729
730 CallFunc_t* callf = gInterpreter->CallFunc_Factory();
731 MethodInfo_t* meth = gInterpreter->MethodInfo_Factory(wrap->fDecl);
732 gInterpreter->CallFunc_SetFunc(callf, meth);
733 gInterpreter->MethodInfo_Delete(meth);
734
735 if (!(callf && gInterpreter->CallFunc_IsValid(callf))) {
736 // TODO: propagate this error to caller w/o use of Python C-API
737 /*
738 PyErr_Format(PyExc_RuntimeError, "could not resolve %s::%s(%s)",
739 const_cast<TClassRef&>(klass).GetClassName(),
740 wrap.fName, callString.c_str()); */
741 std::cerr << "TODO: report unresolved function error to Python\n";
742 if (callf) gInterpreter->CallFunc_Delete(callf);
744 }
745
746// generate the wrapper and JIT it; ignore wrapper generation errors (will simply
747// result in a nullptr that is reported upstream if necessary; often, however,
748// there is a different overload available that will do)
749 auto oldErrLvl = gErrorIgnoreLevel;
751 wrap->fFaceptr = gInterpreter->CallFunc_IFacePtr(callf);
752 gErrorIgnoreLevel = oldErrLvl;
753
754 gInterpreter->CallFunc_Delete(callf); // does not touch IFacePtr
755 return wrap->fFaceptr;
756}
757
758static inline
759bool copy_args(Parameter* args, size_t nargs, void** vargs)
760{
761 bool runRelease = false;
762 for (size_t i = 0; i < nargs; ++i) {
763 switch (args[i].fTypeCode) {
764 case 'X': /* (void*)type& with free */
765 runRelease = true;
766 case 'V': /* (void*)type& */
767 vargs[i] = args[i].fValue.fVoidp;
768 break;
769 case 'r': /* const type& */
770 vargs[i] = args[i].fRef;
771 break;
772 default: /* all other types in union */
773 vargs[i] = (void*)&args[i].fValue.fVoidp;
774 break;
775 }
776 }
777 return runRelease;
778}
779
780static inline
781void release_args(Parameter* args, size_t nargs) {
782 for (size_t i = 0; i < nargs; ++i) {
783 if (args[i].fTypeCode == 'X')
784 free(args[i].fValue.fVoidp);
785 }
786}
787
788static inline bool WrapperCall(Cppyy::TCppMethod_t method, size_t nargs, void* args_, void* self, void* result)
789{
790 Parameter* args = (Parameter*)args_;
791 //bool is_direct = nargs & DIRECT_CALL;
792 nargs = CALL_NARGS(nargs);
793
794 CallWrapper* wrap = (CallWrapper*)method;
795 const TInterpreter::CallFuncIFacePtr_t& faceptr = wrap->fFaceptr.fGeneric ? wrap->fFaceptr : GetCallFunc(method);
796 if (!faceptr.fGeneric)
797 return false; // happens with compilation error
798
800 bool runRelease = false;
801 if (nargs <= SMALL_ARGS_N) {
802 void* smallbuf[SMALL_ARGS_N];
803 if (nargs) runRelease = copy_args(args, nargs, smallbuf);
804 faceptr.fGeneric(self, (int)nargs, smallbuf, result);
805 } else {
806 std::vector<void*> buf(nargs);
807 runRelease = copy_args(args, nargs, buf.data());
808 faceptr.fGeneric(self, (int)nargs, buf.data(), result);
809 }
810 if (runRelease) release_args(args, nargs);
811 return true;
812 }
813
815 bool runRelease = false;
816 if (nargs <= SMALL_ARGS_N) {
817 void* smallbuf[SMALL_ARGS_N];
818 if (nargs) runRelease = copy_args(args, nargs, (void**)smallbuf);
819 faceptr.fCtor((void**)smallbuf, result, (unsigned long)nargs);
820 } else {
821 std::vector<void*> buf(nargs);
822 runRelease = copy_args(args, nargs, buf.data());
823 faceptr.fCtor(buf.data(), result, (unsigned long)nargs);
824 }
825 if (runRelease) release_args(args, nargs);
826 return true;
827 }
828
830 std::cerr << " DESTRUCTOR NOT IMPLEMENTED YET! " << std::endl;
831 return false;
832 }
833
834 return false;
835}
836
837template<typename T>
838static inline
839T CallT(Cppyy::TCppMethod_t method, Cppyy::TCppObject_t self, size_t nargs, void* args)
840{
841 T t{};
842 if (WrapperCall(method, nargs, args, (void*)self, &t))
843 return t;
844 return (T)-1;
845}
846
847#define CPPYY_IMP_CALL(typecode, rtype) \
848rtype Cppyy::Call##typecode(TCppMethod_t method, TCppObject_t self, size_t nargs, void* args)\
849{ \
850 return CallT<rtype>(method, self, nargs, args); \
851}
852
853void Cppyy::CallV(TCppMethod_t method, TCppObject_t self, size_t nargs, void* args)
854{
855 if (!WrapperCall(method, nargs, args, (void*)self, nullptr))
856 return /* TODO ... report error */;
857}
858
859CPPYY_IMP_CALL(B, unsigned char)
866CPPYY_IMP_CALL(D, double )
868
869void* Cppyy::CallR(TCppMethod_t method, TCppObject_t self, size_t nargs, void* args)
870{
871 void* r = nullptr;
872 if (WrapperCall(method, nargs, args, (void*)self, &r))
873 return r;
874 return nullptr;
875}
876
878 TCppMethod_t method, TCppObject_t self, size_t nargs, void* args, size_t* length)
879{
880 char* cstr = nullptr;
881 TClassRef cr("std::string");
882 std::string* cppresult = (std::string*)malloc(sizeof(std::string));
883 if (WrapperCall(method, nargs, args, self, (void*)cppresult)) {
884 cstr = cppstring_to_cstring(*cppresult);
885 *length = cppresult->size();
886 cppresult->std::string::~basic_string();
887 } else
888 *length = 0;
889 free((void*)cppresult);
890 return cstr;
891}
892
894 TCppMethod_t method, TCppType_t /* klass */, size_t nargs, void* args)
895{
896 void* obj = nullptr;
897 if (WrapperCall(method, nargs, args, nullptr, &obj))
898 return (TCppObject_t)obj;
899 return (TCppObject_t)0;
900}
901
903{
905 cr->Destructor((void*)self, true);
906}
907
909 TCppObject_t self, size_t nargs, void* args, TCppType_t result_type)
910{
911 TClassRef& cr = type_from_handle(result_type);
912 void* obj = ::operator new(gInterpreter->ClassInfo_Size(cr->GetClassInfo()));
913 if (WrapperCall(method, nargs, args, self, obj))
914 return (TCppObject_t)obj;
915 ::operator delete(obj);
916 return (TCppObject_t)0;
917}
918
920{
921 if (check_enabled && !gEnableFastPath) return (TCppFuncAddr_t)nullptr;
922 TFunction* f = m2f(method);
923 TCppFuncAddr_t pf = gInterpreter->FindSym(f->GetMangledName());
924 if (pf) return pf;
925
926 int ierr = 0;
927 const char* fn = TClassEdit::DemangleName(f->GetMangledName(), ierr);
928 if (ierr || !fn)
929 return pf;
930
931 // TODO: the following attempts are all brittle and leak transactions, but
932 // each properly exposes the symbol so subsequent lookups will succeed
933 if (strstr(f->GetName(), "<")) {
934 // force explicit instantiation and try again
935 std::ostringstream sig;
936 sig << "template " << fn << ";";
937 gInterpreter->ProcessLine(sig.str().c_str());
938 } else {
939 std::string sfn(fn);
940 std::string addrstr;
941 addrstr.reserve(128);
942 addrstr.push_back('(');
943 addrstr.append(Cppyy::GetMethodResultType(method));
944 addrstr.append(" (");
945
946 if (gInterpreter->FunctionDeclId_IsMethod(m2d(method))) {
947 std::string::size_type colon = sfn.rfind("::");
948 if (colon != std::string::npos) addrstr.append(sfn.substr(0, colon+2));
949 }
950
951 addrstr.append("*)");
952 addrstr.append(Cppyy::GetMethodSignature(method, false));
953 addrstr.append(") &");
954
955 addrstr.append(sfn.substr(0, sfn.find('(')));
956
957 gInterpreter->Calc(addrstr.c_str());
958 }
959
960 return (TCppFuncAddr_t)gInterpreter->FindSym(f->GetMangledName());
961}
962
963
964// handling of function argument buffer --------------------------------------
966{
967 return new Parameter[nargs];
968}
969
971{
972 delete [] (Parameter*)args;
973}
974
976{
977 return sizeof(Parameter);
978}
979
981{
982 return offsetof(Parameter, fTypeCode);
983}
984
985
986// scope reflection information ----------------------------------------------
988{
989// Test if this scope represents a namespace.
990 if (scope == GLOBAL_HANDLE)
991 return true;
992 TClassRef& cr = type_from_handle(scope);
993 if (cr.GetClass())
994 return cr->Property() & kIsNamespace;
995 return false;
996}
997
999{
1000// Test if this type may not be instantiated.
1001 TClassRef& cr = type_from_handle(klass);
1002 if (cr.GetClass())
1003 return cr->Property() & kIsAbstract;
1004 return false;
1005}
1006
1007bool Cppyy::IsEnum(const std::string& type_name)
1008{
1009 if (type_name.empty()) return false;
1010 std::string tn_short = TClassEdit::ShortType(type_name.c_str(), 1);
1011 if (tn_short.empty()) return false;
1012 return gInterpreter->ClassInfo_IsEnum(tn_short.c_str());
1013}
1014
1016{
1017// Test if this type is an aggregate type
1018 TClassRef& cr = type_from_handle(klass);
1019 if (cr.GetClass())
1020 return cr->ClassProperty() & kClassIsAggregate;
1021 return false;
1022}
1023
1025{
1026// Test if this type has a default constructor or is a "plain old data" type
1028 if (cr.GetClass())
1029 return cr->HasDefaultConstructor() || (cr->ClassProperty() & kClassIsAggregate);
1030 return true;
1031}
1032
1033// helpers for stripping scope names
1034static
1035std::string outer_with_template(const std::string& name)
1036{
1037// Cut down to the outer-most scope from <name>, taking proper care of templates.
1038 int tpl_open = 0;
1039 for (std::string::size_type pos = 0; pos < name.size(); ++pos) {
1040 std::string::value_type c = name[pos];
1041
1042 // count '<' and '>' to be able to skip template contents
1043 if (c == '<')
1044 ++tpl_open;
1045 else if (c == '>')
1046 --tpl_open;
1047
1048 // collect name up to "::"
1049 else if (tpl_open == 0 && \
1050 c == ':' && pos+1 < name.size() && name[pos+1] == ':') {
1051 // found the extend of the scope ... done
1052 return name.substr(0, pos-1);
1053 }
1054 }
1055
1056// whole name is apparently a single scope
1057 return name;
1058}
1059
1060static
1061std::string outer_no_template(const std::string& name)
1062{
1063// Cut down to the outer-most scope from <name>, drop templates
1064 std::string::size_type first_scope = name.find(':');
1065 if (first_scope == std::string::npos)
1066 return name.substr(0, name.find('<'));
1067 std::string::size_type first_templ = name.find('<');
1068 if (first_templ == std::string::npos)
1069 return name.substr(0, first_scope);
1070 return name.substr(0, std::min(first_templ, first_scope));
1071}
1072
1073#define FILL_COLL(type, filter) { \
1074 TIter itr{coll}; \
1075 type* obj = nullptr; \
1076 while ((obj = (type*)itr.Next())) { \
1077 const char* nm = obj->GetName(); \
1078 if (nm && nm[0] != '_' && !(obj->Property() & (filter))) { \
1079 if (gInitialNames.find(nm) == gInitialNames.end()) \
1080 cppnames.insert(nm); \
1081 }}}
1082
1083static inline
1084void cond_add(Cppyy::TCppScope_t scope, const std::string& ns_scope,
1085 std::set<std::string>& cppnames, const char* name, bool nofilter = false)
1086{
1087 if (!name || name[0] == '_' || strstr(name, ".h") != 0 || strncmp(name, "operator", 8) == 0)
1088 return;
1089
1090 if (scope == GLOBAL_HANDLE) {
1091 std::string to_add = outer_no_template(name);
1092 if ((nofilter || gInitialNames.find(to_add) == gInitialNames.end()) && !is_missclassified_stl(name))
1093 cppnames.insert(outer_no_template(name));
1094 } else if (scope == STD_HANDLE) {
1095 if (strncmp(name, "std::", 5) == 0) {
1096 name += 5;
1097#ifdef __APPLE__
1098 if (strncmp(name, "__1::", 5) == 0) name += 5;
1099#endif
1100 } else if (!is_missclassified_stl(name))
1101 return;
1102 cppnames.insert(outer_no_template(name));
1103 } else {
1104 if (strncmp(name, ns_scope.c_str(), ns_scope.size()) == 0)
1105 cppnames.insert(outer_with_template(name + ns_scope.size()));
1106 }
1107}
1108
1109void Cppyy::GetAllCppNames(TCppScope_t scope, std::set<std::string>& cppnames)
1110{
1111// Collect all known names of C++ entities under scope. This is useful for IDEs
1112// employing tab-completion, for example. Note that functions names need not be
1113// unique as they can be overloaded.
1114 TClassRef& cr = type_from_handle(scope);
1115 if (scope != GLOBAL_HANDLE && !(cr.GetClass() && cr->Property()))
1116 return;
1117
1118 std::string ns_scope = GetFinalName(scope);
1119 if (scope != GLOBAL_HANDLE) ns_scope += "::";
1120
1121// add existing values from read rootmap files if within this scope
1122 TCollection* coll = gInterpreter->GetMapfile()->GetTable();
1123 {
1124 TIter itr{coll};
1125 TEnvRec* ev = nullptr;
1126 while ((ev = (TEnvRec*)itr.Next())) {
1127 // TEnv contains rootmap entries and user-side rootmap files may be already
1128 // loaded on startup. Thus, filter on file name rather than load time.
1129 if (gRootSOs.find(ev->GetValue()) == gRootSOs.end())
1130 cond_add(scope, ns_scope, cppnames, ev->GetName(), true);
1131 }
1132 }
1133
1134// do we care about the class table or are the rootmap and list of types enough?
1135/*
1136 gClassTable->Init();
1137 const int N = gClassTable->Classes();
1138 for (int i = 0; i < N; ++i)
1139 cond_add(scope, ns_scope, cppnames, gClassTable->Next());
1140*/
1141
1142// any other types (e.g. that may have come from parsing headers)
1143 coll = gROOT->GetListOfTypes();
1144 {
1145 TIter itr{coll};
1146 TDataType* dt = nullptr;
1147 while ((dt = (TDataType*)itr.Next())) {
1148 if (!(dt->Property() & kIsFundamental)) {
1149 cond_add(scope, ns_scope, cppnames, dt->GetName());
1150 }
1151 }
1152 }
1153
1154// add functions
1155 coll = (scope == GLOBAL_HANDLE) ?
1156 gROOT->GetListOfGlobalFunctions() : cr->GetListOfMethods();
1157 {
1158 TIter itr{coll};
1159 TFunction* obj = nullptr;
1160 while ((obj = (TFunction*)itr.Next())) {
1161 const char* nm = obj->GetName();
1162 // skip templated functions, adding only the un-instantiated ones
1163 if (nm && nm[0] != '_' && strstr(nm, "<") == 0 && strncmp(nm, "operator", 8) != 0) {
1164 if (gInitialNames.find(nm) == gInitialNames.end())
1165 cppnames.insert(nm);
1166 }
1167 }
1168 }
1169
1170// add uninstantiated templates
1171 coll = (scope == GLOBAL_HANDLE) ?
1172 gROOT->GetListOfFunctionTemplates() : cr->GetListOfFunctionTemplates();
1174
1175// add (global) data members
1176 if (scope == GLOBAL_HANDLE) {
1177 coll = gROOT->GetListOfGlobals();
1179 } else {
1180 coll = cr->GetListOfDataMembers();
1182 coll = cr->GetListOfUsingDataMembers();
1184 }
1185
1186// add enums values only for user classes/namespaces
1187 if (scope != GLOBAL_HANDLE && scope != STD_HANDLE) {
1188 coll = cr->GetListOfEnums();
1190 }
1191
1192#ifdef __APPLE__
1193// special case for Apple, add version namespace '__1' entries to std
1194 if (scope == STD_HANDLE)
1195 GetAllCppNames(GetScope("std::__1"), cppnames);
1196#endif
1197}
1198
1199
1200// class reflection information ----------------------------------------------
1201std::vector<Cppyy::TCppScope_t> Cppyy::GetUsingNamespaces(TCppScope_t scope)
1202{
1203 std::vector<Cppyy::TCppScope_t> res;
1204 if (!IsNamespace(scope))
1205 return res;
1206
1207#ifdef __APPLE__
1208 if (scope == STD_HANDLE) {
1209 res.push_back(GetScope("__1"));
1210 return res;
1211 }
1212#endif
1213
1214 TClassRef& cr = type_from_handle(scope);
1215 if (!cr.GetClass() || !cr->GetClassInfo())
1216 return res;
1217
1218 const std::vector<std::string>& v = gInterpreter->GetUsingNamespaces(cr->GetClassInfo());
1219 res.reserve(v.size());
1220 for (const auto& uid : v) {
1221 Cppyy::TCppScope_t uscope = GetScope(uid);
1222 if (uscope) res.push_back(uscope);
1223 }
1224
1225 return res;
1226}
1227
1228
1229// class reflection information ----------------------------------------------
1231{
1232 if (klass == GLOBAL_HANDLE)
1233 return "";
1234 TClassRef& cr = type_from_handle(klass);
1235 std::string clName = cr->GetName();
1236// TODO: why is this template splitting needed?
1237 std::string::size_type pos = clName.substr(0, clName.find('<')).rfind("::");
1238 if (pos != std::string::npos)
1239 return clName.substr(pos+2, std::string::npos);
1240 return clName;
1241}
1242
1244{
1245 if (klass == GLOBAL_HANDLE)
1246 return "";
1247 TClassRef& cr = type_from_handle(klass);
1248 if (cr.GetClass()) {
1249 std::string name = cr->GetName();
1251 return std::string("std::")+cr->GetName();
1252 return cr->GetName();
1253 }
1254 return "";
1255}
1256
1258{
1259 TClassRef& cr = type_from_handle(klass);
1260 if (!cr.GetClass())
1261 return false;
1262
1263 TFunction* f = cr->GetMethod(("~"+GetFinalName(klass)).c_str(), "");
1264 if (f && (f->Property() & kIsVirtual))
1265 return true;
1266
1267 return false;
1268}
1269
1271{
1272 int is_complex = 1;
1273 size_t nbases = 0;
1274
1275 TClassRef& cr = type_from_handle(klass);
1276 if (cr.GetClass() && cr->GetListOfBases() != 0)
1277 nbases = GetNumBases(klass);
1278
1279 if (1 < nbases)
1280 is_complex = 1;
1281 else if (nbases == 0)
1282 is_complex = 0;
1283 else { // one base class only
1284 TBaseClass* base = (TBaseClass*)cr->GetListOfBases()->At(0);
1285 if (base->Property() & kIsVirtualBase)
1286 is_complex = 1; // TODO: verify; can be complex, need not be.
1287 else
1288 is_complex = HasComplexHierarchy(GetScope(base->GetName()));
1289 }
1290
1291 return is_complex;
1292}
1293
1295{
1296// Get the total number of base classes that this class has.
1297 TClassRef& cr = type_from_handle(klass);
1298 if (cr.GetClass() && cr->GetListOfBases() != 0)
1299 return (TCppIndex_t)cr->GetListOfBases()->GetSize();
1300 return (TCppIndex_t)0;
1301}
1302
1303////////////////////////////////////////////////////////////////////////////////
1304/// \fn Cppyy::TCppIndex_t GetLongestInheritancePath(TClass *klass)
1305/// \brief Retrieve number of base classes in the longest branch of the
1306/// inheritance tree of the input class.
1307/// \param[in] klass The class to start the retrieval process from.
1308///
1309/// This is a helper function for Cppyy::GetNumBasesLongestBranch.
1310/// Given an inheritance tree, the function assigns weight 1 to each class that
1311/// has at least one base. Starting from the input class, the function is
1312/// called recursively on all the bases. For each base the return value is one
1313/// (the weight of the base itself) plus the maximum value retrieved for their
1314/// bases in turn. For example, given the following inheritance tree:
1315///
1316/// ~~~{.cpp}
1317/// class A {}; class B: public A {};
1318/// class X {}; class Y: public X {}; class Z: public Y {};
1319/// class C: public B, Z {};
1320/// ~~~
1321///
1322/// calling this function on an instance of `C` will return 3, the steps
1323/// required to go from C to X.
1325{
1326
1327 auto directbases = klass->GetListOfBases();
1328 if (!directbases) {
1329 // This is a leaf with no bases
1330 return 0;
1331 }
1332 auto ndirectbases = directbases->GetSize();
1333 if (ndirectbases == 0) {
1334 // This is a leaf with no bases
1335 return 0;
1336 } else {
1337 // If there is at least one direct base
1338 std::vector<Cppyy::TCppIndex_t> nbases_branches;
1339 nbases_branches.reserve(ndirectbases);
1340
1341 // Traverse all direct bases of the current class and call the function
1342 // recursively
1343 for (auto baseclass : TRangeDynCast<TBaseClass>(directbases)) {
1344 if (!baseclass)
1345 continue;
1346 if (auto baseclass_tclass = baseclass->GetClassPointer()) {
1347 nbases_branches.emplace_back(GetLongestInheritancePath(baseclass_tclass));
1348 }
1349 }
1350
1351 // Get longest path among the direct bases of the current class
1352 auto longestbranch = std::max_element(std::begin(nbases_branches), std::end(nbases_branches));
1353
1354 // Add 1 to include the current class in the count
1355 return 1 + *longestbranch;
1356 }
1357}
1358
1359////////////////////////////////////////////////////////////////////////////////
1360/// \fn Cppyy::TCppIndex_t Cppyy::GetNumBasesLongestBranch(TCppType_t klass)
1361/// \brief Retrieve number of base classes in the longest branch of the
1362/// inheritance tree.
1363/// \param[in] klass The class to start the retrieval process from.
1364///
1365/// The function converts the input class to a `TClass *` and calls
1366/// GetLongestInheritancePath.
1368{
1369
1370 const auto &cr = type_from_handle(klass);
1371
1372 if (auto klass_tclass = cr.GetClass()) {
1373 return GetLongestInheritancePath(klass_tclass);
1374 }
1375
1376 // In any other case, return zero
1377 return 0;
1378}
1379
1381{
1382 TClassRef& cr = type_from_handle(klass);
1383 return ((TBaseClass*)cr->GetListOfBases()->At((int)ibase))->GetName();
1384}
1385
1387{
1388 if (derived == base)
1389 return true;
1390 TClassRef& derived_type = type_from_handle(derived);
1391 TClassRef& base_type = type_from_handle(base);
1392 return derived_type->GetBaseClass(base_type) != 0;
1393}
1394
1396{
1397 TClassRef& cr = type_from_handle(klass);
1398 const std::string& tn = cr->GetName();
1399 if (gSmartPtrTypes.find(tn.substr(0, tn.find("<"))) != gSmartPtrTypes.end())
1400 return true;
1401 return false;
1402}
1403
1405 const std::string& tname, TCppType_t* raw, TCppMethod_t* deref)
1406{
1407 const std::string& rn = ResolveName(tname);
1408 if (gSmartPtrTypes.find(rn.substr(0, rn.find("<"))) != gSmartPtrTypes.end()) {
1409 if (!raw && !deref) return true;
1410
1411 TClassRef& cr = type_from_handle(GetScope(tname));
1412 if (cr.GetClass()) {
1413 TFunction* func = cr->GetMethod("operator->", "");
1414 if (!func) {
1415 gInterpreter->UpdateListOfMethods(cr.GetClass());
1416 func = cr->GetMethod("operator->", "");
1417 }
1418 if (func) {
1419 if (deref) *deref = (TCppMethod_t)new_CallWrapper(func);
1420 if (raw) *raw = GetScope(TClassEdit::ShortType(
1421 func->GetReturnTypeNormalizedName().c_str(), 1));
1422 return (!deref || *deref) && (!raw || *raw);
1423 }
1424 }
1425 }
1426
1427 return false;
1428}
1429
1430void Cppyy::AddSmartPtrType(const std::string& type_name)
1431{
1432 gSmartPtrTypes.insert(ResolveName(type_name));
1433}
1434
1435void Cppyy::AddTypeReducer(const std::string& /*reducable*/, const std::string& /*reduced*/)
1436{
1437 // This function is deliberately left empty, because it is not used in
1438 // PyROOT, and synchronizing it with cppyy-backend upstream would require
1439 // patches to ROOT meta.
1440}
1441
1442
1443// type offsets --------------------------------------------------------------
1445 TCppObject_t address, int direction, bool rerror)
1446{
1447// calculate offsets between declared and actual type, up-cast: direction > 0; down-cast: direction < 0
1448 if (derived == base || !(base && derived))
1449 return (ptrdiff_t)0;
1450
1451 TClassRef& cd = type_from_handle(derived);
1452 TClassRef& cb = type_from_handle(base);
1453
1454 if (!cd.GetClass() || !cb.GetClass())
1455 return (ptrdiff_t)0;
1456
1457 ptrdiff_t offset = -1;
1458 if (!(cd->GetClassInfo() && cb->GetClassInfo())) { // gInterpreter requirement
1459 // would like to warn, but can't quite determine error from intentional
1460 // hiding by developers, so only cover the case where we really should have
1461 // had a class info, but apparently don't:
1462 if (cd->IsLoaded()) {
1463 // warn to allow diagnostics
1464 std::ostringstream msg;
1465 msg << "failed offset calculation between " << cb->GetName() << " and " << cd->GetName();
1466 // TODO: propagate this warning to caller w/o use of Python C-API
1467 // PyErr_Warn(PyExc_RuntimeWarning, const_cast<char*>(msg.str().c_str()));
1468 std::cerr << "Warning: " << msg.str() << '\n';
1469 }
1470
1471 // return -1 to signal caller NOT to apply offset
1472 return rerror ? (ptrdiff_t)offset : 0;
1473 }
1474
1475 offset = gInterpreter->ClassInfo_GetBaseOffset(
1476 cd->GetClassInfo(), cb->GetClassInfo(), (void*)address, direction > 0);
1477 if (offset == -1) // Cling error, treat silently
1478 return rerror ? (ptrdiff_t)offset : 0;
1479
1480 return (ptrdiff_t)(direction < 0 ? -offset : offset);
1481}
1482
1483
1484// method/function reflection information ------------------------------------
1486{
1487 if (!accept_namespace && IsNamespace(scope))
1488 return (TCppIndex_t)0; // enforce lazy
1489
1490 if (scope == GLOBAL_HANDLE)
1491 return gROOT->GetListOfGlobalFunctions(true)->GetSize();
1492
1493 TClassRef& cr = type_from_handle(scope);
1494 if (cr.GetClass() && cr->GetListOfMethods(true)) {
1495 Cppyy::TCppIndex_t nMethods = (TCppIndex_t)cr->GetListOfMethods(false)->GetSize();
1496 if (nMethods == (TCppIndex_t)0) {
1497 std::string clName = GetScopedFinalName(scope);
1498 if (clName.find('<') != std::string::npos) {
1499 // chicken-and-egg problem: TClass does not know about methods until
1500 // instantiation, so force it
1501 std::ostringstream stmt;
1502 stmt << "template class " << clName << ";";
1503 gInterpreter->Declare(stmt.str().c_str()/*, silent = true*/);
1504
1505 // now reload the methods
1506 return (TCppIndex_t)cr->GetListOfMethods(true)->GetSize();
1507 }
1508 }
1509 return nMethods;
1510 }
1511
1512 return (TCppIndex_t)0; // unknown class?
1513}
1514
1515std::vector<Cppyy::TCppIndex_t> Cppyy::GetMethodIndicesFromName(
1516 TCppScope_t scope, const std::string& name)
1517{
1518 std::vector<TCppIndex_t> indices;
1519 TClassRef& cr = type_from_handle(scope);
1520 if (cr.GetClass()) {
1521 gInterpreter->UpdateListOfMethods(cr.GetClass());
1522 int imeth = 0;
1523 TFunction* func = nullptr;
1524 TIter next(cr->GetListOfMethods());
1525 while ((func = (TFunction*)next())) {
1526 if (match_name(name, func->GetName())) {
1527 if (func->Property() & kIsPublic)
1528 indices.push_back((TCppIndex_t)imeth);
1529 }
1530 ++imeth;
1531 }
1532 } else if (scope == GLOBAL_HANDLE) {
1533 TCollection* funcs = gROOT->GetListOfGlobalFunctions(true);
1534
1535 // tickle deserialization
1536 if (!funcs->FindObject(name.c_str()))
1537 return indices;
1538
1539 TFunction* func = nullptr;
1540 TIter ifunc(funcs);
1541 while ((func = (TFunction*)ifunc.Next())) {
1542 if (match_name(name, func->GetName()))
1543 indices.push_back((TCppIndex_t)new_CallWrapper(func));
1544 }
1545 }
1546
1547 return indices;
1548}
1549
1551{
1552 TClassRef& cr = type_from_handle(scope);
1553 if (cr.GetClass()) {
1554 TFunction* f = (TFunction*)cr->GetListOfMethods(false)->At((int)idx);
1555 if (f) return (Cppyy::TCppMethod_t)new_CallWrapper(f);
1556 return (Cppyy::TCppMethod_t)nullptr;
1557 }
1558
1559 assert(klass == (Cppyy::TCppType_t)GLOBAL_HANDLE);
1560 return (Cppyy::TCppMethod_t)idx;
1561}
1562
1564{
1565 if (method) {
1566 const std::string& name = ((CallWrapper*)method)->fName;
1567
1568 if (name.compare(0, 8, "operator") != 0)
1569 // strip template instantiation part, if any
1570 return name.substr(0, name.find('<'));
1571 return name;
1572 }
1573 return "<unknown>";
1574}
1575
1577{
1578 if (method) {
1579 std::string name = ((CallWrapper*)method)->fName;
1580 name.erase(std::remove(name.begin(), name.end(), ' '), name.end());
1581 return name;
1582 }
1583 return "<unknown>";
1584}
1585
1587{
1588 if (method)
1589 return m2f(method)->GetMangledName();
1590 return "<unknown>";
1591}
1592
1594{
1595 if (method) {
1596 TFunction* f = m2f(method);
1597 if (f->ExtraProperty() & kIsConstructor)
1598 return "constructor";
1599 std::string restype = f->GetReturnTypeName();
1600 // TODO: this is ugly, but we can't use GetReturnTypeName() for ostreams
1601 // and maybe others, whereas GetReturnTypeNormalizedName() has proven to
1602 // be save in all cases (Note: 'int8_t' covers 'int8_t' and 'uint8_t')
1603 if (restype.find("int8_t") != std::string::npos)
1604 return restype;
1605 restype = f->GetReturnTypeNormalizedName();
1606 if (restype == "(lambda)") {
1607 std::ostringstream s;
1608 // TODO: what if there are parameters to the lambda?
1609 s << "__cling_internal::FT<decltype("
1610 << GetMethodFullName(method) << "(";
1611 for (Cppyy::TCppIndex_t i = 0; i < Cppyy::GetMethodNumArgs(method); ++i) {
1612 if (i != 0) s << ", ";
1613 s << Cppyy::GetMethodArgType(method, i) << "{}";
1614 }
1615 s << "))>::F";
1616 TClass* cl = TClass::GetClass(s.str().c_str());
1617 if (cl) return cl->GetName();
1618 // TODO: signal some type of error (or should that be upstream?
1619 }
1620 return restype;
1621 }
1622 return "<unknown>";
1623}
1624
1626{
1627 if (method)
1628 return m2f(method)->GetNargs();
1629 return 0;
1630}
1631
1633{
1634 if (method) {
1635 TFunction* f = m2f(method);
1636 return (TCppIndex_t)(f->GetNargs() - f->GetNargsOpt());
1637 }
1638 return (TCppIndex_t)0;
1639}
1640
1642{
1643 if (method) {
1644 TFunction* f = m2f(method);
1645 TMethodArg* arg = (TMethodArg*)f->GetListOfMethodArgs()->At((int)iarg);
1646 return arg->GetName();
1647 }
1648 return "<unknown>";
1649}
1650
1652{
1653 if (method) {
1654 TFunction* f = m2f(method);
1655 TMethodArg* arg = (TMethodArg*)f->GetListOfMethodArgs()->At((int)iarg);
1656 return arg->GetTypeNormalizedName();
1657 }
1658 return "<unknown>";
1659}
1660
1662{
1663 if (method) {
1664 TFunction* f = m2f(method);
1665 TMethodArg* arg = (TMethodArg *)f->GetListOfMethodArgs()->At((int)iarg);
1666 void *argqtp = gInterpreter->TypeInfo_QualTypePtr(arg->GetTypeInfo());
1667
1668 TypeInfo_t *reqti = gInterpreter->TypeInfo_Factory(req_type.c_str());
1669 void *reqqtp = gInterpreter->TypeInfo_QualTypePtr(reqti);
1670
1671 // This scoring is not based on any particular rules
1672 if (gInterpreter->IsSameType(argqtp, reqqtp))
1673 return 0; // Best match
1674 else if ((gInterpreter->IsSignedIntegerType(argqtp) && gInterpreter->IsSignedIntegerType(reqqtp)) ||
1675 (gInterpreter->IsUnsignedIntegerType(argqtp) && gInterpreter->IsUnsignedIntegerType(reqqtp)) ||
1676 (gInterpreter->IsFloatingType(argqtp) && gInterpreter->IsFloatingType(reqqtp)))
1677 return 1;
1678 else if ((gInterpreter->IsSignedIntegerType(argqtp) && gInterpreter->IsUnsignedIntegerType(reqqtp)) ||
1679 (gInterpreter->IsFloatingType(argqtp) && gInterpreter->IsUnsignedIntegerType(reqqtp)))
1680 return 2;
1681 else if ((gInterpreter->IsIntegerType(argqtp) && gInterpreter->IsIntegerType(reqqtp)))
1682 return 3;
1683 else if ((gInterpreter->IsVoidPointerType(argqtp) && gInterpreter->IsPointerType(reqqtp)))
1684 return 4;
1685 else
1686 return 10; // Penalize heavily for no possible match
1687 }
1688 return INT_MAX; // Method is not valid
1689}
1690
1692{
1693 if (method) {
1694 TFunction* f = m2f(method);
1695 TMethodArg* arg = (TMethodArg*)f->GetListOfMethodArgs()->At((int)iarg);
1696 const char* def = arg->GetDefault();
1697 if (def)
1698 return def;
1699 }
1700
1701 return "";
1702}
1703
1704std::string Cppyy::GetMethodSignature(TCppMethod_t method, bool show_formalargs, TCppIndex_t maxargs)
1705{
1706 TFunction* f = m2f(method);
1707 if (f) {
1708 std::ostringstream sig;
1709 sig << "(";
1710 int nArgs = f->GetNargs();
1711 if (maxargs != (TCppIndex_t)-1) nArgs = std::min(nArgs, (int)maxargs);
1712 for (int iarg = 0; iarg < nArgs; ++iarg) {
1713 TMethodArg* arg = (TMethodArg*)f->GetListOfMethodArgs()->At(iarg);
1714 sig << arg->GetFullTypeName();
1715 if (show_formalargs) {
1716 const char* argname = arg->GetName();
1717 if (argname && argname[0] != '\0') sig << " " << argname;
1718 const char* defvalue = arg->GetDefault();
1719 if (defvalue && defvalue[0] != '\0') sig << " = " << defvalue;
1720 }
1721 if (iarg != nArgs-1) sig << (show_formalargs ? ", " : ",");
1722 }
1723 sig << ")";
1724 return sig.str();
1725 }
1726 return "<unknown>";
1727}
1728
1729std::string Cppyy::GetMethodPrototype(TCppScope_t scope, TCppMethod_t method, bool show_formalargs)
1730{
1731 std::string scName = GetScopedFinalName(scope);
1732 TFunction* f = m2f(method);
1733 if (f) {
1734 std::ostringstream sig;
1735 sig << f->GetReturnTypeName() << " "
1736 << scName << "::" << f->GetName();
1737 sig << GetMethodSignature(method, show_formalargs);
1738 return sig.str();
1739 }
1740 return "<unknown>";
1741}
1742
1744{
1745 if (method) {
1746 TFunction* f = m2f(method);
1747 return f->Property() & kIsConstMethod;
1748 }
1749 return false;
1750}
1751
1753{
1754 if (!accept_namespace && IsNamespace(scope))
1755 return (TCppIndex_t)0; // enforce lazy
1756
1757 if (scope == GLOBAL_HANDLE) {
1758 TCollection* coll = gROOT->GetListOfFunctionTemplates();
1759 if (coll) return (TCppIndex_t)coll->GetSize();
1760 } else {
1761 TClassRef& cr = type_from_handle(scope);
1762 if (cr.GetClass()) {
1763 TCollection* coll = cr->GetListOfFunctionTemplates(true);
1764 if (coll) return (TCppIndex_t)coll->GetSize();
1765 }
1766 }
1767
1768// failure ...
1769 return (TCppIndex_t)0;
1770}
1771
1773{
1774 if (scope == (TCppScope_t)GLOBAL_HANDLE)
1775 return ((THashList*)gROOT->GetListOfFunctionTemplates())->At((int)imeth)->GetName();
1776 else {
1777 TClassRef& cr = type_from_handle(scope);
1778 if (cr.GetClass())
1779 return cr->GetListOfFunctionTemplates(false)->At((int)imeth)->GetName();
1780 }
1781
1782// failure ...
1783 assert(!"should not be called unless GetNumTemplatedMethods() succeeded");
1784 return "";
1785}
1786
1788{
1789 if (scope == (TCppScope_t)GLOBAL_HANDLE)
1790 return false;
1791
1792 TClassRef& cr = type_from_handle(scope);
1793 if (cr.GetClass()) {
1795 return f->ExtraProperty() & kIsConstructor;
1796 }
1797
1798 return false;
1799}
1800
1801bool Cppyy::ExistsMethodTemplate(TCppScope_t scope, const std::string& name)
1802{
1803 if (scope == (TCppScope_t)GLOBAL_HANDLE)
1804 return (bool)gROOT->GetFunctionTemplate(name.c_str());
1805 else {
1806 TClassRef& cr = type_from_handle(scope);
1807 if (cr.GetClass())
1808 return (bool)cr->GetFunctionTemplate(name.c_str());
1809 }
1810
1811// failure ...
1812 return false;
1813}
1814
1816{
1817 TClassRef& cr = type_from_handle(scope);
1818 if (cr.GetClass()) {
1819 TFunction* f = (TFunction*)cr->GetListOfMethods(false)->At((int)idx);
1820 if (f && strstr(f->GetName(), "<")) return true;
1821 return false;
1822 }
1823
1824 assert(scope == (Cppyy::TCppType_t)GLOBAL_HANDLE);
1825 if (((CallWrapper*)idx)->fName.find('<') != std::string::npos) return true;
1826 return false;
1827}
1828
1829// helpers for Cppyy::GetMethodTemplate()
1830static std::map<TDictionary::DeclId_t, CallWrapper*> gMethodTemplates;
1831
1833 TCppScope_t scope, const std::string& name, const std::string& proto)
1834{
1835// There is currently no clean way of extracting a templated method out of ROOT/meta
1836// for a variety of reasons, none of them fundamental. The game played below is to
1837// first get any pre-existing functions already managed by ROOT/meta, but if that fails,
1838// to do an explicit lookup that ignores the prototype (i.e. the full name should be
1839// enough), and finally to ignore the template arguments part of the name as this fails
1840// in cling if there are default parameters.
1841// It would be possible to get the prototype from the created functions and use that to
1842// do a new lookup, after which ROOT/meta will manage the function. However, neither
1843// TFunction::GetPrototype() nor TFunction::GetSignature() is of the proper form, so
1844// we'll/ manage the new TFunctions instead and will assume that they are cached on the
1845// calling side to prevent multiple creations.
1846 TFunction* func = nullptr; ClassInfo_t* cl = nullptr;
1847 if (scope == (cppyy_scope_t)GLOBAL_HANDLE) {
1848 func = gROOT->GetGlobalFunctionWithPrototype(name.c_str(), proto.c_str());
1849 if (func && name.back() == '>' && name != func->GetName())
1850 func = nullptr; // happens if implicit conversion matches the overload
1851 } else {
1852 TClassRef& cr = type_from_handle(scope);
1853 if (cr.GetClass()) {
1854 func = cr->GetMethodWithPrototype(name.c_str(), proto.c_str());
1855 if (!func) {
1856 cl = cr->GetClassInfo();
1857 // try base classes to cover a common 'using' case (TODO: this is stupid and misses
1858 // out on base classes; fix that with improved access to Cling)
1859 TCppIndex_t nbases = GetNumBases(scope);
1860 for (TCppIndex_t i = 0; i < nbases; ++i) {
1861 TClassRef& base = type_from_handle(GetScope(GetBaseName(scope, i)));
1862 if (base.GetClass()) {
1863 func = base->GetMethodWithPrototype(name.c_str(), proto.c_str());
1864 if (func) break;
1865 }
1866 }
1867 }
1868 }
1869 }
1870
1871 if (!func && name.back() == '>' && (cl || scope == (cppyy_scope_t)GLOBAL_HANDLE)) {
1872 // try again, ignoring proto in case full name is complete template
1873 auto declid = gInterpreter->GetFunction(cl, name.c_str());
1874 if (declid) {
1875 auto existing = gMethodTemplates.find(declid);
1876 if (existing == gMethodTemplates.end()) {
1877 auto cw = new_CallWrapper(declid, name);
1878 existing = gMethodTemplates.insert(std::make_pair(declid, cw)).first;
1879 }
1880 return (TCppMethod_t)existing->second;
1881 }
1882 }
1883
1884 if (func) {
1885 // make sure we didn't match a non-templated overload
1886 if (func->ExtraProperty() & kIsTemplateSpec)
1887 return (TCppMethod_t)new_CallWrapper(func);
1888
1889 // disregard this non-templated method as it will be considered when appropriate
1890 return (TCppMethod_t)nullptr;
1891 }
1892
1893// try again with template arguments removed from name, if applicable
1894 if (name.back() == '>') {
1895 auto pos = name.find('<');
1896 if (pos != std::string::npos) {
1897 TCppMethod_t cppmeth = GetMethodTemplate(scope, name.substr(0, pos), proto);
1898 if (cppmeth) {
1899 // allow if requested template names match up to the result
1900 const std::string& alt = GetMethodFullName(cppmeth);
1901 if (name.size() < alt.size() && alt.find('<') == pos) {
1902 const std::string& partial = name.substr(pos, name.size()-1-pos);
1903 if (strncmp(partial.c_str(), alt.substr(pos, alt.size()-1-pos).c_str(), partial.size()) == 0)
1904 return cppmeth;
1905 }
1906 }
1907 }
1908 }
1909
1910// failure ...
1911 return (TCppMethod_t)nullptr;
1912}
1913
1914static inline
1915std::string type_remap(const std::string& n1, const std::string& n2)
1916{
1917// Operator lookups of (C++ string, Python str) should succeeded, for the combos of
1918// string/str, wstring/str, string/unicode and wstring/unicode; since C++ does not have a
1919// operator+(std::string, std::wstring), we'll have to look up the same type and rely on
1920// the converters in CPyCppyy/_cppyy.
1921 if (n1 == "str") {
1922 if (n2 == "std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> >")
1923 return n2; // match like for like
1924 return "std::string"; // probably best bet
1925 } else if (n1 == "float")
1926 return "double"; // debatable, but probably intended
1927 return n1;
1928}
1929
1931 TCppType_t scope, const std::string& lc, const std::string& rc, const std::string& opname)
1932{
1933// Find a global operator function with a matching signature; prefer by-ref, but
1934// fall back on by-value if that fails.
1935 std::string lcname1 = TClassEdit::CleanType(lc.c_str());
1936 const std::string& rcname = rc.empty() ? rc : type_remap(TClassEdit::CleanType(rc.c_str()), lcname1);
1937 const std::string& lcname = type_remap(lcname1, rcname);
1938
1939 std::string proto = lcname + "&" + (rc.empty() ? rc : (", " + rcname + "&"));
1940 if (scope == (cppyy_scope_t)GLOBAL_HANDLE) {
1941 TFunction* func = gROOT->GetGlobalFunctionWithPrototype(opname.c_str(), proto.c_str());
1942 if (func) return (TCppIndex_t)new_CallWrapper(func);
1943 proto = lcname + (rc.empty() ? rc : (", " + rcname));
1944 func = gROOT->GetGlobalFunctionWithPrototype(opname.c_str(), proto.c_str());
1945 if (func) return (TCppIndex_t)new_CallWrapper(func);
1946 } else {
1947 TClassRef& cr = type_from_handle(scope);
1948 if (cr.GetClass()) {
1949 TFunction* func = cr->GetMethodWithPrototype(opname.c_str(), proto.c_str());
1950 if (func) return (TCppIndex_t)cr->GetListOfMethods()->IndexOf(func);
1951 proto = lcname + (rc.empty() ? rc : (", " + rcname));
1952 func = cr->GetMethodWithPrototype(opname.c_str(), proto.c_str());
1953 if (func) return (TCppIndex_t)cr->GetListOfMethods()->IndexOf(func);
1954 }
1955 }
1956
1957// failure ...
1958 return (TCppIndex_t)-1;
1959}
1960
1961// method properties ---------------------------------------------------------
1963{
1964 if (method) {
1965 TFunction* f = m2f(method);
1966 return f->Property() & kIsPublic;
1967 }
1968 return false;
1969}
1970
1972{
1973 if (method) {
1974 TFunction* f = m2f(method);
1975 return f->Property() & kIsProtected;
1976 }
1977 return false;
1978}
1979
1981{
1982 if (method) {
1983 TFunction* f = m2f(method);
1984 return f->ExtraProperty() & kIsConstructor;
1985 }
1986 return false;
1987}
1988
1990{
1991 if (method) {
1992 TFunction* f = m2f(method);
1993 return f->ExtraProperty() & kIsDestructor;
1994 }
1995 return false;
1996}
1997
1999{
2000 if (method) {
2001 TFunction* f = m2f(method);
2002 return f->Property() & kIsStatic;
2003 }
2004 return false;
2005}
2006
2007// data member reflection information ----------------------------------------
2009{
2010 if (!accept_namespace && IsNamespace(scope))
2011 return (TCppIndex_t)0; // enforce lazy
2012
2013 if (scope == GLOBAL_HANDLE)
2014 return gROOT->GetListOfGlobals(true)->GetSize();
2015
2016 TClassRef& cr = type_from_handle(scope);
2017 if (cr.GetClass() && cr->GetListOfDataMembers())
2018 return cr->GetListOfDataMembers()->GetSize();
2019
2020 return (TCppIndex_t)0; // unknown class?
2021}
2022
2024{
2025 if (!cr.GetClass() || !cr->GetListOfDataMembers())
2026 return nullptr;
2027
2028 int numDMs = cr->GetListOfDataMembers()->GetSize();
2029 if ((int)idata < numDMs)
2030 return (TDataMember*)cr->GetListOfDataMembers()->At((int)idata);
2031 return (TDataMember*)cr->GetListOfUsingDataMembers()->At((int)idata - numDMs);
2032}
2033
2035{
2036 TClassRef& cr = type_from_handle(scope);
2037 if (cr.GetClass()) {
2038 TDataMember *m = GetDataMemberByIndex(cr, (int)idata);
2039 return m->GetName();
2040 }
2041 assert(scope == GLOBAL_HANDLE);
2042 TGlobal* gbl = g_globalvars[idata];
2043 return gbl->GetName();
2044}
2045
2047{
2048 if (scope == GLOBAL_HANDLE) {
2049 TGlobal* gbl = g_globalvars[idata];
2050 std::string fullType = gbl->GetFullTypeName();
2051
2052 if ((int)gbl->GetArrayDim()) {
2053 std::ostringstream s;
2054 for (int i = 0; i < (int)gbl->GetArrayDim(); ++i)
2055 s << '[' << gbl->GetMaxIndex(i) << ']';
2056 fullType.append(s.str());
2057 }
2058 return fullType;
2059 }
2060
2061 TClassRef& cr = type_from_handle(scope);
2062 if (cr.GetClass()) {
2063 TDataMember* m = GetDataMemberByIndex(cr, (int)idata);
2064 // TODO: fix this upstream. Usually, we want m->GetFullTypeName(), because it does
2065 // not resolve typedefs, but it looses scopes for inner classes/structs, so in that
2066 // case m->GetTrueTypeName() should be used (this also cleans up the cases where
2067 // the "full type" retains spurious "struct" or "union" in the name).
2068 std::string fullType = m->GetFullTypeName();
2069 if (fullType != m->GetTrueTypeName()) {
2070 const std::string& trueName = m->GetTrueTypeName();
2071 if (fullType.find("::") == std::string::npos && trueName.find("::") != std::string::npos)
2072 fullType = trueName;
2073 }
2074
2075 if ((int)m->GetArrayDim()) {
2076 std::ostringstream s;
2077 for (int i = 0; i < (int)m->GetArrayDim(); ++i)
2078 s << '[' << m->GetMaxIndex(i) << ']';
2079 fullType.append(s.str());
2080 }
2081 return fullType;
2082 }
2083
2084 return "<unknown>";
2085}
2086
2088{
2089 if (scope == GLOBAL_HANDLE) {
2090 TGlobal* gbl = g_globalvars[idata];
2091 if (!gbl->GetAddress() || gbl->GetAddress() == (void*)-1) {
2092 // CLING WORKAROUND: make sure variable is loaded
2093 intptr_t addr = (intptr_t)gInterpreter->ProcessLine((std::string("&")+gbl->GetName()+";").c_str());
2094 if (gbl->GetAddress() && gbl->GetAddress() != (void*)-1)
2095 return (intptr_t)gbl->GetAddress(); // now loaded!
2096 return addr; // last resort ...
2097 }
2098 return (intptr_t)gbl->GetAddress();
2099 }
2100
2101 TClassRef& cr = type_from_handle(scope);
2102 if (cr.GetClass()) {
2103 TDataMember* m = GetDataMemberByIndex(cr, (int)idata);
2104 // CLING WORKAROUND: the following causes templates to be instantiated first within the proper
2105 // scope, making the lookup succeed and preventing spurious duplicate instantiations later. Also,
2106 // if the variable is not yet loaded, pull it in through gInterpreter.
2107 if (m->Property() & kIsStatic) {
2108 if (strchr(cr->GetName(), '<'))
2109 gInterpreter->ProcessLine(((std::string)cr->GetName()+"::"+m->GetName()+";").c_str());
2110 if ((intptr_t)m->GetOffsetCint() == (intptr_t)-1)
2111 return (intptr_t)gInterpreter->ProcessLine((std::string("&")+cr->GetName()+"::"+m->GetName()+";").c_str());
2112 }
2113 return (intptr_t)m->GetOffsetCint(); // yes, CINT (GetOffset() is both wrong
2114 // and caches that wrong result!
2115 }
2116
2117 return (intptr_t)-1;
2118}
2119
2121{
2122 if (scope == GLOBAL_HANDLE) {
2123 TGlobal* gb = (TGlobal*)gROOT->GetListOfGlobals(false /* load */)->FindObject(name.c_str());
2124 if (!gb) gb = (TGlobal*)gROOT->GetListOfGlobals(true /* load */)->FindObject(name.c_str());
2125 if (!gb) {
2126 // some enums are not loaded as they are not considered part of
2127 // the global scope, but of the enum scope; get them w/o checking
2128 TDictionary::DeclId_t did = gInterpreter->GetDataMember(nullptr, name.c_str());
2129 if (did) {
2130 DataMemberInfo_t* t = gInterpreter->DataMemberInfo_Factory(did, nullptr);
2131 ((TListOfDataMembers*)gROOT->GetListOfGlobals())->Get(t, true);
2132 gb = (TGlobal*)gROOT->GetListOfGlobals(false /* load */)->FindObject(name.c_str());
2133 }
2134 }
2135
2136 if (gb && strcmp(gb->GetFullTypeName(), "(lambda)") == 0) {
2137 // lambdas use a compiler internal closure type, so we wrap
2138 // them, then return the wrapper's type
2139 // TODO: this current leaks the std::function; also, if possible,
2140 // should instantiate through TClass rather then ProcessLine
2141 std::ostringstream s;
2142 s << "auto __cppyy_internal_wrap_" << name << " = "
2143 "new __cling_internal::FT<decltype(" << name << ")>::F"
2144 "{" << name << "};";
2145 gInterpreter->ProcessLine(s.str().c_str());
2146 TGlobal* wrap = (TGlobal*)gROOT->GetListOfGlobals(true)->FindObject(
2147 ("__cppyy_internal_wrap_"+name).c_str());
2148 if (wrap && wrap->GetAddress()) gb = wrap;
2149 }
2150
2151 if (gb) {
2152 // TODO: do we ever need a reverse lookup?
2153 g_globalvars.push_back(gb);
2154 return TCppIndex_t(g_globalvars.size() - 1);
2155 }
2156
2157 } else {
2158 TClassRef& cr = type_from_handle(scope);
2159 if (cr.GetClass()) {
2160 TDataMember* dm =
2162 // TODO: turning this into an index is silly ...
2163 if (dm) return (TCppIndex_t)cr->GetListOfDataMembers()->IndexOf(dm);
2165 if (dm)
2166 return (TCppIndex_t)cr->GetListOfDataMembers()->IndexOf(dm)
2167 + cr->GetListOfDataMembers()->GetSize();
2168 }
2169 }
2170
2171 return (TCppIndex_t)-1;
2172}
2173
2174
2175// data member properties ----------------------------------------------------
2177{
2178 if (scope == GLOBAL_HANDLE)
2179 return true;
2180 TClassRef& cr = type_from_handle(scope);
2181 if (cr->Property() & kIsNamespace)
2182 return true;
2183 TDataMember* m = GetDataMemberByIndex(cr, (int)idata);
2184 return m->Property() & kIsPublic;
2185}
2186
2188{
2189 if (scope == GLOBAL_HANDLE)
2190 return true;
2191 TClassRef& cr = type_from_handle(scope);
2192 if (cr->Property() & kIsNamespace)
2193 return true;
2194 TDataMember* m = GetDataMemberByIndex(cr, (int)idata);
2195 return m->Property() & kIsProtected;
2196}
2197
2199{
2200 if (scope == GLOBAL_HANDLE)
2201 return true;
2202 TClassRef& cr = type_from_handle(scope);
2203 if (cr->Property() & kIsNamespace)
2204 return true;
2205 TDataMember* m = GetDataMemberByIndex(cr, (int)idata);
2206 return m->Property() & kIsStatic;
2207}
2208
2210{
2211 if (scope == GLOBAL_HANDLE) {
2212 TGlobal* gbl = g_globalvars[idata];
2213 return gbl->Property() & kIsConstant;
2214 }
2215 TClassRef& cr = type_from_handle(scope);
2216 if (cr.GetClass()) {
2217 TDataMember* m = GetDataMemberByIndex(cr, (int)idata);
2218 return m->Property() & kIsConstant;
2219 }
2220 return false;
2221}
2222
2224{
2225// TODO: currently, ROOT/meta does not properly distinguish between variables of enum
2226// type, and values of enums. The latter are supposed to be const. This code relies on
2227// odd features (bugs?) to figure out the difference, but this should really be fixed
2228// upstream and/or deserves a new API.
2229
2230 if (scope == GLOBAL_HANDLE) {
2231 TGlobal* gbl = g_globalvars[idata];
2232
2233 // make use of an oddity: enum global variables do not have their kIsStatic bit
2234 // set, whereas enum global values do
2235 return (gbl->Property() & kIsEnum) && (gbl->Property() & kIsStatic);
2236 }
2237
2238 TClassRef& cr = type_from_handle(scope);
2239 if (cr.GetClass()) {
2240 TDataMember* m = GetDataMemberByIndex(cr, (int)idata);
2241 std::string ti = m->GetTypeName();
2242
2243 // can't check anonymous enums by type name, so just accept them as enums
2244 if (ti.rfind("(unnamed)") != std::string::npos)
2245 return m->Property() & kIsEnum;
2246
2247 // since there seems to be no distinction between data of enum type and enum values,
2248 // check the list of constants for the type to see if there's a match
2249 if (ti.rfind(cr->GetName(), 0) != std::string::npos) {
2250 std::string::size_type s = strlen(cr->GetName())+2;
2251 if (s < ti.size()) {
2252 TEnum* ee = ((TListOfEnums*)cr->GetListOfEnums())->GetObject(ti.substr(s, std::string::npos).c_str());
2253 if (ee) return ee->GetConstant(m->GetName());
2254 }
2255 }
2256 }
2257
2258// this default return only means that the data will be writable, not that it will
2259// be unreadable or otherwise misrepresented
2260 return false;
2261}
2262
2263int Cppyy::GetDimensionSize(TCppScope_t scope, TCppIndex_t idata, int dimension)
2264{
2265 if (scope == GLOBAL_HANDLE) {
2266 TGlobal* gbl = g_globalvars[idata];
2267 return gbl->GetMaxIndex(dimension);
2268 }
2269 TClassRef& cr = type_from_handle(scope);
2270 if (cr.GetClass()) {
2271 TDataMember* m = GetDataMemberByIndex(cr, (int)idata);
2272 return m->GetMaxIndex(dimension);
2273 }
2274 return -1;
2275}
2276
2277
2278// enum properties -----------------------------------------------------------
2279Cppyy::TCppEnum_t Cppyy::GetEnum(TCppScope_t scope, const std::string& enum_name)
2280{
2281 if (scope == GLOBAL_HANDLE)
2282 return (TCppEnum_t)gROOT->GetListOfEnums(kTRUE)->FindObject(enum_name.c_str());
2283
2284 TClassRef& cr = type_from_handle(scope);
2285 if (cr.GetClass())
2286 return (TCppEnum_t)cr->GetListOfEnums(kTRUE)->FindObject(enum_name.c_str());
2287
2288 return (TCppEnum_t)0;
2289}
2290
2292{
2293 return (TCppIndex_t)((TEnum*)etype)->GetConstants()->GetSize();
2294}
2295
2297{
2298 return ((TEnumConstant*)((TEnum*)etype)->GetConstants()->At(idata))->GetName();
2299}
2300
2302{
2303 TEnumConstant* ecst = (TEnumConstant*)((TEnum*)etype)->GetConstants()->At(idata);
2304 return (long long)ecst->GetValue();
2305}
2306
2307
2308//- C-linkage wrappers -------------------------------------------------------
2309
2310extern "C" {
2311/* direct interpreter access ---------------------------------------------- */
2312int cppyy_compile(const char* code) {
2313 return Cppyy::Compile(code);
2314}
2315
2316
2317/* name to opaque C++ scope representation -------------------------------- */
2318char* cppyy_resolve_name(const char* cppitem_name) {
2319 return cppstring_to_cstring(Cppyy::ResolveName(cppitem_name));
2320}
2321
2322char* cppyy_resolve_enum(const char* enum_type) {
2323 return cppstring_to_cstring(Cppyy::ResolveEnum(enum_type));
2324}
2325
2326cppyy_scope_t cppyy_get_scope(const char* scope_name) {
2327 return cppyy_scope_t(Cppyy::GetScope(scope_name));
2328}
2329
2331 return cppyy_type_t(Cppyy::GetActualClass(klass, (void*)obj));
2332}
2333
2335 return Cppyy::SizeOf(klass);
2336}
2337
2338size_t cppyy_size_of_type(const char* type_name) {
2339 return Cppyy::SizeOf(type_name);
2340}
2341
2342
2343/* memory management ------------------------------------------------------ */
2346}
2347
2349 Cppyy::Deallocate(type, (void*)self);
2350}
2351
2354}
2355
2357 Cppyy::Destruct(type, (void*)self);
2358}
2359
2360
2361/* method/function dispatching -------------------------------------------- */
2362/* Exception types:
2363 1: default (unknown exception)
2364 2: standard exception
2365*/
2366#define CPPYY_HANDLE_EXCEPTION \
2367 catch (std::exception& e) { \
2368 cppyy_exctype_t* etype = (cppyy_exctype_t*)((Parameter*)args+nargs); \
2369 *etype = (cppyy_exctype_t)2; \
2370 *((char**)(etype+1)) = cppstring_to_cstring(e.what()); \
2371 } \
2372 catch (...) { \
2373 cppyy_exctype_t* etype = (cppyy_exctype_t*)((Parameter*)args+nargs); \
2374 *etype = (cppyy_exctype_t)1; \
2375 *((char**)(etype+1)) = \
2376 cppstring_to_cstring("unhandled, unknown C++ exception"); \
2377 }
2378
2379void cppyy_call_v(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
2380 try {
2381 Cppyy::CallV(method, (void*)self, nargs, args);
2383}
2384
2385unsigned char cppyy_call_b(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
2386 try {
2387 return (unsigned char)Cppyy::CallB(method, (void*)self, nargs, args);
2389 return (unsigned char)-1;
2390}
2391
2392char cppyy_call_c(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
2393 try {
2394 return (char)Cppyy::CallC(method, (void*)self, nargs, args);
2396 return (char)-1;
2397}
2398
2399short cppyy_call_h(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
2400 try {
2401 return (short)Cppyy::CallH(method, (void*)self, nargs, args);
2403 return (short)-1;
2404}
2405
2406int cppyy_call_i(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
2407 try {
2408 return (int)Cppyy::CallI(method, (void*)self, nargs, args);
2410 return (int)-1;
2411}
2412
2413long cppyy_call_l(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
2414 try {
2415 return (long)Cppyy::CallL(method, (void*)self, nargs, args);
2417 return (long)-1;
2418}
2419
2420long long cppyy_call_ll(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
2421 try {
2422 return (long long)Cppyy::CallLL(method, (void*)self, nargs, args);
2424 return (long long)-1;
2425}
2426
2427float cppyy_call_f(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
2428 try {
2429 return (float)Cppyy::CallF(method, (void*)self, nargs, args);
2431 return (float)-1;
2432}
2433
2434double cppyy_call_d(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
2435 try {
2436 return (double)Cppyy::CallD(method, (void*)self, nargs, args);
2438 return (double)-1;
2439}
2440
2441long double cppyy_call_ld(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
2442 try {
2443 return (long double)Cppyy::CallLD(method, (void*)self, nargs, args);
2445 return (long double)-1;
2446}
2447
2448double cppyy_call_nld(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
2449 return (double)cppyy_call_ld(method, self, nargs, args);
2450}
2451
2452void* cppyy_call_r(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
2453 try {
2454 return (void*)Cppyy::CallR(method, (void*)self, nargs, args);
2456 return (void*)nullptr;
2457}
2458
2460 cppyy_method_t method, cppyy_object_t self, int nargs, void* args, size_t* lsz) {
2461 try {
2462 return Cppyy::CallS(method, (void*)self, nargs, args, lsz);
2464 return (char*)nullptr;
2465}
2466
2468 cppyy_method_t method, cppyy_type_t klass, int nargs, void* args) {
2469 try {
2470 return cppyy_object_t(Cppyy::CallConstructor(method, klass, nargs, args));
2472 return (cppyy_object_t)0;
2473}
2474
2476 Cppyy::CallDestructor(klass, self);
2477}
2478
2480 int nargs, void* args, cppyy_type_t result_type) {
2481 try {
2482 return cppyy_object_t(Cppyy::CallO(method, (void*)self, nargs, args, result_type));
2484 return (cppyy_object_t)0;
2485}
2486
2488 return cppyy_funcaddr_t(Cppyy::GetFunctionAddress(method, true));
2489}
2490
2491
2492/* handling of function argument buffer ----------------------------------- */
2494// for calls through C interface, require extra space for reporting exceptions
2495 return malloc(nargs*sizeof(Parameter)+sizeof(cppyy_exctype_t)+sizeof(char**));
2496}
2497
2499 free(args);
2500}
2501
2503 return (size_t)Cppyy::GetFunctionArgSizeof();
2504}
2505
2507 return (size_t)Cppyy::GetFunctionArgTypeoffset();
2508}
2509
2510
2511/* scope reflection information ------------------------------------------- */
2513 return (int)Cppyy::IsNamespace(scope);
2514}
2515
2516int cppyy_is_template(const char* template_name) {
2517 return (int)Cppyy::IsTemplate(template_name);
2518}
2519
2521 return (int)Cppyy::IsAbstract(type);
2522}
2523
2524int cppyy_is_enum(const char* type_name) {
2525 return (int)Cppyy::IsEnum(type_name);
2526}
2527
2529 return (int)Cppyy::IsAggregate(type);
2530}
2531
2532const char** cppyy_get_all_cpp_names(cppyy_scope_t scope, size_t* count) {
2533 std::set<std::string> cppnames;
2534 Cppyy::GetAllCppNames(scope, cppnames);
2535 const char** c_cppnames = (const char**)malloc(cppnames.size()*sizeof(const char*));
2536 int i = 0;
2537 for (const auto& name : cppnames) {
2538 c_cppnames[i] = cppstring_to_cstring(name);
2539 ++i;
2540 }
2541 *count = cppnames.size();
2542 return c_cppnames;
2543}
2544
2545
2546/* namespace reflection information --------------------------------------- */
2548 const std::vector<Cppyy::TCppScope_t>& uv = Cppyy::GetUsingNamespaces((Cppyy::TCppScope_t)scope);
2549
2550 if (uv.empty())
2551 return (cppyy_index_t*)nullptr;
2552
2553 cppyy_scope_t* llresult = (cppyy_scope_t*)malloc(sizeof(cppyy_scope_t)*(uv.size()+1));
2554 for (int i = 0; i < (int)uv.size(); ++i) llresult[i] = uv[i];
2555 llresult[uv.size()] = (cppyy_scope_t)0;
2556 return llresult;
2557}
2558
2559
2560/* class reflection information ------------------------------------------- */
2563}
2564
2567}
2568
2570 return (int)Cppyy::HasVirtualDestructor(type);
2571}
2572
2574 return (int)Cppyy::HasComplexHierarchy(type);
2575}
2576
2578 return (int)Cppyy::GetNumBases(type);
2579}
2580
2583}
2584
2585char* cppyy_base_name(cppyy_type_t type, int base_index) {
2586 return cppstring_to_cstring(Cppyy::GetBaseName (type, base_index));
2587}
2588
2590 return (int)Cppyy::IsSubtype(derived, base);
2591}
2592
2594 return (int)Cppyy::IsSmartPtr(type);
2595}
2596
2597int cppyy_smartptr_info(const char* name, cppyy_type_t* raw, cppyy_method_t* deref) {
2598 return (int)Cppyy::GetSmartPtrInfo(name, raw, deref);
2599}
2600
2601void cppyy_add_smartptr_type(const char* type_name) {
2602 Cppyy::AddSmartPtrType(type_name);
2603}
2604
2605
2606/* calculate offsets between declared and actual type, up-cast: direction > 0; down-cast: direction < 0 */
2607ptrdiff_t cppyy_base_offset(cppyy_type_t derived, cppyy_type_t base, cppyy_object_t address, int direction) {
2608 return (ptrdiff_t)Cppyy::GetBaseOffset(derived, base, (void*)address, direction, 0);
2609}
2610
2611
2612/* method/function reflection information --------------------------------- */
2614 return (int)Cppyy::GetNumMethods(scope);
2615}
2616
2618{
2619 std::vector<cppyy_index_t> result = Cppyy::GetMethodIndicesFromName(scope, name);
2620
2621 if (result.empty())
2622 return (cppyy_index_t*)nullptr;
2623
2624 cppyy_index_t* llresult = (cppyy_index_t*)malloc(sizeof(cppyy_index_t)*(result.size()+1));
2625 for (int i = 0; i < (int)result.size(); ++i) llresult[i] = result[i];
2626 llresult[result.size()] = -1;
2627 return llresult;
2628}
2629
2631 return cppyy_method_t(Cppyy::GetMethod(scope, idx));
2632}
2633
2636}
2637
2640}
2641
2644}
2645
2648}
2649
2651 return (int)Cppyy::GetMethodNumArgs((Cppyy::TCppMethod_t)method);
2652}
2653
2655 return (int)Cppyy::GetMethodReqArgs((Cppyy::TCppMethod_t)method);
2656}
2657
2658char* cppyy_method_arg_name(cppyy_method_t method, int arg_index) {
2660}
2661
2662char* cppyy_method_arg_type(cppyy_method_t method, int arg_index) {
2664}
2665
2666char* cppyy_method_arg_default(cppyy_method_t method, int arg_index) {
2668}
2669
2670char* cppyy_method_signature(cppyy_method_t method, int show_formalargs) {
2671 return cppstring_to_cstring(Cppyy::GetMethodSignature((Cppyy::TCppMethod_t)method, (bool)show_formalargs));
2672}
2673
2674char* cppyy_method_signature_max(cppyy_method_t method, int show_formalargs, int maxargs) {
2675 return cppstring_to_cstring(Cppyy::GetMethodSignature((Cppyy::TCppMethod_t)method, (bool)show_formalargs, (Cppyy::TCppIndex_t)maxargs));
2676}
2677
2678char* cppyy_method_prototype(cppyy_scope_t scope, cppyy_method_t method, int show_formalargs) {
2680 (Cppyy::TCppScope_t)scope, (Cppyy::TCppMethod_t)method, (bool)show_formalargs));
2681}
2682
2684 return (int)Cppyy::IsConstMethod(method);
2685}
2686
2688 return (int)Cppyy::GetNumTemplatedMethods(scope);
2689}
2690
2693}
2694
2697}
2698
2700 return (int)Cppyy::ExistsMethodTemplate(scope, name);
2701}
2702
2704 return (int)Cppyy::IsMethodTemplate(scope, idx);
2705}
2706
2709}
2710
2713}
2714
2715
2716/* method properties ------------------------------------------------------ */
2718 return (int)Cppyy::IsPublicMethod((Cppyy::TCppMethod_t)method);
2719}
2720
2722 return (int)Cppyy::IsProtectedMethod((Cppyy::TCppMethod_t)method);
2723}
2724
2726 return (int)Cppyy::IsConstructor((Cppyy::TCppMethod_t)method);
2727}
2728
2730 return (int)Cppyy::IsDestructor((Cppyy::TCppMethod_t)method);
2731}
2732
2734 return (int)Cppyy::IsStaticMethod((Cppyy::TCppMethod_t)method);
2735}
2736
2737
2738/* data member reflection information ------------------------------------- */
2740 return (int)Cppyy::GetNumDatamembers(scope);
2741}
2742
2743char* cppyy_datamember_name(cppyy_scope_t scope, int datamember_index) {
2744 return cppstring_to_cstring(Cppyy::GetDatamemberName(scope, datamember_index));
2745}
2746
2747char* cppyy_datamember_type(cppyy_scope_t scope, int datamember_index) {
2748 return cppstring_to_cstring(Cppyy::GetDatamemberType(scope, datamember_index));
2749}
2750
2751intptr_t cppyy_datamember_offset(cppyy_scope_t scope, int datamember_index) {
2752 return intptr_t(Cppyy::GetDatamemberOffset(scope, datamember_index));
2753}
2754
2756 return (int)Cppyy::GetDatamemberIndex(scope, name);
2757}
2758
2759
2760
2761/* data member properties ------------------------------------------------- */
2763 return (int)Cppyy::IsPublicData(type, datamember_index);
2764}
2765
2767 return (int)Cppyy::IsProtectedData(type, datamember_index);
2768}
2769
2771 return (int)Cppyy::IsStaticData(type, datamember_index);
2772}
2773
2775 return (int)Cppyy::IsConstData(scope, idata);
2776}
2777
2779 return (int)Cppyy::IsEnumData(scope, idata);
2780}
2781
2782int cppyy_get_dimension_size(cppyy_scope_t scope, cppyy_index_t idata, int dimension) {
2783 return Cppyy::GetDimensionSize(scope, idata, dimension);
2784}
2785
2786
2787/* misc helpers ----------------------------------------------------------- */
2789void* cppyy_load_dictionary(const char* lib_name) {
2790 int result = gSystem->Load(lib_name);
2791 return (void*)(result == 0 /* success */ || result == 1 /* already loaded */);
2792}
2793
2794#if defined(_MSC_VER)
2795long long cppyy_strtoll(const char* str) {
2796 return _strtoi64(str, NULL, 0);
2797}
2798
2799extern "C" {
2800unsigned long long cppyy_strtoull(const char* str) {
2801 return _strtoui64(str, NULL, 0);
2802}
2803}
2804#else
2805long long cppyy_strtoll(const char* str) {
2806 return strtoll(str, NULL, 0);
2807}
2808
2809extern "C" {
2810unsigned long long cppyy_strtoull(const char* str) {
2811 return strtoull(str, NULL, 0);
2812}
2813}
2814#endif
2815
2816void cppyy_free(void* ptr) {
2817 free(ptr);
2818}
2819
2820cppyy_object_t cppyy_charp2stdstring(const char* str, size_t sz) {
2821 return (cppyy_object_t)new std::string(str, sz);
2822}
2823
2824const char* cppyy_stdstring2charp(cppyy_object_t ptr, size_t* lsz) {
2825 *lsz = ((std::string*)ptr)->size();
2826 return ((std::string*)ptr)->data();
2827}
2828
2830 return (cppyy_object_t)new std::string(*(std::string*)ptr);
2831}
2832
2834 return (double)*(long double*)p;
2835}
2836
2837void cppyy_double2longdouble(double d, void* p) {
2838 *(long double*)p = d;
2839}
2840
2842 return (int)(*(std::vector<bool>*)ptr)[idx];
2843}
2844
2846 (*(std::vector<bool>*)ptr)[idx] = (bool)value;
2847}
2848
2849} // end C-linkage wrappers
#define d(i)
Definition RSha256.hxx:102
#define b(i)
Definition RSha256.hxx:100
#define f(i)
Definition RSha256.hxx:104
#define c(i)
Definition RSha256.hxx:101
static Roo_reg_AGKInteg1D instance
int Int_t
Definition RtypesCore.h:45
long double LongDouble_t
Definition RtypesCore.h:61
long long Long64_t
Definition RtypesCore.h:69
constexpr Bool_t kTRUE
Definition RtypesCore.h:93
@ kMAXSIGNALS
Definition Rtypes.h:59
@ kOther_t
Definition TDataType.h:32
@ kIsDestructor
@ kIsTemplateSpec
@ kIsConstructor
@ kClassIsAggregate
@ kClassHasExplicitDtor
@ kClassHasImplicitDtor
@ kIsPublic
Definition TDictionary.h:75
@ kIsConstant
Definition TDictionary.h:88
@ kIsConstMethod
Definition TDictionary.h:96
@ kIsEnum
Definition TDictionary.h:68
@ kIsPrivate
Definition TDictionary.h:77
@ kIsFundamental
Definition TDictionary.h:70
@ kIsAbstract
Definition TDictionary.h:71
@ kIsStatic
Definition TDictionary.h:80
@ kIsProtected
Definition TDictionary.h:76
@ kIsVirtual
Definition TDictionary.h:72
@ kIsNamespace
Definition TDictionary.h:95
@ kIsVirtualBase
Definition TDictionary.h:89
constexpr Int_t kFatal
Definition TError.h:50
Int_t gErrorIgnoreLevel
Error handling routines.
Definition TError.cxx:31
R__EXTERN TExceptionHandler * gExceptionHandler
Definition TException.h:79
R__EXTERN ExceptionContext_t * gException
Definition TException.h:69
R__EXTERN void Throw(int code)
If an exception context has been set (using the TRY and RETRY macros) jump back to where it was set.
winID h TVirtualViewer3D TVirtualGLPainter p
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 r
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 index
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 length
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
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 req_type
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void funcs
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
char name[80]
Definition TGX11.cxx:110
#define gInterpreter
#define gROOT
Definition TROOT.h:406
R__EXTERN TSystem * gSystem
Definition TSystem.h:561
static struct Signalmap_t gSignalMap[kMAXSIGNALS]
size_t cppyy_scope_t
Definition capi.h:12
cppyy_scope_t cppyy_type_t
Definition capi.h:13
intptr_t cppyy_method_t
Definition capi.h:15
size_t cppyy_index_t
Definition capi.h:17
void * cppyy_object_t
Definition capi.h:14
unsigned long cppyy_exctype_t
Definition capi.h:20
void * cppyy_funcaddr_t
Definition capi.h:18
const char * proto
Definition civetweb.c:17536
#define free
Definition civetweb.c:1539
#define malloc
Definition civetweb.c:1536
Each class (see TClass) has a linked list of its base class(es).
Definition TBaseClass.h:33
Long_t Property() const override
Get property description word. For meaning of bits see EProperty.
TClassRef is used to implement a permanent reference to a TClass object.
Definition TClassRef.h:28
TClass * GetClass() const
Definition TClassRef.h:66
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition TClass.h:81
TList * GetListOfUsingDataMembers(Bool_t load=kTRUE)
Return list containing the TDataMembers of using declarations of a class.
Definition TClass.cxx:3786
void * New(ENewType defConstructor=kClassNew, Bool_t quiet=kFALSE) const
Return a pointer to a newly allocated object of this class.
Definition TClass.cxx:4978
TMethod * GetMethod(const char *method, const char *params, Bool_t objectIsConst=kFALSE)
Find the best method (if there is one) matching the parameters.
Definition TClass.cxx:4411
TMethod * GetMethodWithPrototype(const char *method, const char *proto, Bool_t objectIsConst=kFALSE, ROOT::EFunctionMatchMode mode=ROOT::kConversionMatch)
Find the method with a given prototype.
Definition TClass.cxx:4456
void Destructor(void *obj, Bool_t dtorOnly=kFALSE)
Explicitly call destructor for object.
Definition TClass.cxx:5400
TList * GetListOfFunctionTemplates(Bool_t load=kTRUE)
Return TListOfFunctionTemplates for a class.
Definition TClass.cxx:3798
TList * GetListOfEnums(Bool_t load=kTRUE)
Return a list containing the TEnums of a class.
Definition TClass.cxx:3686
TList * GetListOfMethods(Bool_t load=kTRUE)
Return list containing the TMethods of a class.
Definition TClass.cxx:3812
TClass * GetBaseClass(const char *classname)
Return pointer to the base class "classname".
Definition TClass.cxx:2655
TList * GetListOfDataMembers(Bool_t load=kTRUE)
Return list containing the TDataMembers of a class.
Definition TClass.cxx:3770
@ kRealNew
Definition TClass.h:107
TList * GetListOfBases()
Return list containing the TBaseClass(es) of a class.
Definition TClass.cxx:3636
Bool_t IsLoaded() const
Return true if the shared library of this class is currently in the a process's memory.
Definition TClass.cxx:5912
ClassInfo_t * GetClassInfo() const
Definition TClass.h:433
Long_t ClassProperty() const
Return the C++ property of this class, eg.
Definition TClass.cxx:2396
Long_t Property() const override
Returns the properties of the TClass as a bit field stored as a Long_t value.
Definition TClass.cxx:6086
Bool_t HasDefaultConstructor(Bool_t testio=kFALSE) const
Return true if we have access to a constructor usable for I/O.
Definition TClass.cxx:7393
TMethod * GetMethodAllAny(const char *method)
Return pointer to method without looking at parameters.
Definition TClass.cxx:4384
ROOT::DelFunc_t GetDelete() const
Return the wrapper around delete ThiObject.
Definition TClass.cxx:7463
TClass * GetActualClass(const void *object) const
Return a pointer to the real class of the object.
Definition TClass.cxx:2607
TFunctionTemplate * GetFunctionTemplate(const char *name)
Definition TClass.cxx:3607
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Definition TClass.cxx:2968
Collection abstract base class.
Definition TCollection.h:65
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
All ROOT classes may have RTTI (run time type identification) support added.
Definition TDataMember.h:31
Basic data type descriptor (datatype information is obtained from CINT).
Definition TDataType.h:44
Int_t GetType() const
Definition TDataType.h:68
const char * GetFullTypeName() const
Get full type description of typedef, e,g.: "class TDirectory*".
Long_t Property() const override
Get property description word. For meaning of bits see EProperty.
Int_t Size() const
Get size of basic typedef'ed type.
const void * DeclId_t
The TEnumConstant class implements the constants of the enum type.
Long64_t GetValue() const
The TEnum class implements the enum type.
Definition TEnum.h:33
const TEnumConstant * GetConstant(const char *name) const
Definition TEnum.h:64
Definition TEnv.h:86
const char * GetValue() const
Definition TEnv.h:110
const char * GetName() const override
Returns name of object.
Definition TEnv.h:109
virtual void HandleException(int sig)=0
Dictionary for function template This class describes one single function template.
Global functions class (global functions are obtained from CINT).
Definition TFunction.h:30
virtual const char * GetMangledName() const
Returns the mangled name as defined by CINT, or 0 in case of error.
Long_t Property() const override
Get property description word. For meaning of bits see EProperty.
Int_t GetNargs() const
Number of function arguments.
Long_t ExtraProperty() const
Get property description word. For meaning of bits see EProperty.
std::string GetReturnTypeNormalizedName() const
Get the normalized name of the return type.
Global variables class (global variables are obtained from CINT).
Definition TGlobal.h:28
virtual Int_t GetArrayDim() const
Return number of array dimensions.
Definition TGlobal.cxx:89
virtual Int_t GetMaxIndex(Int_t dim) const
Return maximum index for array dimension "dim".
Definition TGlobal.cxx:105
Long_t Property() const override
Get property description word. For meaning of bits see EProperty.
Definition TGlobal.cxx:152
virtual void * GetAddress() const
Return address of global.
Definition TGlobal.cxx:81
virtual const char * GetFullTypeName() const
Get full type description of global variable, e,g.: "class TDirectory*".
Definition TGlobal.cxx:124
THashList implements a hybrid collection class consisting of a hash table and a list to store TObject...
Definition THashList.h:34
TObject * Next()
A collection of TDataMember objects designed for fast access given a DeclId_t and for keep track of T...
A collection of TEnum objects designed for fast access given a DeclId_t and for keep track of TEnum t...
TObject * FindObject(const char *name) const override
Find an object in this list using its name.
Definition TList.cxx:576
TObject * At(Int_t idx) const override
Returns the object at position idx. Returns 0 if idx is out of range.
Definition TList.cxx:355
Each ROOT method (see TMethod) has a linked list of its arguments.
Definition TMethodArg.h:36
const char * GetFullTypeName() const
Get full type description of method argument, e.g.: "class TDirectory*".
TypeInfo_t * GetTypeInfo() const
Get the TypeInfo of the method argument.
const char * GetDefault() const
Get default value of method argument.
std::string GetTypeNormalizedName() const
Get the normalized name of the return type.
const char * GetName() const override
Returns name of object.
Definition TNamed.h:47
virtual const char * GetName() const
Returns name of object.
Definition TObject.cxx:438
virtual TObject * FindObject(const char *name) const
Must be redefined in derived classes.
Definition TObject.cxx:402
static Bool_t Initialized()
Return kTRUE if the TROOT object has been initialized.
Definition TROOT.cxx:2910
virtual Int_t IndexOf(const TObject *obj) const
Return index of object in collection.
virtual int Load(const char *module, const char *entry="", Bool_t system=kFALSE)
Load a shared library.
Definition TSystem.cxx:1857
virtual void Exit(int code, Bool_t mode=kTRUE)
Exit the application.
Definition TSystem.cxx:716
virtual void StackTrace()
Print a stack trace.
Definition TSystem.cxx:734
char * cppyy_method_mangled_name(cppyy_method_t method)
int cppyy_is_staticdata(cppyy_type_t type, cppyy_index_t datamember_index)
int cppyy_vectorbool_getitem(cppyy_object_t ptr, int idx)
int cppyy_has_virtual_destructor(cppyy_type_t type)
int cppyy_is_publicmethod(cppyy_method_t method)
void * cppyy_call_r(cppyy_method_t method, cppyy_object_t self, int nargs, void *args)
cppyy_object_t cppyy_constructor(cppyy_method_t method, cppyy_type_t klass, int nargs, void *args)
void * cppyy_load_dictionary(const char *lib_name)
static void cond_add(Cppyy::TCppScope_t scope, const std::string &ns_scope, std::set< std::string > &cppnames, const char *name, bool nofilter=false)
size_t cppyy_function_arg_typeoffset()
int cppyy_exists_method_template(cppyy_scope_t scope, const char *name)
int cppyy_get_num_templated_methods(cppyy_scope_t scope)
char * cppyy_call_s(cppyy_method_t method, cppyy_object_t self, int nargs, void *args, size_t *lsz)
char * cppyy_resolve_enum(const char *enum_type)
cppyy_object_t cppyy_charp2stdstring(const char *str, size_t sz)
static Name2ClassRefIndex_t g_name2classrefidx
int cppyy_is_constructor(cppyy_method_t method)
int cppyy_is_enum_data(cppyy_scope_t scope, cppyy_index_t idata)
#define FILL_COLL(type, filter)
char * cppyy_scoped_final_name(cppyy_type_t type)
int cppyy_num_bases(cppyy_type_t type)
const int SMALL_ARGS_N
static std::string outer_with_template(const std::string &name)
cppyy_method_t cppyy_get_method_template(cppyy_scope_t scope, const char *name, const char *proto)
static std::string outer_no_template(const std::string &name)
int cppyy_is_smartptr(cppyy_type_t type)
static std::string type_remap(const std::string &n1, const std::string &n2)
static std::map< Cppyy::TCppType_t, bool > sHasOperatorDelete
long long cppyy_strtoll(const char *str)
static std::set< std::string > gRootSOs
int cppyy_is_subtype(cppyy_type_t derived, cppyy_type_t base)
static TClassRef & type_from_handle(Cppyy::TCppScope_t scope)
double cppyy_call_nld(cppyy_method_t method, cppyy_object_t self, int nargs, void *args)
void cppyy_free(void *ptr)
int cppyy_smartptr_info(const char *name, cppyy_type_t *raw, cppyy_method_t *deref)
unsigned long long cppyy_strtoull(const char *str)
char * cppyy_method_arg_type(cppyy_method_t method, int arg_index)
cppyy_object_t cppyy_stdstring2stdstring(cppyy_object_t ptr)
char * cppyy_base_name(cppyy_type_t type, int base_index)
cppyy_scope_t * cppyy_get_using_namespaces(cppyy_scope_t scope)
static bool copy_args(Parameter *args, size_t nargs, void **vargs)
int cppyy_num_bases_longest_branch(cppyy_type_t type)
static TInterpreter::CallFuncIFacePtr_t GetCallFunc(Cppyy::TCppMethod_t method)
int cppyy_is_publicdata(cppyy_type_t type, cppyy_index_t datamember_index)
CPyCppyy::Parameter Parameter
intptr_t cppyy_datamember_offset(cppyy_scope_t scope, int datamember_index)
char * cppyy_datamember_type(cppyy_scope_t scope, int datamember_index)
static bool is_missclassified_stl(const std::string &name)
std::map< std::string, ClassRefs_t::size_type > Name2ClassRefIndex_t
void cppyy_destructor(cppyy_type_t klass, cppyy_object_t self)
static const ClassRefs_t::size_type STD_HANDLE
char cppyy_call_c(cppyy_method_t method, cppyy_object_t self, int nargs, void *args)
ptrdiff_t cppyy_base_offset(cppyy_type_t derived, cppyy_type_t base, cppyy_object_t address, int direction)
long double cppyy_call_ld(cppyy_method_t method, cppyy_object_t self, int nargs, void *args)
int cppyy_is_const_data(cppyy_scope_t scope, cppyy_index_t idata)
const char ** cppyy_get_all_cpp_names(cppyy_scope_t scope, size_t *count)
void cppyy_call_v(cppyy_method_t method, cppyy_object_t self, int nargs, void *args)
static std::set< std::string > gSmartPtrTypes
double cppyy_longdouble2double(void *p)
int cppyy_method_req_args(cppyy_method_t method)
int cppyy_is_staticmethod(cppyy_method_t method)
static GlobalVars_t g_globalvars
cppyy_index_t * cppyy_method_indices_from_name(cppyy_scope_t scope, const char *name)
static char * cppstring_to_cstring(const std::string &cppstr)
char * cppyy_method_signature(cppyy_method_t method, int show_formalargs)
int cppyy_is_abstract(cppyy_type_t type)
static void release_args(Parameter *args, size_t nargs)
int cppyy_call_i(cppyy_method_t method, cppyy_object_t self, int nargs, void *args)
static std::set< std::string > g_builtins
unsigned char cppyy_call_b(cppyy_method_t method, cppyy_object_t self, int nargs, void *args)
int cppyy_is_template(const char *template_name)
char * cppyy_method_result_type(cppyy_method_t method)
cppyy_type_t cppyy_actual_class(cppyy_type_t klass, cppyy_object_t obj)
int cppyy_is_templated_constructor(cppyy_scope_t scope, cppyy_index_t imeth)
char * cppyy_method_name(cppyy_method_t method)
int cppyy_is_protectedmethod(cppyy_method_t method)
char * cppyy_final_name(cppyy_type_t type)
char * cppyy_get_templated_method_name(cppyy_scope_t scope, cppyy_index_t imeth)
char * cppyy_method_full_name(cppyy_method_t method)
long cppyy_call_l(cppyy_method_t method, cppyy_object_t self, int nargs, void *args)
void cppyy_double2longdouble(double d, void *p)
void cppyy_deallocate_function_args(void *args)
int cppyy_method_is_template(cppyy_scope_t scope, cppyy_index_t idx)
static std::vector< CallWrapper * > gWrapperHolder
static bool gEnableFastPath
void cppyy_destruct(cppyy_type_t type, cppyy_object_t self)
int cppyy_is_enum(const char *type_name)
size_t cppyy_size_of_type(const char *type_name)
int cppyy_is_destructor(cppyy_method_t method)
cppyy_object_t cppyy_allocate(cppyy_type_t type)
char * cppyy_datamember_name(cppyy_scope_t scope, int datamember_index)
cppyy_object_t cppyy_construct(cppyy_type_t type)
static ClassRefs_t g_classrefs(1)
static bool WrapperCall(Cppyy::TCppMethod_t method, size_t nargs, void *args_, void *self, void *result)
static std::map< std::string, std::string > resolved_enum_types
int cppyy_is_namespace(cppyy_scope_t scope)
cppyy_object_t cppyy_call_o(cppyy_method_t method, cppyy_object_t self, int nargs, void *args, cppyy_type_t result_type)
long long cppyy_call_ll(cppyy_method_t method, cppyy_object_t self, int nargs, void *args)
cppyy_scope_t cppyy_get_scope(const char *scope_name)
void cppyy_vectorbool_setitem(cppyy_object_t ptr, int idx, int value)
static size_t CALL_NARGS(size_t nargs)
static CallWrapper * new_CallWrapper(TFunction *f)
void cppyy_add_smartptr_type(const char *type_name)
void * cppyy_allocate_function_args(int nargs)
float cppyy_call_f(cppyy_method_t method, cppyy_object_t self, int nargs, void *args)
short cppyy_call_h(cppyy_method_t method, cppyy_object_t self, int nargs, void *args)
int cppyy_is_protecteddata(cppyy_type_t type, cppyy_index_t datamember_index)
static std::set< std::string > gSTLNames
static const ClassRefs_t::size_type GLOBAL_HANDLE
int cppyy_get_dimension_size(cppyy_scope_t scope, cppyy_index_t idata, int dimension)
char * cppyy_method_signature_max(cppyy_method_t method, int show_formalargs, int maxargs)
double cppyy_call_d(cppyy_method_t method, cppyy_object_t self, int nargs, void *args)
int cppyy_num_methods(cppyy_scope_t scope)
char * cppyy_method_prototype(cppyy_scope_t scope, cppyy_method_t method, int show_formalargs)
std::vector< TGlobal * > GlobalVars_t
char * cppyy_resolve_name(const char *cppitem_name)
cppyy_method_t cppyy_get_method(cppyy_scope_t scope, cppyy_index_t idx)
std::vector< TClassRef > ClassRefs_t
size_t cppyy_function_arg_sizeof()
int cppyy_is_const_method(cppyy_method_t method)
static std::map< TDictionary::DeclId_t, CallWrapper * > gMethodTemplates
int cppyy_num_datamembers(cppyy_scope_t scope)
#define CPPYY_HANDLE_EXCEPTION
size_t cppyy_size_of_klass(cppyy_type_t klass)
static bool match_name(const std::string &tname, const std::string fname)
int cppyy_datamember_index(cppyy_scope_t scope, const char *name)
cppyy_index_t cppyy_get_global_operator(cppyy_scope_t scope, cppyy_scope_t lc, cppyy_scope_t rc, const char *op)
static TFunction * m2f(Cppyy::TCppMethod_t method)
void cppyy_deallocate(cppyy_type_t type, cppyy_object_t self)
const char * cppyy_stdstring2charp(cppyy_object_t ptr, size_t *lsz)
int cppyy_compile(const char *code)
static CallWrapper::DeclId_t m2d(Cppyy::TCppMethod_t method)
int cppyy_is_aggregate(cppyy_type_t type)
static TDataMember * GetDataMemberByIndex(TClassRef cr, int idata)
#define CPPYY_IMP_CALL(typecode, rtype)
int cppyy_method_num_args(cppyy_method_t method)
static std::set< std::string > gInitialNames
char * cppyy_method_arg_default(cppyy_method_t method, int arg_index)
static T CallT(Cppyy::TCppMethod_t method, Cppyy::TCppObject_t self, size_t nargs, void *args)
cppyy_funcaddr_t cppyy_function_address(cppyy_method_t method)
int cppyy_has_complex_hierarchy(cppyy_type_t type)
Cppyy::TCppIndex_t GetLongestInheritancePath(TClass *klass)
Retrieve number of base classes in the longest branch of the inheritance tree of the input class.
char * cppyy_method_arg_name(cppyy_method_t method, int arg_index)
const Int_t n
Definition legend1.C:16
#define F(x, y, z)
#define I(x, y, z)
#define H(x, y, z)
size_t TCppIndex_t
Definition cpp_cppyy.h:24
RPY_EXPORTED TCppIndex_t GetNumTemplatedMethods(TCppScope_t scope, bool accept_namespace=false)
RPY_EXPORTED std::string GetMethodMangledName(TCppMethod_t)
RPY_EXPORTED TCppObject_t CallO(TCppMethod_t method, TCppObject_t self, size_t nargs, void *args, TCppType_t result_type)
RPY_EXPORTED int CallI(TCppMethod_t method, TCppObject_t self, size_t nargs, void *args)
RPY_EXPORTED TCppIndex_t CompareMethodArgType(TCppMethod_t, TCppIndex_t iarg, const std::string &req_type)
RPY_EXPORTED ptrdiff_t GetBaseOffset(TCppType_t derived, TCppType_t base, TCppObject_t address, int direction, bool rerror=false)
RPY_EXPORTED void DeallocateFunctionArgs(void *args)
RPY_EXPORTED bool IsEnumData(TCppScope_t scope, TCppIndex_t idata)
RPY_EXPORTED unsigned char CallB(TCppMethod_t method, TCppObject_t self, size_t nargs, void *args)
RPY_EXPORTED Long64_t CallLL(TCppMethod_t method, TCppObject_t self, size_t nargs, void *args)
RPY_EXPORTED bool IsAbstract(TCppType_t type)
RPY_EXPORTED size_t SizeOf(TCppType_t klass)
RPY_EXPORTED TCppObject_t CallConstructor(TCppMethod_t method, TCppType_t type, size_t nargs, void *args)
intptr_t TCppMethod_t
Definition cpp_cppyy.h:22
RPY_EXPORTED void * AllocateFunctionArgs(size_t nargs)
RPY_EXPORTED bool IsDefaultConstructable(TCppType_t type)
RPY_EXPORTED bool IsTemplate(const std::string &template_name)
RPY_EXPORTED TCppIndex_t GetMethodReqArgs(TCppMethod_t)
RPY_EXPORTED bool IsEnum(const std::string &type_name)
RPY_EXPORTED std::vector< TCppIndex_t > GetMethodIndicesFromName(TCppScope_t scope, const std::string &name)
RPY_EXPORTED bool ExistsMethodTemplate(TCppScope_t scope, const std::string &name)
RPY_EXPORTED TCppIndex_t GetNumDatamembers(TCppScope_t scope, bool accept_namespace=false)
RPY_EXPORTED std::string ToString(TCppType_t klass, TCppObject_t obj)
RPY_EXPORTED std::string GetMethodName(TCppMethod_t)
RPY_EXPORTED bool IsConstData(TCppScope_t scope, TCppIndex_t idata)
RPY_EXPORTED void AddSmartPtrType(const std::string &)
RPY_EXPORTED bool Compile(const std::string &code, bool silent=false)
RPY_EXPORTED void CallDestructor(TCppType_t type, TCppObject_t self)
RPY_EXPORTED TCppScope_t gGlobalScope
Definition cpp_cppyy.h:53
RPY_EXPORTED bool IsProtectedData(TCppScope_t scope, TCppIndex_t idata)
RPY_EXPORTED std::string GetMethodSignature(TCppMethod_t, bool show_formalargs, TCppIndex_t maxargs=(TCppIndex_t) -1)
RPY_EXPORTED int GetDimensionSize(TCppScope_t scope, TCppIndex_t idata, int dimension)
RPY_EXPORTED bool IsSubtype(TCppType_t derived, TCppType_t base)
RPY_EXPORTED TCppMethod_t GetMethodTemplate(TCppScope_t scope, const std::string &name, const std::string &proto)
void * TCppObject_t
Definition cpp_cppyy.h:21
RPY_EXPORTED bool IsConstructor(TCppMethod_t method)
RPY_EXPORTED TCppIndex_t GetNumMethods(TCppScope_t scope, bool accept_namespace=false)
RPY_EXPORTED TCppObject_t Construct(TCppType_t type, void *arena=nullptr)
RPY_EXPORTED bool GetSmartPtrInfo(const std::string &, TCppType_t *raw, TCppMethod_t *deref)
RPY_EXPORTED char CallC(TCppMethod_t method, TCppObject_t self, size_t nargs, void *args)
RPY_EXPORTED std::string GetMethodArgName(TCppMethod_t, TCppIndex_t iarg)
RPY_EXPORTED double CallD(TCppMethod_t method, TCppObject_t self, size_t nargs, void *args)
RPY_EXPORTED size_t GetFunctionArgTypeoffset()
RPY_EXPORTED TCppObject_t Allocate(TCppType_t type)
RPY_EXPORTED void Destruct(TCppType_t type, TCppObject_t instance)
RPY_EXPORTED std::string ResolveName(const std::string &cppitem_name)
TCppScope_t TCppType_t
Definition cpp_cppyy.h:19
RPY_EXPORTED void AddTypeReducer(const std::string &reducable, const std::string &reduced)
RPY_EXPORTED std::string ResolveEnum(const std::string &enum_type)
RPY_EXPORTED long long GetEnumDataValue(TCppEnum_t, TCppIndex_t idata)
RPY_EXPORTED bool IsAggregate(TCppType_t type)
RPY_EXPORTED TCppIndex_t GetMethodNumArgs(TCppMethod_t)
RPY_EXPORTED TCppType_t GetActualClass(TCppType_t klass, TCppObject_t obj)
RPY_EXPORTED std::string GetBaseName(TCppType_t type, TCppIndex_t ibase)
RPY_EXPORTED bool IsNamespace(TCppScope_t scope)
void * TCppEnum_t
Definition cpp_cppyy.h:20
RPY_EXPORTED float CallF(TCppMethod_t method, TCppObject_t self, size_t nargs, void *args)
RPY_EXPORTED std::string GetScopedFinalName(TCppType_t type)
RPY_EXPORTED void Deallocate(TCppType_t type, TCppObject_t instance)
RPY_EXPORTED bool IsPublicData(TCppScope_t scope, TCppIndex_t idata)
RPY_EXPORTED std::string GetMethodArgType(TCppMethod_t, TCppIndex_t iarg)
RPY_EXPORTED long CallL(TCppMethod_t method, TCppObject_t self, size_t nargs, void *args)
RPY_EXPORTED void * CallR(TCppMethod_t method, TCppObject_t self, size_t nargs, void *args)
RPY_EXPORTED std::string GetEnumDataName(TCppEnum_t, TCppIndex_t idata)
RPY_EXPORTED void GetAllCppNames(TCppScope_t scope, std::set< std::string > &cppnames)
RPY_EXPORTED bool IsComplete(const std::string &type_name)
RPY_EXPORTED bool IsBuiltin(const std::string &type_name)
RPY_EXPORTED bool IsStaticMethod(TCppMethod_t method)
RPY_EXPORTED TCppIndex_t GetDatamemberIndex(TCppScope_t scope, const std::string &name)
RPY_EXPORTED void CallV(TCppMethod_t method, TCppObject_t self, size_t nargs, void *args)
RPY_EXPORTED LongDouble_t CallLD(TCppMethod_t method, TCppObject_t self, size_t nargs, void *args)
RPY_EXPORTED bool IsStaticData(TCppScope_t scope, TCppIndex_t idata)
RPY_EXPORTED std::string GetDatamemberType(TCppScope_t scope, TCppIndex_t idata)
RPY_EXPORTED TCppMethod_t GetMethod(TCppScope_t scope, TCppIndex_t imeth)
RPY_EXPORTED bool IsDestructor(TCppMethod_t method)
RPY_EXPORTED bool IsSmartPtr(TCppType_t type)
RPY_EXPORTED std::string GetTemplatedMethodName(TCppScope_t scope, TCppIndex_t imeth)
RPY_EXPORTED size_t GetFunctionArgSizeof()
RPY_EXPORTED TCppScope_t GetScope(const std::string &scope_name)
RPY_EXPORTED bool HasVirtualDestructor(TCppType_t type)
RPY_EXPORTED bool IsConstMethod(TCppMethod_t)
RPY_EXPORTED bool HasComplexHierarchy(TCppType_t type)
RPY_EXPORTED std::vector< TCppScope_t > GetUsingNamespaces(TCppScope_t)
size_t TCppScope_t
Definition cpp_cppyy.h:18
RPY_EXPORTED bool IsTemplatedConstructor(TCppScope_t scope, TCppIndex_t imeth)
RPY_EXPORTED TCppIndex_t GetGlobalOperator(TCppType_t scope, const std::string &lc, const std::string &rc, const std::string &op)
RPY_EXPORTED TCppFuncAddr_t GetFunctionAddress(TCppMethod_t method, bool check_enabled=true)
RPY_EXPORTED TCppIndex_t GetNumEnumData(TCppEnum_t)
RPY_EXPORTED TCppIndex_t GetNumBases(TCppType_t type)
RPY_EXPORTED TCppIndex_t GetNumBasesLongestBranch(TCppType_t type)
Retrieve number of base classes in the longest branch of the inheritance tree.
RPY_EXPORTED std::string GetMethodPrototype(TCppScope_t scope, TCppMethod_t, bool show_formalargs)
RPY_EXPORTED std::string GetMethodResultType(TCppMethod_t)
RPY_EXPORTED std::string GetFinalName(TCppType_t type)
RPY_EXPORTED char * CallS(TCppMethod_t method, TCppObject_t self, size_t nargs, void *args, size_t *length)
RPY_EXPORTED std::string GetMethodArgDefault(TCppMethod_t, TCppIndex_t iarg)
RPY_EXPORTED bool IsMethodTemplate(TCppScope_t scope, TCppIndex_t imeth)
RPY_EXPORTED std::string GetDatamemberName(TCppScope_t scope, TCppIndex_t idata)
RPY_EXPORTED bool IsPublicMethod(TCppMethod_t method)
RPY_EXPORTED intptr_t GetDatamemberOffset(TCppScope_t scope, TCppIndex_t idata)
void * TCppFuncAddr_t
Definition cpp_cppyy.h:25
RPY_EXPORTED std::string GetMethodFullName(TCppMethod_t)
RPY_EXPORTED short CallH(TCppMethod_t method, TCppObject_t self, size_t nargs, void *args)
RPY_EXPORTED bool IsProtectedMethod(TCppMethod_t method)
RPY_EXPORTED TCppEnum_t GetEnum(TCppScope_t scope, const std::string &enum_name)
void(* DelFunc_t)(void *)
Definition Rtypes.h:111
std::string ResolveTypedef(const char *tname, bool resolveAll=false)
std::string CleanType(const char *typeDesc, int mode=0, const char **tail=nullptr)
Cleanup type description, redundant blanks removed and redundant tail ignored return *tail = pointer ...
std::string ShortType(const char *typeDesc, int mode)
Return the absolute type of typeDesc.
char * DemangleName(const char *mangled_name, int &errorCode)
Definition TClassEdit.h:208
#define RPY_EXTERN
union CPyCppyy::Parameter::Value fValue
const char * fSigName
TMarker m
Definition textangle.C:8