5050 'set_debug' , # enable/disable debug output
5151 ]
5252
53- import ctypes
54- import os
55- import sys
56- import sysconfig
57- import warnings
53+ from ._version import __version__
54+
55+ import ctypes , os , sys , sysconfig , warnings
56+
57+ if not 'CLING_STANDARD_PCH' in os .environ :
58+ def _set_pch ():
59+ try :
60+ import cppyy_backend as cpb
61+ local_pch = os .path .join (os .path .dirname (__file__ ), 'allDict.cxx.pch.' + str (cpb .__version__ ))
62+ if os .path .exists (local_pch ):
63+ os .putenv ('CLING_STANDARD_PCH' , local_pch )
64+ os .environ ['CLING_STANDARD_PCH' ] = local_pch
65+ except (ImportError , AttributeError ):
66+ pass
67+ _set_pch (); del _set_pch
5868
5969try :
6070 import __pypy__
6373except ImportError :
6474 ispypy = False
6575
66- from . import _typemap
67- from ._version import __version__
68-
6976# import separately instead of in the above try/except block for easier to
7077# understand tracebacks
7178if ispypy :
7986sys .modules ['cppyy.gbl.std' ] = gbl .std
8087
8188
89+ #- force creation of std.exception -------------------------------------------------------
90+ _e = gbl .std .exception
91+
92+
93+ #- enable auto-loading -------------------------------------------------------
94+ try : gbl .cling .runtime .gCling .EnableAutoLoading ()
95+ except : pass
96+
97+
8298#- external typemap ----------------------------------------------------------
99+ from . import _typemap
83100_typemap .initialize (_backend ) # also creates (u)int8_t mapper
84101
85102try :
@@ -113,15 +130,18 @@ def tuple_getitem(self, idx, get=cppyy.gbl.std.get):
113130 raise IndexError (idx )
114131 pyclass .__getitem__ = tuple_getitem
115132
116- # pythonization of std::string ; placed here because it's simpler to write the
133+ # pythonization of std::basic_string<char> ; placed here because it's simpler to write the
117134 # custom "npos" object (to allow easy result checking of find/rfind) in Python
118- elif pyclass .__cpp_name__ == "std::string" :
119- class NPOS (0x3000000 <= sys .hexversion and int or long ):
135+ elif pyclass .__cpp_name__ == "std::basic_string<char>" :
136+ class NPOS (int ):
137+ def __init__ (self , npos ):
138+ self .__cpp_npos = npos
120139 def __eq__ (self , other ):
121- return other == - 1 or int ( self ) == other
140+ return other == - 1 or other == self . __cpp_npos
122141 def __ne__ (self , other ):
123- return other != - 1 and int (self ) != other
124- del pyclass .__class__ .npos # drop b/c is const data
142+ return other != - 1 and other != self .__cpp_npos
143+ if hasattr (pyclass .__class__ , 'npos' ):
144+ del pyclass .__class__ .npos # drop b/c is const data
125145 pyclass .npos = NPOS (pyclass .npos )
126146
127147 return True
@@ -158,24 +178,24 @@ def __getitem__(self, cls):
158178 return py_make_smartptr (cls , self .ptrcls )
159179 except AttributeError :
160180 pass
161- if isinstance (cls , str ) and not cls in ('int' , 'float' ):
181+ if type (cls ) == str and not cls in ('int' , 'float' ):
162182 return py_make_smartptr (getattr (gbl , cls ), self .ptrcls )
163183 return self .maker [cls ]
164184
165- gbl .std .make_shared = make_smartptr (gbl .std .shared_ptr , gbl .std .make_shared )
166- gbl .std .make_unique = make_smartptr (gbl .std .unique_ptr , gbl .std .make_unique )
185+ # gbl.std.make_shared = make_smartptr(gbl.std.shared_ptr, gbl.std.make_shared)
186+ # gbl.std.make_unique = make_smartptr(gbl.std.unique_ptr, gbl.std.make_unique)
167187del make_smartptr
168188
169189
170190#--- interface to Cling ------------------------------------------------------
171191class _stderr_capture (object ):
172192 def __init__ (self ):
173- self ._capture = not gbl .gDebug and True or False
174- self .err = ""
193+ self ._capture = not gbl .Cpp . IsDebugOutputEnabled ()
194+ self .err = ""
175195
176196 def __enter__ (self ):
177197 if self ._capture :
178- _begin_capture_stderr ()
198+ _begin_capture_stderr ()
179199 return self
180200
181201 def __exit__ (self , tp , val , trace ):
@@ -200,32 +220,39 @@ def _cling_report(msg, errcode, msg_is_error=False):
200220def cppdef (src ):
201221 """Declare C++ source <src> to Cling."""
202222 with _stderr_capture () as err :
203- errcode = gbl .gInterpreter .Declare (src )
204- _cling_report (err .err , int (not errcode ), msg_is_error = True )
223+ errcode = gbl .Cpp .Declare (src , False )
224+ if not errcode == 0 or err .err :
225+ if 'warning' in err .err .lower () and not 'error' in err .err .lower ():
226+ warnings .warn (err .err , SyntaxWarning )
227+ return True
228+ raise SyntaxError ('Failed to parse the given C++ code%s' % err .err )
205229 return True
206230
207231def cppexec (stmt ):
208232 """Execute C++ statement <stmt> in Cling's global scope."""
209233 if stmt and stmt [- 1 ] != ';' :
210234 stmt += ';'
211235
212- # capture stderr, but note that ProcessLine could legitimately be writing to
236+ # capture stderr, but note that Process could legitimately be writing to
213237 # std::cerr, in which case the captured output needs to be printed as normal
214238 with _stderr_capture () as err :
215239 errcode = ctypes .c_int (0 )
216240 try :
217- gbl .gInterpreter . ProcessLine (stmt , ctypes . pointer ( errcode ) )
241+ errcode = gbl .Cpp . Process (stmt )
218242 except Exception as e :
219243 sys .stderr .write ("%s\n \n " % str (e ))
220- if not errcode .value :
221- errcode .value = 1
244+ if not errcode .value : errcode .value = 1
222245
223- _cling_report (err .err , errcode .value )
224- if err .err and err .err [1 :] != '\n ' :
246+ if not errcode == 0 :
247+ raise SyntaxError ('Failed to parse the given C++ code%s' % err .err )
248+ elif err .err and err .err [1 :] != '\n ' :
225249 sys .stderr .write (err .err [1 :])
226250
227251 return True
228252
253+ def evaluate (input , HadError = _backend .nullptr ):
254+ return gbl .Cpp .Evaluate (input , HadError )
255+
229256def macro (cppm ):
230257 """Attempt to evalute a C/C++ pre-processor macro as a constant"""
231258
@@ -243,43 +270,35 @@ def macro(cppm):
243270def load_library (name ):
244271 """Explicitly load a shared library."""
245272 with _stderr_capture () as err :
246- gSystem = gbl .gSystem
247- if name [:3 ] != 'lib' :
248- if not gSystem .FindDynamicLibrary (gbl .TString (name ), True ) and \
249- gSystem .FindDynamicLibrary (gbl .TString ('lib' + name ), True ):
250- name = 'lib' + name
251- sc = gSystem .Load (name )
252- if sc == - 1 :
253- # special case for Windows as of python3.8: use winmode=0, otherwise the default
254- # will not consider regular search paths (such as $PATH)
255- if 0x3080000 <= sys .hexversion and 'win32' in sys .platform and os .path .isabs (name ):
256- return ctypes .CDLL (name , ctypes .RTLD_GLOBAL , winmode = 0 ) # raises on error
257- raise RuntimeError ('Unable to load library "%s"%s' % (name , err .err ))
273+ result = gbl .Cpp .LoadLibrary (name , True )
274+ if result == False :
275+ raise RuntimeError ('Could not load library "%s": %s' % (name , err .err ))
276+
258277 return True
259278
260279def include (header ):
261280 """Load (and JIT) header file <header> into Cling."""
262281 with _stderr_capture () as err :
263- errcode = gbl .gInterpreter .Declare ('#include "%s"' % header )
264- if not errcode :
282+ errcode = gbl .Cpp .Declare ('#include "%s"' % header , False )
283+ if not errcode == 0 :
265284 raise ImportError ('Failed to load header file "%s"%s' % (header , err .err ))
266285 return True
267286
268287def c_include (header ):
269288 """Load (and JIT) header file <header> into Cling."""
270289 with _stderr_capture () as err :
271- errcode = gbl .gInterpreter .Declare ("""extern "C" {
272- #include "%s"
273- }""" % header )
274- if not errcode :
290+ errcode = gbl .Cpp .Declare ("""extern "C" {
291+ #include "%s"
292+ }""" % header , False )
293+ if not errcode == 0 :
275294 raise ImportError ('Failed to load header file "%s"%s' % (header , err .err ))
276295 return True
277296
278297def add_include_path (path ):
279298 """Add a path to the include paths available to Cling."""
280299 if not os .path .isdir (path ):
281300 raise OSError ('No such directory: %s' % path )
282- gbl .gInterpreter .AddIncludePath (path )
301+ gbl .Cpp .AddIncludePath (path )
283302
284303def add_library_path (path ):
285304 """Add a path to the library search paths available to Cling."""
@@ -319,23 +338,22 @@ def add_library_path(path):
319338 else :
320339 import pkg_resources as pr
321340
322- d = pr .get_distribution ('CPyCppyy' )
323- for line in d .get_metadata_lines ('RECORD' ):
324- if 'API.h' in line :
325- ape = os .path .join (d .location , line [0 :line .find (',' )])
326- break
327- del line , d , pr
341+ d = pr .get_distribution ('CPyCppyy' )
342+ for line in d .get_metadata_lines ('RECORD' ):
343+ if 'API.h' in line :
344+ part = line [0 :line .find (',' )]
328345
346+ ape = os .path .join (d .location , part )
329347 if os .path .exists (ape ):
330348 apipath_extra = os .path .dirname (os .path .dirname (ape ))
331- del ape
349+
350+ del part , d , pr
332351 except Exception :
333352 pass
334353
335354 if apipath_extra is None :
336355 ldversion = sysconfig .get_config_var ('LDVERSION' )
337- if not ldversion :
338- ldversion = sys .version [:3 ]
356+ if not ldversion : ldversion = sys .version [:3 ]
339357
340358 apipath_extra = os .path .join (os .path .dirname (apipath ), 'site' , 'python' + ldversion )
341359 if not os .path .exists (os .path .join (apipath_extra , 'CPyCppyy' )):
@@ -361,9 +379,7 @@ def add_library_path(path):
361379
362380 if apipath_extra .lower () != 'none' :
363381 if not os .path .exists (os .path .join (apipath_extra , 'CPyCppyy' )):
364- warnings .warn ("CPyCppyy API not found (tried: %s); "
365- "set CPPYY_API_PATH envar to the 'CPyCppyy' API directory to fix"
366- % apipath_extra )
382+ warnings .warn ("CPyCppyy API not found (tried: %s); set CPPYY_API_PATH envar to the 'CPyCppyy' API directory to fix" % apipath_extra )
367383 else :
368384 add_include_path (apipath_extra )
369385
@@ -372,38 +388,30 @@ def add_library_path(path):
372388if os .getenv ('CONDA_PREFIX' ):
373389 # MacOS, Linux
374390 include_path = os .path .join (os .getenv ('CONDA_PREFIX' ), 'include' )
375- if os .path .exists (include_path ):
376- add_include_path (include_path )
391+ if os .path .exists (include_path ): add_include_path (include_path )
377392
378393 # Windows
379394 include_path = os .path .join (os .getenv ('CONDA_PREFIX' ), 'Library' , 'include' )
380- if os .path .exists (include_path ):
381- add_include_path (include_path )
395+ if os .path .exists (include_path ): add_include_path (include_path )
382396
383- # assuming that we are in PREFIX/lib/python/site-packages/cppyy,
384- # add PREFIX/include to the search path
385- include_path = os .path .abspath (
386- os .path .join (os .path .dirname (__file__ ), * (4 * [os .path .pardir ]+ ['include' ])))
387- if os .path .exists (include_path ):
388- add_include_path (include_path )
397+ # assuming that we are in PREFIX/lib/python/site-packages/cppyy, add PREFIX/include to the search path
398+ include_path = os .path .abspath (os .path .join (os .path .dirname (__file__ ), * (4 * [os .path .pardir ]+ ['include' ])))
399+ if os .path .exists (include_path ): add_include_path (include_path )
389400
390401del include_path , apipath , ispypy
391402
392403def add_autoload_map (fname ):
393404 """Add the entries from a autoload (.rootmap) file to Cling."""
394405 if not os .path .isfile (fname ):
395406 raise OSError ("no such file: %s" % fname )
396- gbl .gInterpreter .LoadLibraryMap (fname )
407+ gbl .cling . runtime . gCling .LoadLibraryMap (fname )
397408
398409def set_debug (enable = True ):
399410 """Enable/disable debug output."""
400- if enable :
401- gbl .gDebug = 10
402- else :
403- gbl .gDebug = 0
411+ gbl .Cpp .EnableDebugOutput (enable )
404412
405413def _get_name (tt ):
406- if isinstance (tt , str ) :
414+ if type (tt ) == str :
407415 return tt
408416 try :
409417 ttname = tt .__cpp_name__
@@ -414,15 +422,15 @@ def _get_name(tt):
414422_sizes = {}
415423def sizeof (tt ):
416424 """Returns the storage size (in chars) of C++ type <tt>."""
417- if not isinstance (tt , type ) and not isinstance (tt , str ) :
425+ if not isinstance (tt , type ) and not type (tt ) == str :
418426 tt = type (tt )
419427 try :
420428 return _sizes [tt ]
421429 except KeyError :
422430 try :
423431 sz = ctypes .sizeof (tt )
424432 except TypeError :
425- sz = gbl .gInterpreter . ProcessLine ("sizeof(%s); " % (_get_name (tt ),))
433+ sz = gbl .Cpp . Evaluate ("sizeof(%s)" % (_get_name (tt ),), nullptr )
426434 _sizes [tt ] = sz
427435 return sz
428436
@@ -435,7 +443,7 @@ def typeid(tt):
435443 return _typeids [tt ]
436444 except KeyError :
437445 tidname = 'typeid_' + str (len (_typeids ))
438- gbl . gInterpreter . ProcessLine (
446+ cppexec (
439447 "namespace _cppyy_internal { auto* %s = &typeid(%s); }" % \
440448 (tidname , _get_name (tt ),))
441449 tid = getattr (gbl ._cppyy_internal , tidname )
@@ -445,9 +453,15 @@ def typeid(tt):
445453def multi (* bases ): # after six, see also _typemap.py
446454 """Resolve metaclasses for multiple inheritance."""
447455 # contruct a "no conflict" meta class; the '_meta' is needed by convention
448- nc_meta = type .__new__ (
449- type , 'cppyy_nc_meta' , tuple (type (b ) for b in bases if type (b ) is not type ), {})
456+ nc_meta = type .__new__ (type , 'cppyy_nc_meta' , tuple (type (b ) for b in bases if type (b ) is not type ), {})
450457 class faux_meta (type ):
451- def __new__ (mcs , name , this_bases , d ):
458+ def __new__ (cls , name , this_bases , d ):
452459 return nc_meta (name , bases , d )
453460 return type .__new__ (faux_meta , 'faux_meta' , (), {})
461+
462+
463+ #- workaround (TODO: may not be needed with Clang9) --------------------------
464+ if 'win32' in sys .platform :
465+ cppdef ("""template<>
466+ std::basic_ostream<char, std::char_traits<char>>& __cdecl std::endl<char, std::char_traits<char>>(
467+ std::basic_ostream<char, std::char_traits<char>>&);""" )
0 commit comments