[pypy-commit] pypy cling-support: From Aditi: first stab at new Cling backend, based off the C++ Cppyy.cxx
wlav
pypy.commits at gmail.com
Mon Jun 27 17:02:50 EDT 2016
Author: Wim Lavrijsen <WLavrijsen at lbl.gov>
Branch: cling-support
Changeset: r85418:1e669815cd70
Date: 2016-06-27 13:59 -0700
http://bitbucket.org/pypy/pypy/changeset/1e669815cd70/
Log: From Aditi: first stab at new Cling backend, based off the C++
Cppyy.cxx
diff too long, truncating to 2000 out of 3541 lines
diff --git a/.hgignore b/.hgignore
--- a/.hgignore
+++ b/.hgignore
@@ -77,3 +77,5 @@
^.hypothesis/
^release/
^rpython/_cache$
+
+pypy/module/cppyy/.+/*\.pcm
diff --git a/pypy/module/cppyy/bench/Makefile b/pypy/module/cppyy/bench/Makefile
--- a/pypy/module/cppyy/bench/Makefile
+++ b/pypy/module/cppyy/bench/Makefile
@@ -26,4 +26,4 @@
bench02Dict_reflex.so: bench02.h bench02.cxx bench02.xml
$(genreflex) bench02.h $(genreflexflags) --selection=bench02.xml -I$(ROOTSYS)/include
- g++ -o $@ bench02.cxx bench02_rflx.cpp -I$(ROOTSYS)/include -shared -lReflex -lHistPainter `root-config --libs` $(cppflags) $(cppflags2)
+ g++ -o $@ bench02.cxx bench02_rflx.cpp -I$(ROOTSYS)/include -shared -std=c++14 -lHistPainter `root-config --libs` $(cppflags) $(cppflags2)
diff --git a/pypy/module/cppyy/capi/__init__.py b/pypy/module/cppyy/capi/__init__.py
--- a/pypy/module/cppyy/capi/__init__.py
+++ b/pypy/module/cppyy/capi/__init__.py
@@ -9,8 +9,8 @@
# the selection of the desired backend (default is Reflex).
# choose C-API access method:
-from pypy.module.cppyy.capi.loadable_capi import *
-#from pypy.module.cppyy.capi.builtin_capi import *
+#from pypy.module.cppyy.capi.loadable_capi import *
+from pypy.module.cppyy.capi.builtin_capi import *
from pypy.module.cppyy.capi.capi_types import C_OBJECT,\
C_NULL_TYPE, C_NULL_OBJECT
diff --git a/pypy/module/cppyy/capi/builtin_capi.py b/pypy/module/cppyy/capi/builtin_capi.py
--- a/pypy/module/cppyy/capi/builtin_capi.py
+++ b/pypy/module/cppyy/capi/builtin_capi.py
@@ -1,7 +1,8 @@
from rpython.rtyper.lltypesystem import rffi, lltype
from rpython.rlib import jit
-import reflex_capi as backend
+import cling_capi as backend
+#import reflex_capi as backend
#import cint_capi as backend
from pypy.module.cppyy.capi.capi_types import C_SCOPE, C_TYPE, C_OBJECT,\
diff --git a/pypy/module/cppyy/capi/cling_capi.py b/pypy/module/cppyy/capi/cling_capi.py
--- a/pypy/module/cppyy/capi/cling_capi.py
+++ b/pypy/module/cppyy/capi/cling_capi.py
@@ -16,7 +16,8 @@
if os.environ.get("ROOTSYS"):
if config_stat != 0: # presumably Reflex-only
rootincpath = [os.path.join(os.environ["ROOTSYS"], "interpreter/cling/include"),
- os.path.join(os.environ["ROOTSYS"], "interpreter/llvm/inst/include")]
+ os.path.join(os.environ["ROOTSYS"], "interpreter/llvm/inst/include"),
+ os.path.join(os.environ["ROOTSYS"], "include"),]
rootlibpath = [os.path.join(os.environ["ROOTSYS"], "lib64"), os.path.join(os.environ["ROOTSYS"], "lib")]
else:
rootincpath = [incdir]
@@ -39,13 +40,21 @@
std_string_name = 'std::basic_string<char>'
+# force loading (and exposure) of libCore symbols
+with rffi.scoped_str2charp('libCore.so') as ll_libname:
+ _coredll = rdynload.dlopen(ll_libname, rdynload.RTLD_GLOBAL | rdynload.RTLD_NOW)
+
+# require local translator path to pickup common defs
+from rpython.translator import cdir
+translator_c_dir = py.path.local(cdir)
+
eci = ExternalCompilationInfo(
separate_module_files=[srcpath.join("clingcwrapper.cxx")],
- include_dirs=[incpath] + rootincpath,
+ include_dirs=[incpath, translator_c_dir] + rootincpath,
includes=["clingcwrapper.h"],
library_dirs=rootlibpath,
libraries=["Cling"],
- compile_extra=["-fno-strict-aliasing"],
+ compile_extra=["-fno-strict-aliasing", "-std=c++14"],
use_cpp_linker=True,
)
diff --git a/pypy/module/cppyy/converter.py b/pypy/module/cppyy/converter.py
--- a/pypy/module/cppyy/converter.py
+++ b/pypy/module/cppyy/converter.py
@@ -735,7 +735,7 @@
type_info = (
(rffi.LONG, ("long", "long int")),
- (rffi.LONGLONG, ("long long", "long long int")),
+ (rffi.LONGLONG, ("long long", "long long int", "Long64_t")),
)
for c_type, names in type_info:
@@ -743,6 +743,7 @@
_immutable_ = True
def __init__(self, space, default):
self.default = rffi.cast(self.c_type, capi.c_strtoll(space, default))
+
class ConstRefConverter(ConstRefNumericTypeConverterMixin, BasicConverter):
_immutable_ = True
libffitype = jit_libffi.types.pointer
@@ -761,7 +762,7 @@
(rffi.USHORT, ("unsigned short", "unsigned short int")),
(rffi.UINT, ("unsigned", "unsigned int")),
(rffi.ULONG, ("unsigned long", "unsigned long int")),
- (rffi.ULONGLONG, ("unsigned long long", "unsigned long long int")),
+ (rffi.ULONGLONG, ("unsigned long long", "unsigned long long int", "ULong64_t")),
)
for c_type, names in type_info:
diff --git a/pypy/module/cppyy/include/cpp_cppyy.h b/pypy/module/cppyy/include/cpp_cppyy.h
new file mode 100644
--- /dev/null
+++ b/pypy/module/cppyy/include/cpp_cppyy.h
@@ -0,0 +1,143 @@
+#ifndef PYROOT_CPPYY_H
+#define PYROOT_CPPYY_H
+
+// Standard
+#include <string>
+#include <vector>
+#include <stddef.h>
+
+//ROOT types
+ typedef long Long_t;
+ typedef unsigned long ULong_t;
+ typedef long long Long64_t;
+ typedef unsigned long long ULong64_t;
+ typedef float Float_t;
+ typedef double Double_t;
+ typedef long double LongDouble_t;
+ typedef bool Bool_t;
+ typedef char Char_t;
+ typedef unsigned char UChar_t;
+ typedef short Short_t;
+ typedef unsigned short UShort_t;
+ typedef int Int_t;
+ typedef unsigned int UInt_t;
+
+namespace Cppyy {
+ typedef ptrdiff_t TCppScope_t;
+ typedef TCppScope_t TCppType_t;
+ typedef void* TCppObject_t;
+ typedef ptrdiff_t TCppMethod_t;
+
+ typedef Long_t TCppIndex_t;
+ typedef void* (*TCppMethPtrGetter_t)( TCppObject_t );
+
+// name to opaque C++ scope representation -----------------------------------
+ TCppIndex_t GetNumScopes( TCppScope_t parent );
+ std::string GetScopeName( TCppScope_t parent, TCppIndex_t iscope );
+ std::string ResolveName( const std::string& cppitem_name );
+ TCppScope_t GetScope( const std::string& scope_name );
+ TCppType_t GetTemplate( const std::string& template_name );
+ TCppType_t GetActualClass( TCppType_t klass, TCppObject_t obj );
+ size_t SizeOf( TCppType_t klass );
+
+ Bool_t IsBuiltin( const std::string& type_name );
+ Bool_t IsComplete( const std::string& type_name );
+
+ extern TCppScope_t gGlobalScope; // for fast access
+
+// memory management ---------------------------------------------------------
+ TCppObject_t Allocate( TCppType_t type );
+ void Deallocate( TCppType_t type, TCppObject_t instance );
+ TCppObject_t Construct( TCppType_t type );
+ void Destruct( TCppType_t type, TCppObject_t instance );
+
+// method/function dispatching -----------------------------------------------
+ void CallV( TCppMethod_t method, TCppObject_t self, void* args );
+ UChar_t CallB( TCppMethod_t method, TCppObject_t self, void* args );
+ Char_t CallC( TCppMethod_t method, TCppObject_t self, void* args );
+ Short_t CallH( TCppMethod_t method, TCppObject_t self, void* args );
+ Int_t CallI( TCppMethod_t method, TCppObject_t self, void* args );
+ Long_t CallL( TCppMethod_t method, TCppObject_t self, void* args );
+ Long64_t CallLL( TCppMethod_t method, TCppObject_t self, void* args );
+ Float_t CallF( TCppMethod_t method, TCppObject_t self, void* args );
+ Double_t CallD( TCppMethod_t method, TCppObject_t self, void* args );
+ LongDouble_t CallLD( TCppMethod_t method, TCppObject_t self, void* args );
+ void* CallR( TCppMethod_t method, TCppObject_t self, void* args );
+ Char_t* CallS( TCppMethod_t method, TCppObject_t self, void* args );
+ TCppObject_t CallConstructor( TCppMethod_t method, TCppType_t type, void* args );
+ void CallDestructor( TCppType_t type, TCppObject_t self );
+ TCppObject_t CallO( TCppMethod_t method, TCppObject_t self, void* args, TCppType_t result_type );
+
+ TCppMethPtrGetter_t GetMethPtrGetter( TCppScope_t scope, TCppIndex_t imeth );
+
+// handling of function argument buffer --------------------------------------
+ void* AllocateFunctionArgs( size_t nargs );
+ void DeallocateFunctionArgs( void* args );
+ size_t GetFunctionArgSizeof();
+ size_t GetFunctionArgTypeoffset();
+
+// scope reflection information ----------------------------------------------
+ Bool_t IsNamespace( TCppScope_t scope );
+ Bool_t IsAbstract( TCppType_t type );
+ Bool_t IsEnum( const std::string& type_name );
+
+// class reflection information ----------------------------------------------
+ std::string GetFinalName( TCppType_t type );
+ std::string GetScopedFinalName( TCppType_t type );
+ Bool_t HasComplexHierarchy( TCppType_t type );
+ TCppIndex_t GetNumBases( TCppType_t type );
+ std::string GetBaseName( TCppType_t type, TCppIndex_t ibase );
+ Bool_t IsSubtype( TCppType_t derived, TCppType_t base );
+ void AddSmartPtrType( const std::string& );
+ Bool_t IsSmartPtr( const std::string& );
+
+// calculate offsets between declared and actual type, up-cast: direction > 0; down-cast: direction < 0
+ ptrdiff_t GetBaseOffset(
+ TCppType_t derived, TCppType_t base, TCppObject_t address, int direction, bool rerror = false );
+
+// method/function reflection information ------------------------------------
+ TCppIndex_t GetNumMethods( TCppScope_t scope );
+ TCppIndex_t GetMethodIndexAt( TCppScope_t scope, TCppIndex_t imeth );
+ std::vector< TCppMethod_t > GetMethodsFromName( TCppScope_t scope, const std::string& name );
+
+ TCppMethod_t GetMethod( TCppScope_t scope, TCppIndex_t imeth );
+
+ std::string GetMethodName( TCppMethod_t );
+ std::string GetMethodResultType( TCppMethod_t );
+ TCppIndex_t GetMethodNumArgs( TCppMethod_t );
+ TCppIndex_t GetMethodReqArgs( TCppMethod_t );
+ std::string GetMethodArgName( TCppMethod_t, int iarg );
+ std::string GetMethodArgType( TCppMethod_t, int iarg );
+ std::string GetMethodArgDefault( TCppMethod_t, int iarg );
+ std::string GetMethodSignature( TCppScope_t scope, TCppIndex_t imeth );
+ Bool_t IsConstMethod( TCppMethod_t );
+
+ Bool_t IsMethodTemplate( TCppMethod_t );
+ TCppIndex_t GetMethodNumTemplateArgs( TCppScope_t scope, TCppIndex_t imeth );
+ std::string GetMethodTemplateArgName( TCppScope_t scope, TCppIndex_t imeth, TCppIndex_t iarg );
+
+ TCppIndex_t GetGlobalOperator(
+ TCppType_t scope, TCppType_t lc, TCppScope_t rc, const std::string& op );
+
+// method properties ---------------------------------------------------------
+ Bool_t IsConstructor( TCppMethod_t method );
+ Bool_t IsPublicMethod( TCppMethod_t method );
+ Bool_t IsStaticMethod( TCppMethod_t method );
+
+// data member reflection information ----------------------------------------
+ TCppIndex_t GetNumDatamembers( TCppScope_t scope );
+ std::string GetDatamemberName( TCppScope_t scope, TCppIndex_t idata );
+ std::string GetDatamemberType( TCppScope_t scope, TCppIndex_t idata );
+ ptrdiff_t GetDatamemberOffset( TCppScope_t scope, TCppIndex_t idata );
+ TCppIndex_t GetDatamemberIndex( TCppScope_t scope, const std::string& name );
+
+// data member properties ----------------------------------------------------
+ Bool_t IsPublicData( TCppScope_t scope, TCppIndex_t idata );
+ Bool_t IsStaticData( TCppScope_t scope, TCppIndex_t idata );
+ Bool_t IsConstData( TCppScope_t scope, TCppIndex_t idata );
+ Bool_t IsEnumData( TCppScope_t scope, TCppIndex_t idata );
+ Int_t GetDimensionSize( TCppScope_t scope, TCppIndex_t idata, int dimension );
+
+} // namespace Cppyy
+
+#endif // ifndef PYROOT_CPPYY_H
diff --git a/pypy/module/cppyy/include/cppyy.h b/pypy/module/cppyy/include/cppyy.h
--- a/pypy/module/cppyy/include/cppyy.h
+++ b/pypy/module/cppyy/include/cppyy.h
@@ -1,6 +1,8 @@
#ifndef CPPYY_CPPYY
#define CPPYY_CPPYY
+#include "cpp_cppyy.h"
+
#ifdef __cplusplus
struct CPPYY_G__DUMMY_FOR_CINT7 {
#else
diff --git a/pypy/module/cppyy/src/callcontext.h b/pypy/module/cppyy/src/callcontext.h
new file mode 100644
--- /dev/null
+++ b/pypy/module/cppyy/src/callcontext.h
@@ -0,0 +1,101 @@
+#ifndef PYROOT_TCALLCONTEXT_H
+#define PYROOT_TCALLCONTEXT_H
+
+// Standard
+#include <vector>
+
+//Bindings
+#include "cpp_cppyy.h"
+
+//ROOT
+#include "Rtypes.h"
+
+namespace PyROOT {
+
+// general place holder for function parameters
+ struct TParameter {
+ union Value {
+ Bool_t fBool;
+ Short_t fShort;
+ UShort_t fUShort;
+ Int_t fInt;
+ UInt_t fUInt;
+ Long_t fLong;
+ ULong_t fULong;
+ Long64_t fLongLong;
+ ULong64_t fULongLong;
+ Float_t fFloat;
+ Double_t fDouble;
+ LongDouble_t fLongDouble;
+ void* fVoidp;
+ } fValue;
+ void* fRef;
+ char fTypeCode;
+ };
+
+// extra call information
+ struct TCallContext {
+ TCallContext( std::vector< TParameter >::size_type sz = 0 ) : fArgs( sz ), fFlags( 0 ) {}
+
+ enum ECallFlags {
+ kNone = 0,
+ kIsSorted = 1, // if method overload priority determined
+ kIsCreator = 2, // if method creates python-owned objects
+ kIsConstructor = 4, // if method is a C++ constructor
+ kUseHeuristics = 8, // if method applies heuristics memory policy
+ kUseStrict = 16, // if method applies strict memory policy
+ kManageSmartPtr = 32, // if executor should manage smart pointers
+ kReleaseGIL = 64, // if method should release the GIL
+ kFast = 128, // if method should NOT handle signals
+ kSafe = 256 // if method should return on signals
+ };
+
+ // memory handling
+ static ECallFlags sMemoryPolicy;
+ static Bool_t SetMemoryPolicy( ECallFlags e );
+
+ // signal safety
+ static ECallFlags sSignalPolicy;
+ static Bool_t SetSignalPolicy( ECallFlags e );
+
+ // payload
+ std::vector< TParameter > fArgs;
+ UInt_t fFlags;
+ };
+
+ inline Bool_t IsSorted( UInt_t flags ) {
+ return flags & TCallContext::kIsSorted;
+ }
+
+ inline Bool_t IsCreator( UInt_t flags ) {
+ return flags & TCallContext::kIsCreator;
+ }
+
+ inline Bool_t IsConstructor( UInt_t flags ) {
+ return flags & TCallContext::kIsConstructor;
+ }
+
+ inline Bool_t ManagesSmartPtr( TCallContext* ctxt ) {
+ return ctxt->fFlags & TCallContext::kManageSmartPtr;
+ }
+
+ inline Bool_t ReleasesGIL( UInt_t flags ) {
+ return flags & TCallContext::kReleaseGIL;
+ }
+
+ inline Bool_t ReleasesGIL( TCallContext* ctxt ) {
+ return ctxt ? (ctxt->fFlags & TCallContext::kReleaseGIL) : kFALSE;
+ }
+
+ inline Bool_t UseStrictOwnership( TCallContext* ctxt ) {
+ if ( ctxt && (ctxt->fFlags & TCallContext::kUseStrict) )
+ return kTRUE;
+ if ( ctxt && (ctxt->fFlags & TCallContext::kUseHeuristics) )
+ return kFALSE;
+
+ return TCallContext::sMemoryPolicy == TCallContext::kUseStrict;
+ }
+
+} // namespace PyROOT
+
+#endif // !PYROOT_TCALLCONTEXT_H
diff --git a/pypy/module/cppyy/src/clingcwrapper.cxx b/pypy/module/cppyy/src/clingcwrapper.cxx
--- a/pypy/module/cppyy/src/clingcwrapper.cxx
+++ b/pypy/module/cppyy/src/clingcwrapper.cxx
@@ -1,1810 +1,1364 @@
-#include "cppyy.h"
-#include "clingcwrapper.h"
+// Bindings
+#include "capi.h"
+#include "cpp_cppyy.h"
+#include "callcontext.h"
-/*************************************************************************
- * Copyright (C) 1995-2014, the ROOT team. *
- * LICENSE: LGPLv2.1; see http://root.cern.ch/drupal/content/license *
- * CONTRIBUTORS: see http://root.cern.ch/drupal/content/contributors *
- *************************************************************************/
+// ROOT
+#include "TBaseClass.h"
+#include "TClass.h"
+#include "TClassRef.h"
+#include "TClassTable.h"
+#include "TClassEdit.h"
+#include "TCollection.h"
+#include "TDataMember.h"
+#include "TDataType.h"
+#include "TError.h"
+#include "TFunction.h"
+#include "TGlobal.h"
+#include "TInterpreter.h"
+#include "TList.h"
+#include "TMethod.h"
+#include "TMethodArg.h"
+#include "TROOT.h"
-#include <stdint.h>
+// Standard
+#include <assert.h>
+#include <map>
+#include <set>
+#include <sstream>
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/Decl.h"
-#include "clang/AST/DeclBase.h"
-#include "clang/AST/DeclCXX.h"
-#include "clang/AST/PrettyPrinter.h"
-#include "clang/AST/Type.h"
-#include "clang/Frontend/CompilerInstance.h"
-#include "clang/Sema/Sema.h"
+// temp
+#include <iostream>
+typedef PyROOT::TParameter TParameter;
+// --temp
-#include "cling/Interpreter/DynamicLibraryManager.h"
-#include "cling/Interpreter/Interpreter.h"
-#include "cling/Interpreter/LookupHelper.h"
-#include "cling/Interpreter/StoredValueRef.h"
-#include "cling/MetaProcessor/MetaProcessor.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ExecutionEngine/GenericValue.h"
-#include "llvm/Support/raw_ostream.h"
+// small number that allows use of stack for argument passing
+const int SMALL_ARGS_N = 8;
-#include <iostream>
-#include <map>
-#include <string>
-#include <sstream>
-#include <vector>
+// data for life time management ---------------------------------------------
+typedef std::vector< TClassRef > ClassRefs_t;
+static ClassRefs_t g_classrefs( 1 );
+static const ClassRefs_t::size_type GLOBAL_HANDLE = 1;
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
+typedef std::map< std::string, ClassRefs_t::size_type > Name2ClassRefIndex_t;
+static Name2ClassRefIndex_t g_name2classrefidx;
-using namespace clang;
+typedef std::map< Cppyy::TCppMethod_t, CallFunc_t* > Method2CallFunc_t;
+static Method2CallFunc_t g_method2callfunc;
+typedef std::vector< TFunction > GlobalFuncs_t;
+static GlobalFuncs_t g_globalfuncs;
-/* cling initialization --------------------------------------------------- */
+typedef std::vector< TGlobal* > GlobalVars_t;
+static GlobalVars_t g_globalvars;
+
+// data ----------------------------------------------------------------------
+Cppyy::TCppScope_t Cppyy::gGlobalScope = GLOBAL_HANDLE;
+
+// smart pointer types
+static std::set< std::string > gSmartPtrTypes =
+ { "auto_ptr", "shared_ptr", "weak_ptr", "unique_ptr" };
+
+
+// global initialization -----------------------------------------------------
namespace {
-cling::Interpreter* gCppyy_Cling;
-cling::MetaProcessor* gCppyy_MetaProcessor;
+class ApplicationStarter {
+public:
+ ApplicationStarter() {
+ // setup dummy holders for global and std namespaces
+ assert( g_classrefs.size() == GLOBAL_HANDLE );
+ g_name2classrefidx[ "" ] = GLOBAL_HANDLE;
+ g_classrefs.push_back(TClassRef(""));
+ // ROOT ignores std/::std, so point them to the global namespace
+ g_name2classrefidx[ "std" ] = GLOBAL_HANDLE;
+ g_name2classrefidx[ "::std" ] = GLOBAL_HANDLE;
+ // add a dummy global to refer to as null at index 0
+ g_globalvars.push_back( nullptr );
+ }
-struct Cppyy_InitCling { // TODO: check whether ROOT/meta's TCling is linked in
- Cppyy_InitCling() {
- std::vector<std::string> cling_args_storage;
- cling_args_storage.push_back("cling4cppyy");
-
- // TODO: get this from env
- cling_args_storage.push_back("-I/home/wlavrijsen/rootdev/root/etc");
-
- std::vector<const char*> interp_args;
- for (std::vector<std::string>::const_iterator iarg = cling_args_storage.begin();
- iarg != cling_args_storage.end(); ++iarg)
- interp_args.push_back(iarg->c_str());
-
- // TODO: get this from env
- const char* llvm_resource_dir = "/home/wlavrijsen/rootdev/root/etc/cling";
- gCppyy_Cling = new cling::Interpreter(
- interp_args.size(), &(interp_args[0]), llvm_resource_dir);
-
- // fInterpreter->installLazyFunctionCreator(llvmLazyFunctionCreator);
-
- {
- // R__LOCKGUARD(gInterpreterMutex);
- gCppyy_Cling->AddIncludePath("/home/wlavrijsen/rootdev/root/etc/cling");
- gCppyy_Cling->AddIncludePath(".");
- }
-
- // don't check whether modules' files exist.
- gCppyy_Cling->getCI()->getPreprocessorOpts().DisablePCHValidation = true;
-
- // Use a stream that doesn't close its file descriptor.
- static llvm::raw_fd_ostream fMPOuts (STDOUT_FILENO, /* ShouldClose */ false);
- gCppyy_MetaProcessor = new cling::MetaProcessor(*gCppyy_Cling, fMPOuts);
-
- gCppyy_Cling->enableDynamicLookup();
- }
-} _init;
-
-typedef std::map<std::string, cppyy_scope_t> NamedHandles_t;
-static NamedHandles_t s_named;
-
-struct SimpleScope {
- std::vector<FunctionDecl*> m_methods;
- std::vector<Decl*> m_data;
-};
-
-typedef std::map<cppyy_scope_t, SimpleScope*> Scopes_t;
-static Scopes_t s_scopes;
-
-typedef std::map<cppyy_method_t, CPPYY_Cling_Wrapper_t> Wrappers_t;
-static Wrappers_t s_wrappers;
+ ~ApplicationStarter() {
+ for ( auto ifunc : g_method2callfunc )
+ gInterpreter->CallFunc_Delete( ifunc.second );
+ }
+} _applicationStarter;
} // unnamed namespace
-
-/* local helpers --------------------------------------------------------- */
-static inline void print_error(const std::string& where, const std::string& what) {
- std::cerr << where << ": " << what << std::endl;
+// local helpers -------------------------------------------------------------
+static inline
+TClassRef& type_from_handle( Cppyy::TCppScope_t scope )
+{
+ assert( (ClassRefs_t::size_type) scope < g_classrefs.size() );
+ return g_classrefs[ (ClassRefs_t::size_type)scope ];
}
-static inline char* cppstring_to_cstring(const std::string& name) {
+// type_from_handle to go here
+static inline
+TFunction* type_get_method( Cppyy::TCppType_t klass, Cppyy::TCppIndex_t idx )
+{
+ TClassRef& cr = type_from_handle( klass );
+ if ( cr.GetClass() )
+ return (TFunction*)cr->GetListOfMethods()->At( idx );
+ assert( klass == (Cppyy::TCppType_t)GLOBAL_HANDLE );
+ return (TFunction*)idx;
+}
+
+static inline
+Cppyy::TCppScope_t declaring_scope( Cppyy::TCppMethod_t method )
+{
+ TMethod* m = dynamic_cast<TMethod*>( (TFunction*)method );
+ if ( m ) return Cppyy::GetScope( m->GetClass()->GetName() );
+ return (Cppyy::TCppScope_t)GLOBAL_HANDLE;
+}
+
+static inline
+char* cppstring_to_cstring(const std::string& name) {
char* name_char = (char*)malloc(name.size() + 1);
strcpy(name_char, name.c_str());
return name_char;
}
-static inline SimpleScope* scope_from_handle(cppyy_type_t handle) {
- return s_scopes[(cppyy_scope_t)handle];
+
+// name to opaque C++ scope representation -----------------------------------
+Cppyy::TCppIndex_t Cppyy::GetNumScopes( TCppScope_t scope )
+{
+ TClassRef& cr = type_from_handle( scope );
+ if ( cr.GetClass() ) return 0; // not supported if not at global scope
+ assert( scope == (TCppScope_t)GLOBAL_HANDLE );
+ return gClassTable->Classes();
}
-static inline std::string qualtype_to_string(const QualType& qt, const ASTContext& atx) {
- std::string result;
-
- PrintingPolicy policy(atx.getPrintingPolicy());
- policy.SuppressTagKeyword = true; // no class or struct keyword
- policy.SuppressScope = true; // force scope from a clang::ElaboratedType
- policy.AnonymousTagLocations = false; // no file name + line number for anonymous types
- // The scope suppression is required for getting rid of the anonymous part of the name
- // of a class defined in an anonymous namespace.
-
- qt.getAsStringInternal(result, policy);
- return result;
+std::string Cppyy::GetScopeName( TCppScope_t parent, TCppIndex_t iscope )
+{
+// Retrieve the scope name of the scope indexed with iscope in parent.
+ TClassRef& cr = type_from_handle( parent );
+ if ( cr.GetClass() ) return 0; // not supported if not at global scope
+ assert( parent == (TCppScope_t)GLOBAL_HANDLE );
+ std::string name = gClassTable->At( iscope );
+ if ( name.find("::") == std::string::npos )
+ return name;
+ return "";
}
-static inline std::vector<void*> build_args(int nargs, void* args) {
- std::vector<void*> arguments;
- arguments.reserve(nargs);
- for (int i = 0; i < nargs; ++i) {
- char tc = ((CPPYY_G__value*)args)[i].type;
- if (tc != 'a' && tc != 'o')
- arguments.push_back(&((CPPYY_G__value*)args)[i]);
- else
- arguments.push_back((void*)(*(long*)&((CPPYY_G__value*)args)[i]));
- }
- return arguments;
+std::string Cppyy::ResolveName( const std::string& cppitem_name )
+{
+// Fully resolve the given name to the final type name.
+ std::string tclean = TClassEdit::CleanType( cppitem_name.c_str() );
+
+ TDataType* dt = gROOT->GetType( tclean.c_str() );
+ if ( dt ) return dt->GetFullTypeName();
+ return TClassEdit::ResolveTypedef( tclean.c_str(), true );
}
+Cppyy::TCppScope_t Cppyy::GetScope( const std::string& sname )
+{
+ std::string scope_name;
+ if ( sname.find( "std::", 0, 5 ) == 0 )
+ scope_name = sname.substr( 5, std::string::npos );
+ else
+ scope_name = sname;
+ scope_name = ResolveName( scope_name );
+ auto icr = g_name2classrefidx.find( scope_name );
+ if ( icr != g_name2classrefidx.end() )
+ return (TCppType_t)icr->second;
+
+ // use TClass directly, to enable auto-loading
+ TClassRef cr( TClass::GetClass( scope_name.c_str(), kTRUE, kTRUE ) );
+ if ( !cr.GetClass() )
+ return (TCppScope_t)NULL;
+
+ // no check for ClassInfo as forward declared classes are okay (fragile)
+
+ ClassRefs_t::size_type sz = g_classrefs.size();
+ g_name2classrefidx[ scope_name ] = sz;
+ g_classrefs.push_back( TClassRef( scope_name.c_str() ) );
+ return (TCppScope_t)sz;
+}
+
+Cppyy::TCppType_t Cppyy::GetTemplate( const std::string& /* template_name */ )
+{
+ return (TCppType_t)0;
+}
+
+Cppyy::TCppType_t Cppyy::GetActualClass( TCppType_t klass, TCppObject_t obj )
+{
+ TClassRef& cr = type_from_handle( klass );
+ TClass* clActual = cr->GetActualClass( (void*)obj );
+ if ( clActual && clActual != cr.GetClass() ) {
+ // TODO: lookup through name should not be needed
+ return (TCppType_t)GetScope( clActual->GetName() );
+ }
+ return klass;
+}
+
+size_t Cppyy::SizeOf( TCppType_t klass )
+{
+ TClassRef& cr = type_from_handle( klass );
+ if ( cr.GetClass() ) return (size_t)cr->Size();
+ return (size_t)0;
+}
+
+Bool_t Cppyy::IsBuiltin( const std::string& type_name )
+{
+ TDataType* dt = gROOT->GetType( TClassEdit::CleanType( type_name.c_str(), 1 ).c_str() );
+ if ( dt ) return dt->GetType() != kOther_t;
+ return kFALSE;
+}
+
+Bool_t Cppyy::IsComplete( const std::string& type_name )
+{
+// verify whether the dictionary of this class is fully available
+ Bool_t b = kFALSE;
+
+ Int_t oldEIL = gErrorIgnoreLevel;
+ gErrorIgnoreLevel = 3000;
+ TClass* klass = TClass::GetClass( TClassEdit::ShortType( type_name.c_str(), 1 ).c_str() );
+ if ( klass && klass->GetClassInfo() ) // works for normal case w/ dict
+ b = gInterpreter->ClassInfo_IsLoaded( klass->GetClassInfo() );
+ else { // special case for forward declared classes
+ ClassInfo_t* ci = gInterpreter->ClassInfo_Factory( type_name.c_str() );
+ if ( ci ) {
+ b = gInterpreter->ClassInfo_IsLoaded( ci );
+ gInterpreter->ClassInfo_Delete( ci ); // we own the fresh class info
+ }
+ }
+ gErrorIgnoreLevel = oldEIL;
+ return b;
+}
+
+// memory management ---------------------------------------------------------
+Cppyy::TCppObject_t Cppyy::Allocate( TCppType_t type )
+{
+ TClassRef& cr = type_from_handle( type );
+ return (TCppObject_t)malloc( cr->Size() );
+}
+
+void Cppyy::Deallocate( TCppType_t /* type */, TCppObject_t instance )
+{
+ free( instance );
+}
+
+Cppyy::TCppObject_t Cppyy::Construct( TCppType_t type )
+{
+ TClassRef& cr = type_from_handle( type );
+ return (TCppObject_t)cr->New();
+}
+
+void Cppyy::Destruct( TCppType_t type, TCppObject_t instance )
+{
+ TClassRef& cr = type_from_handle( type );
+ cr->Destructor( (void*)instance );
+}
+
+
+// method/function dispatching -----------------------------------------------
+static inline ClassInfo_t* GetGlobalNamespaceInfo()
+{
+ static ClassInfo_t* gcl = gInterpreter->ClassInfo_Factory();
+ return gcl;
+}
+
+static CallFunc_t* GetCallFunc( Cppyy::TCppMethod_t method )
+{
+ auto icf = g_method2callfunc.find( method );
+ if ( icf != g_method2callfunc.end() )
+ return icf->second;
+
+ CallFunc_t* callf = nullptr;
+ TFunction* func = (TFunction*)method;
+ std::string callString = "";
+
+// create, if not cached
+ Cppyy::TCppScope_t scope = declaring_scope( method );
+ const TClassRef& klass = type_from_handle( scope );
+ if ( klass.GetClass() || (func && scope == GLOBAL_HANDLE) ) {
+ ClassInfo_t* gcl = klass.GetClass() ? klass->GetClassInfo() : nullptr;
+ if ( ! gcl )
+ gcl = GetGlobalNamespaceInfo();
+
+ TCollection* method_args = func->GetListOfMethodArgs();
+ TIter iarg( method_args );
+
+ TMethodArg* method_arg = 0;
+ while ((method_arg = (TMethodArg*)iarg.Next())) {
+ std::string fullType = method_arg->GetTypeNormalizedName();
+ if ( callString.empty() )
+ callString = fullType;
+ else
+ callString += ", " + fullType;
+ }
+
+ Long_t offset = 0;
+ callf = gInterpreter->CallFunc_Factory();
+
+ gInterpreter->CallFunc_SetFuncProto(
+ callf,
+ gcl,
+ func ? func->GetName() : klass->GetName(),
+ callString.c_str(),
+ func ? (func->Property() & kIsConstMethod) : kFALSE,
+ &offset,
+ ROOT::kExactMatch );
+
+// CLING WORKAROUND -- The number of arguments is not always correct (e.g. when there
+// are default parameters, causing the callString to be wrong and
+// the exact match to fail); or the method may have been inline or
+// be compiler generated. In all those cases the exact match fails,
+// whereas the conversion match sometimes works.
+ if ( ! gInterpreter->CallFunc_IsValid( callf ) ) {
+ gInterpreter->CallFunc_SetFuncProto(
+ callf,
+ gcl,
+ func ? func->GetName() : klass->GetName(),
+ callString.c_str(),
+ func ? (func->Property() & kIsConstMethod) : kFALSE,
+ &offset ); // <- no kExactMatch as that will fail
+ }
+// -- CLING WORKAROUND
+
+ }
+
+ if ( !( callf && gInterpreter->CallFunc_IsValid( callf ) ) ) {
+ // TODO: propagate this error to caller w/o use of Python C-API
+ /*
+ PyErr_Format( PyExc_RuntimeError, "could not resolve %s::%s(%s)",
+ const_cast<TClassRef&>(klass).GetClassName(),
+ func ? func->GetName() : const_cast<TClassRef&>(klass).GetClassName(),
+ callString.c_str() ); */
+ std::cerr << "TODO: report unresolved function error to Python\n";
+ if ( callf ) gInterpreter->CallFunc_Delete( callf );
+ return nullptr;
+ }
+
+ g_method2callfunc[ method ] = callf;
+ return callf;
+}
+
+static inline void copy_args( void* args_, void** vargs ) {
+ std::vector<TParameter>& args = *(std::vector<TParameter>*)args_;
+ for ( std::vector<TParameter>::size_type i = 0; i < args.size(); ++i ) {
+ switch ( args[i].fTypeCode ) {
+ case 'l': /* long */
+ vargs[i] = (void*)&args[i].fValue.fLong;
+ break;
+ case 'f': /* double */
+ vargs[i] = (void*)&args[i].fValue.fFloat;
+ break;
+ case 'd': /* double */
+ vargs[i] = (void*)&args[i].fValue.fDouble;
+ break;
+ case 'D': /* long double */
+ vargs[i] = (void*)&args[i].fValue.fLongDouble;
+ break;
+ case 'k': /* long long */
+ case 'K': /* unsigned long long */
+ case 'U': /* unsigned long */
+ case 'p': /* void* */
+ vargs[i] = (void*)&args[i].fValue.fVoidp;
+ break;
+ case 'V': /* (void*)type& */
+ vargs[i] = args[i].fValue.fVoidp;
+ break;
+ case 'r': /* const type& */
+ vargs[i] = args[i].fRef;
+ break;
+ default:
+ std::cerr << "unknown type code: " << args[i].fTypeCode << std::endl;
+ break;
+ }
+ }
+}
+
+Bool_t FastCall(
+ Cppyy::TCppMethod_t method, void* args_, void* self, void* result )
+{
+ const std::vector<TParameter>& args = *(std::vector<TParameter>*)args_;
+
+ CallFunc_t* callf = GetCallFunc( method );
+ if ( ! callf )
+ return kFALSE;
+
+ TInterpreter::CallFuncIFacePtr_t faceptr = gCling->CallFunc_IFacePtr( callf );
+ if ( faceptr.fKind == TInterpreter::CallFuncIFacePtr_t::kGeneric ) {
+ if ( args.size() <= SMALL_ARGS_N ) {
+ void* smallbuf[SMALL_ARGS_N];
+ copy_args( args_, smallbuf );
+ faceptr.fGeneric( self, args.size(), smallbuf, result );
+ } else {
+ std::vector<void*> buf( args.size() );
+ copy_args( args_, buf.data() );
+ faceptr.fGeneric( self, args.size(), buf.data(), result );
+ }
+ return kTRUE;
+ }
+
+ if ( faceptr.fKind == TInterpreter::CallFuncIFacePtr_t::kCtor ) {
+ if ( args.size() <= SMALL_ARGS_N ) {
+ void* smallbuf[SMALL_ARGS_N];
+ copy_args( args_, (void**)smallbuf );
+ faceptr.fCtor( (void**)smallbuf, result, args.size() );
+ } else {
+ std::vector<void*> buf( args.size() );
+ copy_args( args_, buf.data() );
+ faceptr.fCtor( buf.data(), result, args.size() );
+ }
+ return kTRUE;
+ }
+
+ if ( faceptr.fKind == TInterpreter::CallFuncIFacePtr_t::kDtor ) {
+ std::cerr << " DESTRUCTOR NOT IMPLEMENTED YET! " << std::endl;
+ return kFALSE;
+ }
+
+ return kFALSE;
+}
+
+template< typename T >
+static inline T CallT( Cppyy::TCppMethod_t method, Cppyy::TCppObject_t self, void* args )
+{
+ T t{};
+ if ( FastCall( method, args, (void*)self, &t ) )
+ return t;
+ return (T)-1;
+}
+
+#define CPPYY_IMP_CALL( typecode, rtype ) \
+rtype Cppyy::Call##typecode( TCppMethod_t method, TCppObject_t self, void* args )\
+{ \
+ return CallT< rtype >( method, self, args ); \
+}
+
+void Cppyy::CallV( TCppMethod_t method, TCppObject_t self, void* args )
+{
+ if ( ! FastCall( method, args, (void*)self, nullptr ) )
+ return /* TODO ... report error */;
+}
+
+CPPYY_IMP_CALL( B, UChar_t )
+CPPYY_IMP_CALL( C, Char_t )
+CPPYY_IMP_CALL( H, Short_t )
+CPPYY_IMP_CALL( I, Int_t )
+CPPYY_IMP_CALL( L, Long_t )
+CPPYY_IMP_CALL( LL, Long64_t )
+CPPYY_IMP_CALL( F, Float_t )
+CPPYY_IMP_CALL( D, Double_t )
+CPPYY_IMP_CALL( LD, LongDouble_t )
+
+void* Cppyy::CallR( TCppMethod_t method, TCppObject_t self, void* args )
+{
+ void* r = nullptr;
+ if ( FastCall( method, args, (void*)self, &r ) )
+ return r;
+ return nullptr;
+}
+
+Char_t* Cppyy::CallS( TCppMethod_t method, TCppObject_t self, void* args )
+{
+ Char_t* s = nullptr;
+ if ( FastCall( method, args, (void*)self, &s ) )
+ return s;
+ return nullptr;
+}
+
+Cppyy::TCppObject_t Cppyy::CallConstructor(
+ TCppMethod_t method, TCppType_t /* klass */, void* args ) {
+ void* obj = nullptr;
+ if ( FastCall( method, args, nullptr, &obj ) )
+ return (TCppObject_t)obj;
+ return (TCppObject_t)0;
+}
+
+void Cppyy::CallDestructor( TCppType_t type, TCppObject_t self )
+{
+ TClassRef& cr = type_from_handle( type );
+ cr->Destructor( (void*)self, kTRUE );
+}
+
+Cppyy::TCppObject_t Cppyy::CallO( TCppMethod_t method,
+ TCppObject_t self, void* args, TCppType_t result_type )
+{
+ TClassRef& cr = type_from_handle( result_type );
+ void* obj = malloc( cr->Size() );
+ if ( FastCall( method, args, self, obj ) )
+ return (TCppObject_t)obj;
+ return (TCppObject_t)0;
+}
+
+Cppyy::TCppMethPtrGetter_t Cppyy::GetMethPtrGetter(
+ TCppScope_t /* scope */, TCppIndex_t /* imeth */ )
+{
+ return (TCppMethPtrGetter_t)0;
+}
+
+
+// handling of function argument buffer --------------------------------------
+void* Cppyy::AllocateFunctionArgs( size_t nargs )
+{
+ return new TParameter[nargs];
+}
+
+void Cppyy::DeallocateFunctionArgs( void* args )
+{
+ delete [] (TParameter*)args;
+}
+
+size_t Cppyy::GetFunctionArgSizeof()
+{
+ return sizeof( TParameter );
+}
+
+size_t Cppyy::GetFunctionArgTypeoffset()
+{
+ return offsetof( TParameter, fTypeCode );
+}
+
+
+// scope reflection information ----------------------------------------------
+Bool_t Cppyy::IsNamespace( TCppScope_t scope ) {
+// Test if this scope represents a namespace.
+ TClassRef& cr = type_from_handle( scope );
+ if ( cr.GetClass() )
+ return cr->Property() & kIsNamespace;
+ return kFALSE;
+}
+
+Bool_t Cppyy::IsAbstract( TCppType_t klass ) {
+// Test if this type may not be instantiated.
+ TClassRef& cr = type_from_handle( klass );
+ if ( cr.GetClass() )
+ return cr->Property() & kIsAbstract;
+ return kFALSE;
+}
+
+Bool_t Cppyy::IsEnum( const std::string& type_name ) {
+ return gInterpreter->ClassInfo_IsEnum( type_name.c_str() );
+}
+
+
+// class reflection information ----------------------------------------------
+std::string Cppyy::GetFinalName( TCppType_t klass )
+{
+ if ( klass == GLOBAL_HANDLE ) // due to CLING WORKAROUND in InitConverters_
+ return "";
+ // TODO: either this or GetScopedFinalName is wrong
+ TClassRef& cr = type_from_handle( klass );
+ return cr->GetName();
+}
+
+std::string Cppyy::GetScopedFinalName( TCppType_t klass )
+{
+ // TODO: either this or GetFinalName is wrong
+ TClassRef& cr = type_from_handle( klass );
+ return cr->GetName();
+}
+
+Bool_t Cppyy::HasComplexHierarchy( TCppType_t /* handle */ )
+{
+// Always TRUE for now (pre-empts certain optimizations).
+ return kTRUE;
+}
+
+Cppyy::TCppIndex_t Cppyy::GetNumBases( TCppType_t klass )
+{
+// Get the total number of base classes that this class has.
+ TClassRef& cr = type_from_handle( klass );
+ if ( cr.GetClass() && cr->GetListOfBases() != 0 )
+ return cr->GetListOfBases()->GetSize();
+ return 0;
+}
+
+std::string Cppyy::GetBaseName( TCppType_t klass, TCppIndex_t ibase )
+{
+ TClassRef& cr = type_from_handle( klass );
+ return ((TBaseClass*)cr->GetListOfBases()->At( ibase ))->GetName();
+}
+
+Bool_t Cppyy::IsSubtype( TCppType_t derived, TCppType_t base )
+{
+ if ( derived == base )
+ return kTRUE;
+ TClassRef& derived_type = type_from_handle( derived );
+ TClassRef& base_type = type_from_handle( base );
+ return derived_type->GetBaseClass( base_type ) != 0;
+}
+
+void Cppyy::AddSmartPtrType( const std::string& type_name ) {
+ gSmartPtrTypes.insert( ResolveName( type_name ) );
+}
+
+Bool_t Cppyy::IsSmartPtr( const std::string& type_name ) {
+// checks if typename denotes a smart pointer
+// TODO: perhaps make this stricter?
+ const std::string& real_name = ResolveName( type_name );
+ return gSmartPtrTypes.find(
+ real_name.substr( 0,real_name.find( "<" ) ) ) != gSmartPtrTypes.end();
+}
+
+// type offsets --------------------------------------------------------------
+ptrdiff_t Cppyy::GetBaseOffset( TCppType_t derived, TCppType_t base,
+ TCppObject_t address, int direction, bool rerror )
+{
+// calculate offsets between declared and actual type, up-cast: direction > 0; down-cast: direction < 0
+ if ( derived == base || !(base && derived) )
+ return (ptrdiff_t)0;
+
+ TClassRef& cd = type_from_handle( derived );
+ TClassRef& cb = type_from_handle( base );
+
+ if ( !cd.GetClass() || !cb.GetClass() )
+ return (ptrdiff_t)0;
+
+ Long_t offset = -1;
+ if ( ! (cd->GetClassInfo() && cb->GetClassInfo()) ) { // gInterpreter requirement
+ // would like to warn, but can't quite determine error from intentional
+ // hiding by developers, so only cover the case where we really should have
+ // had a class info, but apparently don't:
+ if ( cd->IsLoaded() ) {
+ // warn to allow diagnostics
+ std::ostringstream msg;
+ msg << "failed offset calculation between " << cb->GetName() << " and " << cd->GetName();
+ // TODO: propagate this warning to caller w/o use of Python C-API
+ // PyErr_Warn( PyExc_RuntimeWarning, const_cast<char*>( msg.str().c_str() ) );
+ std::cerr << "Warning: " << msg << '\n';
+ }
+
+ // return -1 to signal caller NOT to apply offset
+ return rerror ? (ptrdiff_t)offset : 0;
+ }
+
+ offset = gInterpreter->ClassInfo_GetBaseOffset(
+ cd->GetClassInfo(), cb->GetClassInfo(), (void*)address, direction > 0 );
+ if ( offset == -1 ) // Cling error, treat silently
+ return rerror ? (ptrdiff_t)offset : 0;
+
+ return (ptrdiff_t)(direction < 0 ? -offset : offset);
+}
+
+
+// method/function reflection information ------------------------------------
+Cppyy::TCppIndex_t Cppyy::GetNumMethods( TCppScope_t scope )
+{
+ TClassRef& cr = type_from_handle( scope );
+ if ( cr.GetClass() && cr->GetListOfMethods() ) {
+ Cppyy::TCppIndex_t nMethods = (TCppIndex_t)cr->GetListOfMethods()->GetSize();
+ if ( nMethods == (TCppIndex_t)0 ) {
+ std::string clName = GetScopedFinalName( scope );
+ if ( clName.find( '<' ) != std::string::npos ) {
+ // chicken-and-egg problem: TClass does not know about methods until instantiation: force it
+ if ( TClass::GetClass( ("std::" + clName).c_str() ) )
+ clName = "std::" + clName;
+ std::ostringstream stmt;
+ stmt << "template class " << clName << ";";
+ gInterpreter->Declare( stmt.str().c_str() );
+ // now reload the methods
+ return (TCppIndex_t)cr->GetListOfMethods( kTRUE )->GetSize();
+ }
+ }
+ return nMethods;
+ } else if ( scope == (TCppScope_t)GLOBAL_HANDLE ) {
+ // enforce lazines by denying the existence of methods
+ return (TCppIndex_t)0;
+ }
+ return (TCppIndex_t)0;
+}
+
+Cppyy::TCppIndex_t Cppyy::GetMethodIndexAt( TCppScope_t scope, TCppIndex_t imeth)
+{
+ TClassRef& cr = type_from_handle (scope);
+ if (cr.GetClass())
+ return (TCppIndex_t)imeth;
+ assert(handle == (TCppType_t)GLOBAL_HANDLE);
+ return (TCppIndex_t)&g_globalfuncs[imeth];
+}
+
+std::vector< Cppyy::TCppMethod_t > Cppyy::GetMethodsFromName(
+ TCppScope_t scope, const std::string& name )
+{
+// TODO: this method assumes that the call for this name is made only
+// once, and thus there is no need to store the results of the search
+// in g_globalfuncs ... probably true, but needs verification
+ std::vector< TCppMethod_t > methods;
+ if ( scope == GLOBAL_HANDLE ) {
+ TCollection* funcs = gROOT->GetListOfGlobalFunctions( kTRUE );
+ g_globalfuncs.reserve(funcs->GetSize());
+
+ TIter ifunc(funcs);
+
+ TFunction* func = 0;
+ while ( (func = (TFunction*)ifunc.Next()) ) {
+ // cover not only direct matches, but also template matches
+ std::string fn = func->GetName();
+ if ( fn.rfind( name, 0 ) == 0 ) {
+ // either match exactly, or match the name as template
+ if ( (name.size() == fn.size()) ||
+ (name.size() < fn.size() && fn[name.size()] == '<') ) {
+ methods.push_back( (TCppMethod_t)func );
+ }
+ }
+ }
+ } else {
+ TClassRef& cr = type_from_handle( scope );
+ if ( cr.GetClass() ) {
+ // todo: handle overloads
+ TMethod* m = cr->GetMethodAny( name.c_str() );
+ if ( m ) methods.push_back( (TCppMethod_t)m );
+ }
+ }
+
+ return methods;
+}
+
+Cppyy::TCppMethod_t Cppyy::GetMethod( TCppScope_t scope, TCppIndex_t imeth )
+{
+ TFunction* f = type_get_method( scope, imeth );
+ return (Cppyy::TCppMethod_t)f;
+}
+
+std::string Cppyy::GetMethodName( TCppMethod_t method )
+{
+ if ( method ) {
+ std::string name = ((TFunction*)method)->GetName();
+ //if ( IsMethodTemplate( method ) )
+ // return name.substr( 0, name.find('<') );
+ return name;
+ }
+ return "<unknown>";
+}
+
+std::string Cppyy::GetMethodResultType( TCppMethod_t method )
+{
+ if ( method ) {
+ TFunction* f = (TFunction*)method;
+ if ( f->ExtraProperty() & kIsConstructor )
+ return "constructor";
+ return f->GetReturnTypeNormalizedName();
+ }
+ return "<unknown>";
+}
+
+Cppyy::TCppIndex_t Cppyy::GetMethodNumArgs( TCppMethod_t method )
+{
+ if ( method )
+ return ((TFunction*)method)->GetNargs();
+ return 0;
+}
+
+Cppyy::TCppIndex_t Cppyy::GetMethodReqArgs( TCppMethod_t method )
+{
+ if ( method ) {
+ TFunction* f = (TFunction*)method;
+ return (TCppIndex_t)(f->GetNargs() - f->GetNargsOpt());
+ }
+ return (TCppIndex_t)0;
+}
+
+std::string Cppyy::GetMethodArgName( TCppMethod_t method, int iarg )
+{
+ if ( method ) {
+ TFunction* f = (TFunction*)method;
+ TMethodArg* arg = (TMethodArg*)f->GetListOfMethodArgs()->At( iarg );
+ return arg->GetName();
+ }
+ return "<unknown>";
+}
+
+std::string Cppyy::GetMethodArgType( TCppMethod_t method, int iarg )
+{
+ if ( method ) {
+ TFunction* f = (TFunction*)method;
+ TMethodArg* arg = (TMethodArg*)f->GetListOfMethodArgs()->At( iarg );
+ return arg->GetTypeNormalizedName();
+ }
+ return "<unknown>";
+}
+
+std::string Cppyy::GetMethodArgDefault( TCppMethod_t method, int iarg )
+{
+ if ( method ) {
+ TFunction* f = (TFunction*)method;
+ TMethodArg* arg = (TMethodArg*)f->GetListOfMethodArgs()->At( iarg );
+ const char* def = arg->GetDefault();
+ if ( def )
+ return def;
+ }
+
+ return "";
+}
+
+std::string Cppyy::GetMethodSignature( TCppScope_t /* scope */, TCppIndex_t /* imeth */ )
+{
+ return "<unknown>";
+}
+
+Bool_t Cppyy::IsConstMethod( TCppMethod_t method )
+{
+ if ( method ) {
+ TFunction* f = (TFunction*)method;
+ return f->Property() & kIsConstMethod;
+ }
+ return kFALSE;
+}
+
+
+Bool_t Cppyy::IsMethodTemplate( TCppMethod_t method )
+{
+ if ( method ) {
+ TFunction* f = (TFunction*)method;
+ std::string name = f->GetName();
+ return (name[name.size()-1] == '>') && (name.find('<') != std::string::npos);
+ }
+ return kFALSE;
+}
+
+Cppyy::TCppIndex_t Cppyy::GetMethodNumTemplateArgs(
+ TCppScope_t /* scope */, TCppIndex_t /* imeth */ )
+{
+ return (TCppIndex_t)0;
+}
+
+std::string Cppyy::GetMethodTemplateArgName(
+ TCppScope_t /* scope */, TCppIndex_t /* imeth */, TCppIndex_t /* iarg */ )
+{
+ return "<unknown>";
+}
+
+Cppyy::TCppIndex_t Cppyy::GetGlobalOperator(
+ TCppScope_t /* scope */, TCppType_t /* lc */, TCppType_t /* rc */, const std::string& /* op */ )
+{
+ return (TCppIndex_t)0;
+}
+
+// method properties ---------------------------------------------------------
+Bool_t Cppyy::IsConstructor( TCppMethod_t method )
+{
+ if ( method ) {
+ TFunction* f = (TFunction*)method;
+ return f->ExtraProperty() & kIsConstructor;
+ }
+ return kFALSE;
+}
+
+Bool_t Cppyy::IsPublicMethod( TCppMethod_t method )
+{
+ if ( method ) {
+ TFunction* f = (TFunction*)method;
+ return f->Property() & kIsPublic;
+ }
+ return kFALSE;
+}
+
+Bool_t Cppyy::IsStaticMethod( TCppMethod_t method )
+{
+ if ( method ) {
+ TFunction* f = (TFunction*)method;
+ return f->Property() & kIsStatic;
+ }
+ return kFALSE;
+}
+
+// data member reflection information ----------------------------------------
+Cppyy::TCppIndex_t Cppyy::GetNumDatamembers( TCppScope_t scope )
+{
+ TClassRef& cr = type_from_handle( scope );
+ if ( cr.GetClass() && cr->GetListOfDataMembers() )
+ return cr->GetListOfDataMembers()->GetSize();
+ else if ( scope == (TCppScope_t)GLOBAL_HANDLE ) {
+ std::cerr << " global data should be retrieved lazily " << std::endl;
+ TCollection* vars = gROOT->GetListOfGlobals( kTRUE );
+ if ( g_globalvars.size() != (GlobalVars_t::size_type)vars->GetSize() ) {
+ g_globalvars.clear();
+ g_globalvars.reserve(vars->GetSize());
+
+ TIter ivar(vars);
+
+ TGlobal* var = 0;
+ while ( (var = (TGlobal*)ivar.Next()) )
+ g_globalvars.push_back( var );
+ }
+ return (TCppIndex_t)g_globalvars.size();
+ }
+ return (TCppIndex_t)0;
+}
+
+std::string Cppyy::GetDatamemberName( TCppScope_t scope, TCppIndex_t idata )
+{
+ TClassRef& cr = type_from_handle( scope );
+ if (cr.GetClass()) {
+ TDataMember* m = (TDataMember*)cr->GetListOfDataMembers()->At( idata );
+ return m->GetName();
+ }
+ assert( scope == (TCppScope_t)GLOBAL_HANDLE );
+ TGlobal* gbl = g_globalvars[ idata ];
+ return gbl->GetName();
+}
+
+std::string Cppyy::GetDatamemberType( TCppScope_t scope, TCppIndex_t idata )
+{
+ if ( scope == GLOBAL_HANDLE ) {
+ TGlobal* gbl = g_globalvars[ idata ];
+ std::string fullType = gbl->GetFullTypeName();
+ if ( fullType[fullType.size()-1] == '*' && \
+ fullType.find( "char", 0, 4 ) == std::string::npos )
+ fullType.append( "*" );
+ else if ( (int)gbl->GetArrayDim() > 1 )
+ fullType.append( "*" );
+ else if ( (int)gbl->GetArrayDim() == 1 ) {
+ std::ostringstream s;
+ s << '[' << gbl->GetMaxIndex( 0 ) << ']' << std::ends;
+ fullType.append( s.str() );
+ }
+ return fullType;
+ }
+
+ TClassRef& cr = type_from_handle( scope );
+ if ( cr.GetClass() ) {
+ TDataMember* m = (TDataMember*)cr->GetListOfDataMembers()->At( idata );
+ std::string fullType = m->GetTrueTypeName();
+ if ( (int)m->GetArrayDim() > 1 || (!m->IsBasic() && m->IsaPointer()) )
+ fullType.append( "*" );
+ else if ( (int)m->GetArrayDim() == 1 ) {
+ std::ostringstream s;
+ s << '[' << m->GetMaxIndex( 0 ) << ']' << std::ends;
+ fullType.append( s.str() );
+ }
+ return fullType;
+ }
+
+ return "<unknown>";
+}
+
+ptrdiff_t Cppyy::GetDatamemberOffset( TCppScope_t scope, TCppIndex_t idata )
+{
+ if ( scope == GLOBAL_HANDLE ) {
+ TGlobal* gbl = g_globalvars[ idata ];
+ return (ptrdiff_t)gbl->GetAddress();
+ }
+
+ TClassRef& cr = type_from_handle( scope );
+ if ( cr.GetClass() ) {
+ TDataMember* m = (TDataMember*)cr->GetListOfDataMembers()->At( idata );
+ return (ptrdiff_t)m->GetOffsetCint(); // yes, CINT ...
+ }
+
+ return (ptrdiff_t)0;
+}
+
+Cppyy::TCppIndex_t Cppyy::GetDatamemberIndex( TCppScope_t scope, const std::string& name )
+{
+ if ( scope == GLOBAL_HANDLE ) {
+ TGlobal* gb = (TGlobal*)gROOT->GetListOfGlobals( kTRUE )->FindObject( name.c_str() );
+ if ( gb && gb->GetAddress() && gb->GetAddress() != (void*)-1 ) {
+ g_globalvars.push_back( gb );
+ return g_globalvars.size() - 1;
+ }
+
+ } else {
+ TClassRef& cr = type_from_handle( scope );
+ if ( cr.GetClass() ) {
+ TDataMember* dm =
+ (TDataMember*)cr->GetListOfDataMembers()->FindObject( name.c_str() );
+ // TODO: turning this into an index is silly ...
+ if ( dm ) return (TCppIndex_t)cr->GetListOfDataMembers()->IndexOf( dm );
+ }
+ }
+
+ return (TCppIndex_t)-1;
+}
+
+
+// data member properties ----------------------------------------------------
+Bool_t Cppyy::IsPublicData( TCppScope_t scope, TCppIndex_t idata )
+{
+ if ( scope == GLOBAL_HANDLE )
+ return kTRUE;
+ TClassRef& cr = type_from_handle( scope );
+ if ( cr->Property() & kIsNamespace )
+ return kTRUE;
+ TDataMember* m = (TDataMember*)cr->GetListOfDataMembers()->At( idata );
+ return m->Property() & kIsPublic;
+}
+
+Bool_t Cppyy::IsStaticData( TCppScope_t scope, TCppIndex_t idata )
+{
+ if ( scope == GLOBAL_HANDLE )
+ return kTRUE;
+ TClassRef& cr = type_from_handle( scope );
+ if ( cr->Property() & kIsNamespace )
+ return kTRUE;
+ TDataMember* m = (TDataMember*)cr->GetListOfDataMembers()->At( idata );
+ return m->Property() & kIsStatic;
+}
+
+Bool_t Cppyy::IsConstData( TCppScope_t scope, TCppIndex_t idata )
+{
+ if ( scope == GLOBAL_HANDLE ) {
+ TGlobal* gbl = g_globalvars[ idata ];
+ return gbl->Property() & kIsConstant;
+ }
+ TClassRef& cr = type_from_handle( scope );
+ if ( cr.GetClass() ) {
+ TDataMember* m = (TDataMember*)cr->GetListOfDataMembers()->At( idata );
+ return m->Property() & kIsConstant;
+ }
+ return kFALSE;
+}
+
+Bool_t Cppyy::IsEnumData( TCppScope_t scope, TCppIndex_t idata )
+{
+ if ( scope == GLOBAL_HANDLE ) {
+ TGlobal* gbl = g_globalvars[ idata ];
+ return gbl->Property() & kIsEnum;
+ }
+ TClassRef& cr = type_from_handle( scope );
+ if ( cr.GetClass() ) {
+ TDataMember* m = (TDataMember*)cr->GetListOfDataMembers()->At( idata );
+ return m->Property() & kIsEnum;
+ }
+ return kFALSE;
+}
+
+Int_t Cppyy::GetDimensionSize( TCppScope_t scope, TCppIndex_t idata, int dimension )
+{
+ if ( scope == GLOBAL_HANDLE ) {
+ TGlobal* gbl = g_globalvars[ idata ];
+ return gbl->GetMaxIndex( dimension );
+ }
+ TClassRef& cr = type_from_handle( scope );
+ if ( cr.GetClass() ) {
+ TDataMember* m = (TDataMember*)cr->GetListOfDataMembers()->At( idata );
+ return m->GetMaxIndex( dimension );
+ }
+ return (Int_t)-1;
+}
+
+
+static inline
+std::vector<TParameter> vsargs_to_parvec(void* args, int nargs)
+{
+ std::vector<TParameter> v;
+ v.reserve(nargs);
+ for (int i=0; i<nargs; ++i)
+ v.push_back(((TParameter*)args)[i]);
+ return v;
+}
+
+//- C-linkage wrappers -------------------------------------------------------
+extern "C" {
/* name to opaque C++ scope representation -------------------------------- */
-int cppyy_num_scopes(cppyy_scope_t handle) {
- return 0;
+int cppyy_num_scopes(cppyy_scope_t parent) {
+ return (int)Cppyy::GetNumScopes(parent);
+}
+
+char* cppyy_scope_name(cppyy_scope_t parent, int iscope) {
+ return cppstring_to_cstring(Cppyy::GetScopeName(parent, iscope));
}
char* cppyy_resolve_name(const char* cppitem_name) {
- std::cout << " RESOLVING: " << cppitem_name << std::endl;
- return cppstring_to_cstring(cppitem_name);
+ return cppstring_to_cstring(Cppyy::ResolveName(cppitem_name));
}
cppyy_scope_t cppyy_get_scope(const char* scope_name) {
- const cling::LookupHelper& lh = gCppyy_Cling->getLookupHelper();
- const Type* type = 0;
- const Decl* decl = lh.findScope(scope_name, &type, /* intantiateTemplate= */ true);
- if (!decl) {
- //std::string buf = TClassEdit::InsertStd(name);
- //decl = lh.findScope(buf, &type, /* intantiateTemplate= */ true);
- }
- if (!decl && type) {
- const TagType* tagtype = type->getAs<TagType>();
- if (tagtype) {
- decl = tagtype->getDecl();
- }
- }
-
- std::cout << "FOR: " << scope_name << " RECEIVED: " << type << " AND: " << decl << std::endl;
- if (decl) {
- DeclContext* dc = llvm::cast<DeclContext>(const_cast<Decl*>(decl));
- SimpleScope* s = new SimpleScope;
- for (DeclContext::decl_iterator idecl = dc->decls_begin(); *idecl; ++idecl) {
- if (FunctionDecl* m = llvm::dyn_cast_or_null<FunctionDecl>(*idecl))
- s->m_methods.push_back(m);
- else if (FieldDecl* d = llvm::dyn_cast_or_null<FieldDecl>(*idecl))
- s->m_data.push_back(d);
- }
- s_scopes[(cppyy_scope_t)decl] = s;
- }
-
- return (cppyy_scope_t)decl; // lookup failure return 0 (== error)
+ return cppyy_scope_t(Cppyy::GetScope(scope_name));
}
+cppyy_type_t cppyy_get_template(const char* template_name) {
+ return cppyy_type_t(Cppyy::GetTemplate(template_name));
+}
+
+cppyy_type_t cppyy_actual_class(cppyy_type_t klass, cppyy_object_t obj) {
+ return cppyy_type_t(Cppyy::GetActualClass(klass, (void*)obj));
+}
+
+
+/* memory management ------------------------------------------------------ */
+cppyy_object_t cppyy_allocate(cppyy_type_t type) {
+ return cppyy_object_t(Cppyy::Allocate(type));
+}
+
+void cppyy_deallocate(cppyy_type_t type, cppyy_object_t self) {
+ Cppyy::Deallocate(type, (void*)self);
+}
+
+void cppyy_destruct(cppyy_type_t type, cppyy_object_t self) {
+ Cppyy::Destruct(type, (void*)self);
+}
+
/* method/function dispatching -------------------------------------------- */
-
-// TODO: expect the below to live in libCling.so
-static CPPYY_Cling_Wrapper_t make_wrapper(const FunctionDecl* fdecl);
-static void exec_with_valref_return(void* address, cling::StoredValueRef* ret, const FunctionDecl*);
-static long long sv_to_long_long(const cling::StoredValueRef& svref);
-// -- TODO: expect the above to live in libCling.so
-
-
-template<typename T>
-static inline T cppyy_call_T(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
- if (s_wrappers.find(method) == s_wrappers.end()) {
- make_wrapper((FunctionDecl*)method);
- }
- cling::StoredValueRef ret;
- // std::vector<void*> arguments = build_args(nargs, args);
- // CPPYY_Cling_Wrapper_t cb = (CPPYY_Cling_Wrapper_t)method;
- exec_with_valref_return((void*)self, &ret, (FunctionDecl*)method);
- // (*cb)((void*)self, nargs, const_cast<void**>(arguments.data()), ret);
- return static_cast<T>(sv_to_long_long(ret));
+void cppyy_call_v(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
+ std::vector<TParameter> parvec = vsargs_to_parvec(args, nargs);
+ Cppyy::CallV(method, (void*)self, &parvec);
}
+unsigned char cppyy_call_b(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
+ std::vector<TParameter> parvec = vsargs_to_parvec(args, nargs);
+ return (unsigned char)Cppyy::CallB(method, (void*)self, &parvec);
+}
+char cppyy_call_c(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
+ std::vector<TParameter> parvec = vsargs_to_parvec(args, nargs);
+ return (char)Cppyy::CallC(method, (void*)self, &parvec);
+}
+
+short cppyy_call_h(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
+ std::vector<TParameter> parvec = vsargs_to_parvec(args, nargs);
+ return (short)Cppyy::CallH(method, (void*)self, &parvec);
+}
int cppyy_call_i(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
- return cppyy_call_T<int>(method, self, nargs, args);
+ std::vector<TParameter> parvec = vsargs_to_parvec(args, nargs);
+ return (int)Cppyy::CallI(method, (void*)self, &parvec);
}
-
-
-cppyy_methptrgetter_t cppyy_get_methptr_getter(cppyy_type_t /* handle */, cppyy_index_t /* method_index */) {
- return (cppyy_methptrgetter_t)0;
+long cppyy_call_l(cppyy_method_t method, cppyy_object_t self, int nargs, void* args){
+ std::vector<TParameter> parvec = vsargs_to_parvec(args, nargs);
+ return (long)Cppyy::CallL(method, (void*)self, &parvec);
}
+long long cppyy_call_ll(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
+ std::vector<TParameter> parvec = vsargs_to_parvec(args, nargs);
+ return (long long)Cppyy::CallLL(method, (void*)self, &parvec);
+}
+
+float cppyy_call_f(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
+ std::vector<TParameter> parvec = vsargs_to_parvec(args, nargs);
+ return (float)Cppyy::CallF(method, (void*)self, &parvec);
+}
+
+double cppyy_call_d(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
+ std::vector<TParameter> parvec = vsargs_to_parvec(args, nargs);
+ return (double)Cppyy::CallD(method, (void*)self, &parvec);
+}
+
+void* cppyy_call_r(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
+ std::vector<TParameter> parvec = vsargs_to_parvec(args, nargs);
+ return (void*)Cppyy::CallR(method, (void*)self, &parvec);
+}
+
+char* cppyy_call_s(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
+ std::vector<TParameter> parvec = vsargs_to_parvec(args, nargs);
+ return cppstring_to_cstring(Cppyy::CallS(method, (void*)self, &parvec));
+}
+
+cppyy_object_t cppyy_constructor(cppyy_method_t method, cppyy_type_t klass, int nargs, void* args) {
+ std::vector<TParameter> parvec = vsargs_to_parvec(args, nargs);
+ return cppyy_object_t(Cppyy::CallConstructor(method, klass, &parvec));
+// return cppyy_object_t(Cppyy::CallConstructor(method, klass, args));
+}
+
+cppyy_object_t cppyy_call_o(cppyy_method_t method, cppyy_object_t self, int nargs, void* args, cppyy_type_t result_type) {
+ std::vector<TParameter> parvec = vsargs_to_parvec(args, nargs);
+ return cppyy_object_t(Cppyy::CallO(method, (void*)self, &parvec, result_type));
+}
+
+cppyy_methptrgetter_t cppyy_get_methptr_getter(cppyy_scope_t scope, cppyy_index_t idx) {
+ return cppyy_methptrgetter_t(Cppyy::GetMethPtrGetter(scope, idx));
+}
+
/* handling of function argument buffer ----------------------------------- */
-void* cppyy_allocate_function_args(size_t nargs) {
- CPPYY_G__value* args = (CPPYY_G__value*)malloc(nargs*sizeof(CPPYY_G__value));
- for (size_t i = 0; i < nargs; ++i)
- args[i].type = 'l';
- return (void*)args;
+void* cppyy_allocate_function_args(int nargs){
+ return (void*)Cppyy::AllocateFunctionArgs(nargs);
}
-void cppyy_deallocate_function_args(void* args) {
- free(args);
+void cppyy_deallocate_function_args(void* args){
+ Cppyy::DeallocateFunctionArgs(args);
}
-size_t cppyy_function_arg_sizeof() {
- return sizeof(CPPYY_G__value);
+size_t cppyy_function_arg_sizeof(){
+ return (size_t)Cppyy::GetFunctionArgSizeof();
}
-size_t cppyy_function_arg_typeoffset() {
- return offsetof(CPPYY_G__value, type);
+size_t cppyy_function_arg_typeoffset(){
+ return (size_t)Cppyy::GetFunctionArgTypeoffset();
}
/* scope reflection information ------------------------------------------- */
-int cppyy_is_namespace(cppyy_scope_t /* handle */) {
- return 0;
-}
-
-int cppyy_is_enum(const char* /* type_name */) {
- return 0;
-}
-
-
-/* class reflection information ------------------------------------------- */
-char* cppyy_final_name(cppyy_type_t handle) {
- for (NamedHandles_t::iterator isp = s_named.begin(); isp != s_named.end(); ++isp) {
- if (isp->second == (cppyy_scope_t)handle)
- return cppstring_to_cstring(isp->first);
- }
- return cppstring_to_cstring("<unknown>");
+int cppyy_is_namespace(cppyy_scope_t scope) {
+ return (int)Cppyy::IsNamespace(scope);
}
-char* cppyy_scoped_final_name(cppyy_type_t handle) {
- return cppyy_final_name(handle);
-}
-
-int cppyy_has_complex_hierarchy(cppyy_type_t /* handle */) {
- return 1;
+int cppyy_is_enum(const char* type_name){
+ return (int)Cppyy::IsEnum(type_name);
}
-/* method/function reflection information --------------------------------- */
-int cppyy_num_methods(cppyy_scope_t handle) {
- SimpleScope* s = scope_from_handle(handle);
- if (!s) return 0;
- return s->m_methods.size();
+/* class reflection information ------------------------------------------- */
+char* cppyy_final_name(cppyy_type_t type) {
+ return cppstring_to_cstring(Cppyy::GetFinalName(type));
}
-cppyy_index_t cppyy_method_index_at(cppyy_scope_t /* scope */, int imeth) {
- return (cppyy_index_t)imeth;
+char* cppyy_scoped_final_name(cppyy_type_t type) {
+ return cppstring_to_cstring(Cppyy::GetScopedFinalName(type));
}
-char* cppyy_method_name(cppyy_scope_t handle, cppyy_index_t method_index) {
- SimpleScope* s = scope_from_handle(handle);
- if (!s) return cppstring_to_cstring("<unknown>");
- FunctionDecl* meth = s->m_methods.at(method_index);
- std::cout << " METHOD NAME: " << meth->getDeclName().getAsString() << std::endl;
- return cppstring_to_cstring(meth->getDeclName().getAsString());
+int cppyy_has_complex_hierarchy(cppyy_type_t type) {
+ return (int)Cppyy::HasComplexHierarchy(type);
}
-char* cppyy_method_result_type(cppyy_scope_t handle, cppyy_index_t method_index) {
- SimpleScope* s = scope_from_handle(handle);
- if (!s) return cppstring_to_cstring("<unknown>");
- FunctionDecl* meth = s->m_methods.at(method_index);
- const std::string& ret_type =
- qualtype_to_string(meth->getCallResultType(), meth->getASTContext());
- std::cout << " -> RET TYPE: " << ret_type << std::endl;
- return cppstring_to_cstring(ret_type);
-}
-
-int cppyy_method_num_args(cppyy_scope_t /* handle */, cppyy_index_t /* method_index */) {
- return 1;
+int cppyy_num_bases(cppyy_type_t type) {
+ return (int)Cppyy::GetNumBases(type);
}
-int cppyy_method_req_args(cppyy_scope_t handle, cppyy_index_t method_index) {
- return cppyy_method_num_args(handle, method_index);
+char* cppyy_base_name(cppyy_type_t type, int base_index){
+ return cppstring_to_cstring(Cppyy::GetBaseName (type, base_index));
}
-char* cppyy_method_arg_type(cppyy_scope_t /* handle */, cppyy_index_t /* method_index */, int /* arg_index */) {
- return cppstring_to_cstring("double");
+int cppyy_is_subtype(cppyy_type_t derived, cppyy_type_t base){
+ return (int)Cppyy::IsSubtype( derived, base );
}
-char* cppyy_method_arg_default(cppyy_scope_t handle, cppyy_index_t method_index, int arg_index) {
- return cppstring_to_cstring("");
+
+/* calculate offsets between declared and actual type, up-cast: direction > 0; down-cast: direction < 0 */
+ptrdiff_t cppyy_base_offset(cppyy_type_t derived, cppyy_type_t base, cppyy_object_t address, int direction) {
+ return (ptrdiff_t)Cppyy::GetBaseOffset(derived, base, (void*)address, direction, 0);
}
-char* cppyy_method_signature(cppyy_scope_t /* handle */, cppyy_index_t /* method_index */) {
- return cppstring_to_cstring("double");
+
+/* method/function reflection information --------------------------------- */
+int cppyy_num_methods(cppyy_scope_t scope) {
+ return (int)Cppyy::GetNumMethods (scope);
}
-int cppyy_method_is_template(cppyy_scope_t /* handle */, cppyy_index_t /* method_index */) {
- return 0;
-}
-
-cppyy_method_t cppyy_get_method(cppyy_scope_t handle, cppyy_index_t method_index) {
- SimpleScope* s = scope_from_handle(handle);
- if (!s) return (cppyy_method_t)0;
- return (cppyy_method_t)s->m_methods.at(method_index);
+cppyy_index_t cppyy_method_index_at(cppyy_scope_t scope, int imeth) {
+ return cppyy_index_t(Cppyy::GetMethodIndexAt (scope, imeth));
}
-
-/* method properties ----------------------------------------------------- */
-int cppyy_is_constructor(cppyy_type_t /* handle */, cppyy_index_t /* method_index */) {
- return 0;
+cppyy_index_t* cppyy_method_indices_from_name(cppyy_scope_t scope, const char* name){
+//NEED TO DO:
+ return (cppyy_index_t*)0;
+// return (cppyy_index_t*)Cppyy::GetMethodsFromName(scope, name);
}
-int cppyy_is_staticmethod(cppyy_type_t /* handle */, cppyy_index_t /* method_index */) {
- return 1;
+char* cppyy_method_name(cppyy_scope_t scope, cppyy_index_t idx) {
+ TFunction* f = type_get_method(scope, idx);
+ return cppstring_to_cstring(Cppyy::GetMethodName((Cppyy::TCppMethod_t)f));
}
+char* cppyy_method_result_type(cppyy_scope_t scope, cppyy_index_t idx) {
+ TFunction* f = type_get_method(scope, idx);
+ return cppstring_to_cstring(Cppyy::GetMethodResultType((Cppyy::TCppMethod_t)f));
+}
+
+int cppyy_method_num_args(cppyy_scope_t scope, cppyy_index_t idx) {
+ TFunction* f = type_get_method(scope, idx);
+ return (int)Cppyy::GetMethodNumArgs((Cppyy::TCppMethod_t)f);
+}
+
+int cppyy_method_req_args(cppyy_scope_t scope, cppyy_index_t idx) {
+ TFunction* f = type_get_method(scope, idx);
+ return (int)Cppyy::GetMethodReqArgs((Cppyy::TCppMethod_t)f);
+}
+
+char* cppyy_method_arg_type(cppyy_scope_t scope, cppyy_index_t idx, int arg_index) {
+ TFunction* f = type_get_method(scope, idx);
+ return cppstring_to_cstring(Cppyy::GetMethodArgType((Cppyy::TCppMethod_t)f, arg_index));
+}
+
+char* cppyy_method_arg_default(cppyy_scope_t scope, cppyy_index_t idx, int arg_index) {
+ TFunction* f = type_get_method(scope, idx);
+ return cppstring_to_cstring(Cppyy::GetMethodArgDefault((Cppyy::TCppMethod_t)f, arg_index));
+}
+
+char* cppyy_method_signature(cppyy_scope_t scope, cppyy_index_t idx) {
+ return cppstring_to_cstring(Cppyy::GetMethodSignature(scope, idx));
+}
+
+int cppyy_method_is_template(cppyy_scope_t scope, cppyy_index_t idx) {
+ TFunction* f = type_get_method(scope, idx);
+ return (int)Cppyy::IsMethodTemplate((Cppyy::TCppMethod_t)f);
+}
+
+int cppyy_method_num_template_args(cppyy_scope_t scope, cppyy_index_t idx) {
+ return (int)Cppyy::GetMethodNumTemplateArgs(scope, idx);
+}
+
+char* cppyy_method_template_arg_name(cppyy_scope_t scope, cppyy_index_t idx, cppyy_index_t iarg) {
+ return cppstring_to_cstring(Cppyy::GetMethodTemplateArgName(scope, idx, iarg));
+}
+
+cppyy_method_t cppyy_get_method(cppyy_scope_t scope, cppyy_index_t idx) {
+ return cppyy_method_t(Cppyy::GetMethod(scope, idx));
+}
+
+cppyy_index_t cppyy_get_global_operator(cppyy_scope_t scope, cppyy_scope_t lc, cppyy_scope_t rc, const char* op) {
+ return cppyy_index_t(Cppyy::GetGlobalOperator(scope, lc, rc, op));
+}
+
+
+/* method properties ------------------------------------------------------ */
+int cppyy_is_constructor(cppyy_type_t type, cppyy_index_t idx) {
+ TFunction* f = type_get_method(type, idx);
+ return (int)Cppyy::IsConstructor((Cppyy::TCppMethod_t)f);
+}
+
+int cppyy_is_staticmethod(cppyy_type_t type, cppyy_index_t idx) {
+ TFunction* f = type_get_method(type, idx);
+ return (int)Cppyy::IsStaticMethod((Cppyy::TCppMethod_t)f);
+}
+
/* data member reflection information ------------------------------------- */
-int cppyy_num_datamembers(cppyy_scope_t /* handle */) {
- return 0;
+int cppyy_num_datamembers(cppyy_scope_t scope) {
+ return (int)Cppyy::GetNumDatamembers(scope);
}
+char* cppyy_datamember_name(cppyy_scope_t scope, int datamember_index) {
+ return cppstring_to_cstring(Cppyy::GetDatamemberName(scope, datamember_index));
+}
+
+char* cppyy_datamember_type(cppyy_scope_t scope, int datamember_index) {
+ return cppstring_to_cstring(Cppyy::GetDatamemberType(scope, datamember_index));
+}
+
+ptrdiff_t cppyy_datamember_offset(cppyy_scope_t scope, int datamember_index) {
+ return ptrdiff_t(Cppyy::GetDatamemberOffset(scope, datamember_index));
+}
+
+int cppyy_datamember_index(cppyy_scope_t scope, const char* name) {
+ return (int)Cppyy::GetDatamemberIndex(scope, name);
+}
+
+
+
+/* data member properties ------------------------------------------------- */
+int cppyy_is_publicdata(cppyy_type_t type, int datamember_index) {
+ return (int)Cppyy::IsPublicData(type, datamember_index);
+}
+
+int cppyy_is_staticdata(cppyy_type_t type, int datamember_index) {
+ return (int)Cppyy::IsStaticData(type, datamember_index);
+}
+
/* misc helpers ----------------------------------------------------------- */
+RPY_EXTERN
+void* cppyy_load_dictionary(const char* lib_name) {
+ return (void*)(gInterpreter->Load(lib_name) == 0);
+}
+
+long long cppyy_strtoll(const char* str) {
+ return strtoll(str, NULL, 0);
+}
+
+unsigned long long cppyy_strtoull(const char* str) {
+ return strtoull(str, NULL, 0);
+}
+
void cppyy_free(void* ptr) {
free(ptr);
}
-
-void* cppyy_load_dictionary(const char* lib_name) {
- // TODO: need to rethink this; for now it creates reflection info from
- // <lib_name>.h while loading lib<lib_name>.so
-
- // Load a library file in cling's memory.
- // if 'system' is true, the library is never unloaded.
- // Return 0 on success, -1 on failure.
- // R__LOCKGUARD2(gInterpreterMutex);
- std::cout << " NOW LOADING: " << lib_name << std::endl;
More information about the pypy-commit
mailing list