Author: Wim Lavrijsen <[email protected]> Branch: reflex-support Changeset: r55941:6f11407e1414 Date: 2012-07-06 00:09 -0700 http://bitbucket.org/pypy/pypy/changeset/6f11407e1414/
Log: code quality diff --git a/pypy/module/cppyy/__init__.py b/pypy/module/cppyy/__init__.py --- a/pypy/module/cppyy/__init__.py +++ b/pypy/module/cppyy/__init__.py @@ -1,7 +1,9 @@ from pypy.interpreter.mixedmodule import MixedModule class Module(MixedModule): - """ """ + "This module provides runtime bindings to C++ code for which reflection\n\ + info has been generated. Current supported back-ends are Reflex and CINT.\n\ + See http://doc.pypy.org/en/latest/cppyy.html for full details." interpleveldefs = { '_load_dictionary' : 'interp_cppyy.load_dictionary', 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 @@ -11,6 +11,15 @@ from pypy.module.cppyy import helper, capi +# Converter objects are used to translate between RPython and C++. They are +# defined by the type name for which they provide conversion. Uses are for +# function arguments, as well as for read and write access to data members. +# All type conversions are fully checked. +# +# Converter instances are greated by get_converter(<type name>), see below. +# The name given should be qualified in case there is a specialised, exact +# match for the qualified type. + def get_rawobject(space, w_obj): from pypy.module.cppyy.interp_cppyy import W_CPPInstance @@ -316,10 +325,6 @@ def _unwrap_object(self, space, w_obj): return rffi.cast(rffi.SHORT, space.int_w(w_obj)) -class ConstShortRefConverter(ConstRefNumericTypeConverterMixin, ShortConverter): - _immutable_ = True - libffitype = libffi.types.pointer - class UnsignedShortConverter(IntTypeConverterMixin, TypeConverter): _immutable_ = True libffitype = libffi.types.sshort @@ -332,10 +337,6 @@ def _unwrap_object(self, space, w_obj): return rffi.cast(self.c_type, space.int_w(w_obj)) -class ConstUnsignedShortRefConverter(ConstRefNumericTypeConverterMixin, UnsignedShortConverter): - _immutable_ = True - libffitype = libffi.types.pointer - class IntConverter(IntTypeConverterMixin, TypeConverter): _immutable_ = True libffitype = libffi.types.sint @@ -348,10 +349,6 @@ def _unwrap_object(self, space, w_obj): return rffi.cast(self.c_type, space.c_int_w(w_obj)) -class ConstIntRefConverter(ConstRefNumericTypeConverterMixin, IntConverter): - _immutable_ = True - libffitype = libffi.types.pointer - class UnsignedIntConverter(IntTypeConverterMixin, TypeConverter): _immutable_ = True libffitype = libffi.types.uint @@ -364,10 +361,6 @@ def _unwrap_object(self, space, w_obj): return rffi.cast(self.c_type, space.uint_w(w_obj)) -class ConstUnsignedIntRefConverter(ConstRefNumericTypeConverterMixin, UnsignedIntConverter): - _immutable_ = True - libffitype = libffi.types.pointer - class LongConverter(IntTypeConverterMixin, TypeConverter): _immutable_ = True libffitype = libffi.types.slong @@ -426,10 +419,6 @@ def _unwrap_object(self, space, w_obj): return space.uint_w(w_obj) -class ConstUnsignedLongRefConverter(ConstRefNumericTypeConverterMixin, UnsignedLongConverter): - _immutable_ = True - libffitype = libffi.types.pointer - class UnsignedLongLongConverter(IntTypeConverterMixin, TypeConverter): _immutable_ = True libffitype = libffi.types.ulong @@ -442,10 +431,6 @@ def _unwrap_object(self, space, w_obj): return space.r_ulonglong_w(w_obj) -class ConstUnsignedLongLongRefConverter(ConstRefNumericTypeConverterMixin, UnsignedLongLongConverter): - _immutable_ = True - libffitype = libffi.types.pointer - class FloatConverter(FloatTypeConverterMixin, TypeConverter): _immutable_ = True @@ -776,56 +761,85 @@ _converters["bool"] = BoolConverter _converters["char"] = CharConverter -_converters["unsigned char"] = CharConverter -_converters["short int"] = ShortConverter -_converters["const short int&"] = ConstShortRefConverter -_converters["short"] = _converters["short int"] -_converters["const short&"] = _converters["const short int&"] -_converters["unsigned short int"] = UnsignedShortConverter -_converters["const unsigned short int&"] = ConstUnsignedShortRefConverter -_converters["unsigned short"] = _converters["unsigned short int"] -_converters["const unsigned short&"] = _converters["const unsigned short int&"] +_converters["short"] = ShortConverter +_converters["unsigned short"] = UnsignedShortConverter _converters["int"] = IntConverter -_converters["const int&"] = ConstIntRefConverter -_converters["unsigned int"] = UnsignedIntConverter -_converters["const unsigned int&"] = ConstUnsignedIntRefConverter -_converters["long int"] = LongConverter -_converters["const long int&"] = ConstLongRefConverter -_converters["long"] = _converters["long int"] -_converters["const long&"] = _converters["const long int&"] -_converters["unsigned long int"] = UnsignedLongConverter -_converters["const unsigned long int&"] = ConstUnsignedLongRefConverter -_converters["unsigned long"] = _converters["unsigned long int"] -_converters["const unsigned long&"] = _converters["const unsigned long int&"] -_converters["long long int"] = LongLongConverter -_converters["const long long int&"] = ConstLongLongRefConverter -_converters["long long"] = _converters["long long int"] -_converters["const long long&"] = _converters["const long long int&"] -_converters["unsigned long long int"] = UnsignedLongLongConverter -_converters["const unsigned long long int&"] = ConstUnsignedLongLongRefConverter -_converters["unsigned long long"] = _converters["unsigned long long int"] -_converters["const unsigned long long&"] = _converters["const unsigned long long int&"] +_converters["unsigned"] = UnsignedIntConverter +_converters["long"] = LongConverter +_converters["const long&"] = ConstLongRefConverter +_converters["unsigned long"] = UnsignedLongConverter +_converters["long long"] = LongLongConverter +_converters["const long long&"] = ConstLongLongRefConverter +_converters["unsigned long long"] = UnsignedLongLongConverter _converters["float"] = FloatConverter _converters["const float&"] = ConstFloatRefConverter _converters["double"] = DoubleConverter _converters["const double&"] = ConstDoubleRefConverter _converters["const char*"] = CStringConverter -_converters["char*"] = CStringConverter _converters["void*"] = VoidPtrConverter _converters["void**"] = VoidPtrPtrConverter _converters["void*&"] = VoidPtrRefConverter # special cases (note: CINT backend requires the simple name 'string') _converters["std::basic_string<char>"] = StdStringConverter -_converters["string"] = _converters["std::basic_string<char>"] _converters["const std::basic_string<char>&"] = StdStringConverter # TODO: shouldn't copy -_converters["const string&"] = _converters["const std::basic_string<char>&"] _converters["std::basic_string<char>&"] = StdStringRefConverter -_converters["string&"] = _converters["std::basic_string<char>&"] _converters["PyObject*"] = PyObjectConverter -_converters["_object*"] = _converters["PyObject*"] +# add the set of aliased names +def _add_aliased_converters(): + "NOT_RPYTHON" + alias_info = ( + ("char", ("unsigned char",)), + + ("short", ("short int",)), + ("unsigned short", ("unsigned short int",)), + ("unsigned", ("unsigned int",)), + ("long", ("long int",)), + ("const long&", ("const long int&",)), + ("unsigned long", ("unsigned long int",)), + ("long long", ("long long int",)), + ("const long long&", ("const long long int&",)), + ("unsigned long long", ("unsigned long long int",)), + + ("const char*", ("char*",)), + + ("std::basic_string<char>", ("string",)), + ("const std::basic_string<char>&", ("const string&",)), + ("std::basic_string<char>&", ("string&",)), + + ("PyObject*", ("_object*",)), + ) + + for info in alias_info: + for name in info[1]: + _converters[name] = _converters[info[0]] +_add_aliased_converters() + +# constref converters exist only b/c the stubs take constref by value, whereas +# libffi takes them by pointer (hence it needs the fast-path in testing); note +# that this is list is not complete, as some classes are specialized +def _build_constref_converters(): + "NOT_RPYTHON" + type_info = ( + (ShortConverter, ("short int", "short")), + (UnsignedShortConverter, ("unsigned short int", "unsigned short")), + (IntConverter, ("int",)), + (UnsignedIntConverter, ("unsigned int", "unsigned")), + (UnsignedLongConverter, ("unsigned long int", "unsigned long")), + (UnsignedLongLongConverter, ("unsigned long long int", "unsigned long long")), + ) + + for info in type_info: + class ConstRefConverter(ConstRefNumericTypeConverterMixin, info[0]): + _immutable_ = True + libffitype = libffi.types.pointer + for name in info[1]: + _converters["const "+name+"&"] = ConstRefConverter +_build_constref_converters() + +# create the array and pointer converters; all real work is in the mixins def _build_array_converters(): "NOT_RPYTHON" array_info = ( diff --git a/pypy/module/cppyy/executor.py b/pypy/module/cppyy/executor.py --- a/pypy/module/cppyy/executor.py +++ b/pypy/module/cppyy/executor.py @@ -10,6 +10,19 @@ from pypy.module.cppyy import helper, capi +# Executor objects are used to dispatch C++ methods. They are defined by their +# return type only: arguments are converted by Converter objects, and Executors +# only deal with arrays of memory that are either passed to a stub or libffi. +# No argument checking or conversions are done. +# +# If a libffi function is not implemented, FastCallNotPossible is raised. If a +# stub function is missing (e.g. if no reflection info is available for the +# return type), an app-level TypeError is raised. +# +# Executor instances are created by get_executor(<return type name>), see +# below. The name given should be qualified in case there is a specialised, +# exact match for the qualified type. + NULL = lltype.nullptr(clibffi.FFI_TYPE_P.TO) @@ -235,38 +248,6 @@ result = rffi.charp2str(ccpresult) # TODO: make it a choice to free return space.wrap(result) -class BoolPtrExecutor(PtrTypeExecutor): - _immutable_ = True - typecode = 'b' # really unsigned char, but this works ... - -class ShortPtrExecutor(PtrTypeExecutor): - _immutable_ = True - typecode = 'h' - -class IntPtrExecutor(PtrTypeExecutor): - _immutable_ = True - typecode = 'i' - -class UnsignedIntPtrExecutor(PtrTypeExecutor): - _immutable_ = True - typecode = 'I' - -class LongPtrExecutor(PtrTypeExecutor): - _immutable_ = True - typecode = 'l' - -class UnsignedLongPtrExecutor(PtrTypeExecutor): - _immutable_ = True - typecode = 'L' - -class FloatPtrExecutor(PtrTypeExecutor): - _immutable_ = True - typecode = 'f' - -class DoublePtrExecutor(PtrTypeExecutor): - _immutable_ = True - typecode = 'd' - class ConstructorExecutor(VoidExecutor): _immutable_ = True @@ -426,24 +407,17 @@ _executors["void*"] = PtrTypeExecutor _executors["bool"] = BoolExecutor _executors["char"] = CharExecutor -_executors["char*"] = CStringExecutor -_executors["unsigned char"] = CharExecutor -_executors["short int"] = ShortExecutor -_executors["short"] = _executors["short int"] -_executors["unsigned short int"] = ShortExecutor -_executors["unsigned short"] = _executors["unsigned short int"] +_executors["const char*"] = CStringExecutor +_executors["short"] = ShortExecutor +_executors["unsigned short"] = ShortExecutor _executors["int"] = IntExecutor _executors["const int&"] = ConstIntRefExecutor _executors["int&"] = ConstIntRefExecutor -_executors["unsigned int"] = UnsignedIntExecutor -_executors["long int"] = LongExecutor -_executors["long"] = _executors["long int"] -_executors["unsigned long int"] = UnsignedLongExecutor -_executors["unsigned long"] = _executors["unsigned long int"] -_executors["long long int"] = LongLongExecutor -_executors["long long"] = _executors["long long int"] -_executors["unsigned long long int"] = UnsignedLongLongExecutor -_executors["unsigned long long"] = _executors["unsigned long long int"] +_executors["unsigned"] = UnsignedIntExecutor +_executors["long"] = LongExecutor +_executors["unsigned long"] = UnsignedLongExecutor +_executors["long long"] = LongLongExecutor +_executors["unsigned long long"] = UnsignedLongLongExecutor _executors["float"] = FloatExecutor _executors["double"] = DoubleExecutor @@ -451,11 +425,37 @@ # special cases (note: CINT backend requires the simple name 'string') _executors["std::basic_string<char>"] = StdStringExecutor -_executors["string"] = _executors["std::basic_string<char>"] _executors["PyObject*"] = PyObjectExecutor -_executors["_object*"] = _executors["PyObject*"] +# add the set of aliased names +def _add_aliased_executors(): + "NOT_RPYTHON" + alias_info = ( + ("char", ("unsigned char",)), + + ("short", ("short int",)), + ("unsigned short", ("unsigned short int",)), + ("unsigned", ("unsigned int",)), + ("long", ("long int",)), + ("unsigned long", ("unsigned long int",)), + ("long long", ("long long int",)), + ("unsigned long long", ("unsigned long long int",)), + + ("const char*", ("char*",)), + + ("std::basic_string<char>", ("string",)), + + ("PyObject*", ("_object*",)), + ) + + for info in alias_info: + for name in info[1]: + _executors[name] = _executors[info[0]] +_add_aliased_executors() + +# create the pointer executors; all real work is in the PtrTypeExecutor, since +# all pointer types are of the same size def _build_ptr_executors(): "NOT_RPYTHON" ptr_info = ( diff --git a/pypy/module/cppyy/interp_cppyy.py b/pypy/module/cppyy/interp_cppyy.py --- a/pypy/module/cppyy/interp_cppyy.py +++ b/pypy/module/cppyy/interp_cppyy.py @@ -823,11 +823,13 @@ @unwrap_spec(cppinstance=W_CPPInstance) def addressof(space, cppinstance): + """Takes a bound C++ instance, returns the raw address.""" address = rffi.cast(rffi.LONG, cppinstance.get_rawobject()) return space.wrap(address) @unwrap_spec(address=int, owns=bool) def bind_object(space, address, w_pycppclass, owns=False): + """Takes an address and a bound C++ class proxy, returns a bound instance.""" rawobject = rffi.cast(capi.C_OBJECT, address) w_cppclass = space.findattr(w_pycppclass, space.wrap("_cpp_proxy")) cppclass = space.interp_w(W_CPPClass, w_cppclass, can_be_None=False) diff --git a/pypy/module/cppyy/pythonify.py b/pypy/module/cppyy/pythonify.py --- a/pypy/module/cppyy/pythonify.py +++ b/pypy/module/cppyy/pythonify.py @@ -366,18 +366,21 @@ _loaded_dictionaries = {} def load_reflection_info(name): + """Takes the name of a library containing reflection info, returns a handle + to the loaded library.""" try: return _loaded_dictionaries[name] except KeyError: - dct = cppyy._load_dictionary(name) - _loaded_dictionaries[name] = dct - return dct + lib = cppyy._load_dictionary(name) + _loaded_dictionaries[name] = lib + return lib # user interface objects (note the two-step of not calling scope_byname here: # creation of global functions may cause the creation of classes in the global # namespace, so gbl must exist at that point to cache them) gbl = make_cppnamespace(None, "::", None, False) # global C++ namespace +gbl.__doc__ = "Global C++ namespace." sys.modules['cppyy.gbl'] = gbl # mostly for the benefit of the CINT backend, which treats std as special @@ -387,6 +390,9 @@ # user-defined pythonizations interface _pythonizations = {} def add_pythonization(class_name, callback): + """Takes a class name and a callback. The callback should take a single + argument, the class proxy, and is called the first time the named class + is bound.""" if not callable(callback): raise TypeError("given '%s' object is not callable" % str(callback)) _pythonizations[class_name] = callback _______________________________________________ pypy-commit mailing list [email protected] http://mail.python.org/mailman/listinfo/pypy-commit
