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