import aa import ROOT import array ''' Note on pointers in pyroot. As far as I can tell, void* are returned as '. The buffer seems to support indexing, but that does not give a sensible result it seems. ''' ROOT.gInterpreter.Declare("unsigned long _tets(void* x) { return (unsigned long)x; }") ROOT.gInterpreter.Declare("void dus(void* p) { cout << p << ' ' << ((TH1D*)p)->GetName() << endl; }") ROOT.gInterpreter.Declare("void crash(void* p) { int *x = 0; cout << *x << endl; }") # create a histogram on the c++ side ROOT.gInterpreter.ProcessLine('TH1D gg("gg","gg",10,0,10);') X = ROOT.gg #important! If you do id(ROOT.gg)/AddressOf(ROOT.gg), you take the #address of a temporarily crated objectproxy print hex_dump_memory( ROOT.gg ,256 ) # ROOT.gg = ROOT.TH1D('dus','dus',10,0,10) ROOT.dus( ROOT.gg ) #ROOT.gInterpreter.ProcessLine('cout << "ptr to gg:" << &gg << endl;') # next step: call a method on a histogram #print ROOT.gInterpreter.ProcessLine("&TH1D::Reset") #for m in ROOT.TH1D.Class().GetListOfMethods(): # print m, hex ( m.InterfaceMethod()[0] ) #print ROOT.TH1D.Class().GetListOfMethods()[8].GetMangledName() #print ROOT.TH1D.Class().GetListOfMethods()[8].InterfaceMethod()[0] cxx = ROOT.gInterpreter.Declare cxx('void funky() { cout << "hi!" << endl; }') cxx('int funkadd(double a, double b) { return a+b; }') cxx('int funkadd(int a, int b) { return a+b; }') ROOT.gInterpreter.Declare(''' struct struct_A { int x; int y; int funky_A (int a ) { return x*a ; } }; ''') A = ROOT.struct_A() A.x = 2 print A.funky_A(1000) cxx("long funky_addr() { return (long) &funky; }") cxx("void* funky_vaddr() { return (void*) &funky; }") hifunc_addr_as_long = ROOT.funky_addr(); hifunc_type = ctypes.CFUNCTYPE(None) #ctypes way to define a function returning void(=None) and taking no args hifunc = hifunc_type( hifunc_addr_as_long ) print " drum roll : " hifunc() # call it tfun = ROOT.gROOT.GetGlobalFunction("funkadd") for arg in list( tfun.GetListOfMethodArgs() ) : print arg.GetTypeName() print arg.GetTypeNormalizedName() print arg.GetName() print print tfun.InterfaceMethod() print tfun.GetMangledName() print hifunc_addr_as_long, hex(hifunc_addr_as_long), ROOT.funky_vaddr() addr = ROOT.gInterpreter.FindSym( "_Z7funkaddii") print addr from llvmlite.binding import * print address_of_symbol("_Z5funkyv") # not working _str_to_ctype = { "int" : ctypes.c_int, "double" : ctypes.c_double } def ctypes_func( pyroot_func ): """ take a pytroot function and convert it to a cytypes function. """ # getglobalfunciton returns the first one in the list # there are versions that handle overloading as well function = ROOT.gROOT.GetGlobalFunction( pyroot_func.__name__ ) retype = _str_to_ctype[function.GetReturnTypeName()] argtypes = [ _str_to_ctype[arg.GetTypeName()] for arg in function.GetListOfMethodArgs() ] buf = ROOT.gInterpreter.FindSym( function.GetMangledName() ) ptr = buffer_to_int( buf ) return ctypes.CFUNCTYPE( retype, *argtypes ) ( ptr ) def ctypes_method( pyroot_method ): methodname = pyroot_method.__name__ classname = pyroot_method.im_class.__name__ try : tclass = pyroot_method.im_class.Class() except AttributeError : print "no dictonary info for ", classname ROOT.gInterpreter.GenerateDictionary( classname ) tclass = ROOT.gInterpreter.GenerateTClass( classname, False ) tmethod = tclass.GetMethodAny( methodname ) mn = tmethod.GetMangledName() buf = buffer_to_int( ROOT.gInterpreter.FindSym( mn ) ) if buf == 0 : # the following triggeres the compilation of the wrapper # for funky_A in TClingCallFunc.cxx. # it also seems that it triggers the acutal compilation/emission of # the method (funky_A in this case). After this, the mangled # symbol name exists. # interfacemethod() -> make_wrapper -> compile_wrapper -> # fInterp->compileFunction -> ... -> IncrementalParser::Compile print "symbol ", mn, "not yet found..." os.environ['WRAPVERB'] = '1' # my hack to turn verbosity on print '----------------------------------------------------------' m = tmethod.InterfaceMethod() print "interfacemethod = ", m[0], id(m) print '----------------------------------------------------------' del os.environ['WRAPVERB'] # I don't actually use the compiled wrapper method, but # directly call the (mangled) function. buf = ROOT.gInterpreter.FindSym( mn ) print 'symbol at : ', repr(buf) iii = buffer_to_int( buf ) if iii == 0 : print "failed to get symbol for",mn return None M = ctypes.CFUNCTYPE( ctypes.c_int, # return type ctypes.c_void_p, # this pointer ctypes.c_int )(iii) # other args return M f = ctypes_method( ROOT.struct_A.funky_A ) A.x = 42 print f( ROOT.AddressOf(A)[0] , 10 ) # should print 420 # just for fun, add it as a method addr = ROOT.AddressOf(A)[0] def Afun ( arg ) : return f( addr , arg ) from timeit import default_timer as timer s1 = timer() for i in range( 100) : A.funky_A(i) s2 = timer() for i in range( 100) : Afun(i) s3 = timer() print "funky_A : ", s2 - s1 print "Afun : ", s3 - s2 cxx(''' long checkptrs() { auto tc = gROOT->GetClass( "struct_A"); auto tmethod = tc->GetMethodAny( "funky_A" ); cout << "iface" << tmethod->InterfaceMethod() << endl; return (long) tmethod->InterfaceMethod() ; } void* long_to_void_ptr( long x ) { return (void*) x; } ''') #al = ROOT.checkptrs() #print al #x = ROOT.long_to_void_ptr( al ) #print x, repr(x) #print hex( buffer_to_int( x ) ) #print hex(x[0]) #f = ctypes_func( ROOT.funkadd ) #print f( 100, 200 )