[pypy-commit] pypy reflex-support: refactoring all duplicated codes from converter.py and executor.py
wlav
noreply at buildbot.pypy.org
Wed Jul 11 09:28:22 CEST 2012
Author: Wim Lavrijsen <WLavrijsen at lbl.gov>
Branch: reflex-support
Changeset: r56022:9948a2bd6028
Date: 2012-07-11 00:28 -0700
http://bitbucket.org/pypy/pypy/changeset/9948a2bd6028/
Log: refactoring all duplicated codes from converter.py and executor.py
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
@@ -4,12 +4,12 @@
from pypy.rpython.lltypesystem import rffi, lltype
from pypy.rlib.rarithmetic import r_singlefloat
-from pypy.rlib import jit, libffi, clibffi, rfloat
+from pypy.rlib import libffi, clibffi, rfloat
from pypy.module._rawffi.interp_rawffi import unpack_simple_shape
from pypy.module._rawffi.array import W_Array
-from pypy.module.cppyy import helper, capi
+from pypy.module.cppyy import helper, capi, ffitypes
# 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
@@ -276,26 +276,8 @@
else:
address[0] = '\x00'
-class CharConverter(TypeConverter):
+class CharConverter(ffitypes.typeid(rffi.CHAR), TypeConverter):
_immutable_ = True
- libffitype = libffi.types.schar
-
- def _unwrap_object(self, space, w_value):
- # allow int to pass to char and make sure that str is of length 1
- if space.isinstance_w(w_value, space.w_int):
- ival = space.c_int_w(w_value)
- if ival < 0 or 256 <= ival:
- raise OperationError(space.w_ValueError,
- space.wrap("char arg not in range(256)"))
-
- value = rffi.cast(rffi.CHAR, space.c_int_w(w_value))
- else:
- value = space.str_w(w_value)
-
- if len(value) != 1:
- raise OperationError(space.w_ValueError,
- space.wrap("char expected, got string of size %d" % len(value)))
- return value[0] # turn it into a "char" to the annotator
def convert_argument(self, space, w_obj, address, call_local):
x = rffi.cast(rffi.CCHARP, address)
@@ -312,132 +294,8 @@
address = rffi.cast(rffi.CCHARP, self._get_raw_address(space, w_obj, offset))
address[0] = self._unwrap_object(space, w_value)
-
-class ShortConverter(IntTypeConverterMixin, TypeConverter):
+class FloatConverter(ffitypes.typeid(rffi.FLOAT), FloatTypeConverterMixin, TypeConverter):
_immutable_ = True
- libffitype = libffi.types.sshort
- c_type = rffi.SHORT
- c_ptrtype = rffi.SHORTP
-
- def __init__(self, space, default):
- self.default = rffi.cast(rffi.SHORT, capi.c_strtoll(default))
-
- def _unwrap_object(self, space, w_obj):
- return rffi.cast(rffi.SHORT, space.int_w(w_obj))
-
-class UnsignedShortConverter(IntTypeConverterMixin, TypeConverter):
- _immutable_ = True
- libffitype = libffi.types.sshort
- c_type = rffi.USHORT
- c_ptrtype = rffi.USHORTP
-
- def __init__(self, space, default):
- self.default = rffi.cast(self.c_type, capi.c_strtoull(default))
-
- def _unwrap_object(self, space, w_obj):
- return rffi.cast(self.c_type, space.int_w(w_obj))
-
-class IntConverter(IntTypeConverterMixin, TypeConverter):
- _immutable_ = True
- libffitype = libffi.types.sint
- c_type = rffi.INT
- c_ptrtype = rffi.INTP
-
- def __init__(self, space, default):
- self.default = rffi.cast(self.c_type, capi.c_strtoll(default))
-
- def _unwrap_object(self, space, w_obj):
- return rffi.cast(self.c_type, space.c_int_w(w_obj))
-
-class UnsignedIntConverter(IntTypeConverterMixin, TypeConverter):
- _immutable_ = True
- libffitype = libffi.types.uint
- c_type = rffi.UINT
- c_ptrtype = rffi.UINTP
-
- def __init__(self, space, default):
- self.default = rffi.cast(self.c_type, capi.c_strtoull(default))
-
- def _unwrap_object(self, space, w_obj):
- return rffi.cast(self.c_type, space.uint_w(w_obj))
-
-class LongConverter(IntTypeConverterMixin, TypeConverter):
- _immutable_ = True
- libffitype = libffi.types.slong
- c_type = rffi.LONG
- c_ptrtype = rffi.LONGP
-
- def __init__(self, space, default):
- self.default = rffi.cast(self.c_type, capi.c_strtoll(default))
-
- def _unwrap_object(self, space, w_obj):
- return space.int_w(w_obj)
-
-class ConstLongRefConverter(ConstRefNumericTypeConverterMixin, LongConverter):
- _immutable_ = True
- libffitype = libffi.types.pointer
- typecode = 'r'
-
- def convert_argument(self, space, w_obj, address, call_local):
- x = rffi.cast(self.c_ptrtype, address)
- x[0] = self._unwrap_object(space, w_obj)
- ba = rffi.cast(rffi.CCHARP, address)
- ba[capi.c_function_arg_typeoffset()] = self.typecode
-
-class LongLongConverter(IntTypeConverterMixin, TypeConverter):
- _immutable_ = True
- libffitype = libffi.types.slong
- c_type = rffi.LONGLONG
- c_ptrtype = rffi.LONGLONGP
-
- def __init__(self, space, default):
- self.default = rffi.cast(self.c_type, capi.c_strtoll(default))
-
- def _unwrap_object(self, space, w_obj):
- return space.r_longlong_w(w_obj)
-
-class ConstLongLongRefConverter(ConstRefNumericTypeConverterMixin, LongLongConverter):
- _immutable_ = True
- libffitype = libffi.types.pointer
- typecode = 'r'
-
- def convert_argument(self, space, w_obj, address, call_local):
- x = rffi.cast(self.c_ptrtype, address)
- x[0] = self._unwrap_object(space, w_obj)
- ba = rffi.cast(rffi.CCHARP, address)
- ba[capi.c_function_arg_typeoffset()] = self.typecode
-
-class UnsignedLongConverter(IntTypeConverterMixin, TypeConverter):
- _immutable_ = True
- libffitype = libffi.types.ulong
- c_type = rffi.ULONG
- c_ptrtype = rffi.ULONGP
-
- def __init__(self, space, default):
- self.default = rffi.cast(self.c_type, capi.c_strtoull(default))
-
- def _unwrap_object(self, space, w_obj):
- return space.uint_w(w_obj)
-
-class UnsignedLongLongConverter(IntTypeConverterMixin, TypeConverter):
- _immutable_ = True
- libffitype = libffi.types.ulong
- c_type = rffi.ULONGLONG
- c_ptrtype = rffi.ULONGLONGP
-
- def __init__(self, space, default):
- self.default = rffi.cast(self.c_type, capi.c_strtoull(default))
-
- def _unwrap_object(self, space, w_obj):
- return space.r_ulonglong_w(w_obj)
-
-
-class FloatConverter(FloatTypeConverterMixin, TypeConverter):
- _immutable_ = True
- libffitype = libffi.types.float
- c_type = rffi.FLOAT
- c_ptrtype = rffi.FLOATP
- typecode = 'f'
def __init__(self, space, default):
if default:
@@ -446,9 +304,6 @@
fval = float(0.)
self.default = r_singlefloat(fval)
- def _unwrap_object(self, space, w_obj):
- return r_singlefloat(space.float_w(w_obj))
-
def from_memory(self, space, w_obj, w_pycppclass, offset):
address = self._get_raw_address(space, w_obj, offset)
rffiptr = rffi.cast(self.c_ptrtype, address)
@@ -463,12 +318,8 @@
from pypy.module.cppyy.interp_cppyy import FastCallNotPossible
raise FastCallNotPossible
-class DoubleConverter(FloatTypeConverterMixin, TypeConverter):
+class DoubleConverter(ffitypes.typeid(rffi.DOUBLE), FloatTypeConverterMixin, TypeConverter):
_immutable_ = True
- libffitype = libffi.types.double
- c_type = rffi.DOUBLE
- c_ptrtype = rffi.DOUBLEP
- typecode = 'd'
def __init__(self, space, default):
if default:
@@ -476,9 +327,6 @@
else:
self.default = rffi.cast(self.c_type, 0.)
- def _unwrap_object(self, space, w_obj):
- return space.float_w(w_obj)
-
class ConstDoubleRefConverter(ConstRefNumericTypeConverterMixin, DoubleConverter):
_immutable_ = True
libffitype = libffi.types.pointer
@@ -750,8 +598,8 @@
elif compound == "":
return InstanceConverter(space, cppclass)
elif capi.c_is_enum(clean_name):
- return UnsignedIntConverter(space, default)
-
+ return _converters['unsigned'](space, default)
+
# 5) void converter, which fails on use
#
# return a void converter here, so that the class can be build even
@@ -761,16 +609,6 @@
_converters["bool"] = BoolConverter
_converters["char"] = CharConverter
-_converters["short"] = ShortConverter
-_converters["unsigned short"] = UnsignedShortConverter
-_converters["int"] = IntConverter
-_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
@@ -787,57 +625,74 @@
_converters["PyObject*"] = PyObjectConverter
-# add the set of aliased names
-def _add_aliased_converters():
+# add basic (builtin) converters
+def _build_basic_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*",)),
+ # signed types (use strtoll in setting of default in __init__)
+ type_info = (
+ (rffi.SHORT, ("short", "short int")),
+ (rffi.INT, ("int",)),
)
- 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
-# 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"
+ for c_type, names in type_info:
+ class BasicConverter(ffitypes.typeid(c_type), IntTypeConverterMixin, TypeConverter):
+ _immutable_ = True
+ def __init__(self, space, default):
+ self.default = rffi.cast(self.c_type, capi.c_strtoll(default))
+ class ConstRefConverter(ConstRefNumericTypeConverterMixin, BasicConverter):
+ _immutable_ = True
+ libffitype = libffi.types.pointer
+ for name in names:
+ _converters[name] = BasicConverter
+ _converters["const "+name+"&"] = ConstRefConverter
+
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")),
+ (rffi.LONG, ("long", "long int")),
+ (rffi.LONGLONG, ("long long", "long long int")),
)
- for info in type_info:
- class ConstRefConverter(ConstRefNumericTypeConverterMixin, info[0]):
+ for c_type, names in type_info:
+ class BasicConverter(ffitypes.typeid(c_type), IntTypeConverterMixin, TypeConverter):
+ _immutable_ = True
+ def __init__(self, space, default):
+ self.default = rffi.cast(self.c_type, capi.c_strtoll(default))
+ class ConstRefConverter(ConstRefNumericTypeConverterMixin, BasicConverter):
_immutable_ = True
libffitype = libffi.types.pointer
- for name in info[1]:
+ typecode = 'r'
+ def convert_argument(self, space, w_obj, address, call_local):
+ x = rffi.cast(self.c_ptrtype, address)
+ x[0] = self._unwrap_object(space, w_obj)
+ ba = rffi.cast(rffi.CCHARP, address)
+ ba[capi.c_function_arg_typeoffset()] = self.typecode
+ for name in names:
+ _converters[name] = BasicConverter
_converters["const "+name+"&"] = ConstRefConverter
-_build_constref_converters()
+
+ # unsigned integer types (use strtoull in setting of default in __init__)
+ type_info = (
+ (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")),
+ )
+
+ for c_type, names in type_info:
+ class BasicConverter(ffitypes.typeid(c_type), IntTypeConverterMixin, TypeConverter):
+ _immutable_ = True
+ def __init__(self, space, default):
+ self.default = rffi.cast(self.c_type, capi.c_strtoull(default))
+ class ConstRefConverter(ConstRefNumericTypeConverterMixin, BasicConverter):
+ _immutable_ = True
+ libffitype = libffi.types.pointer
+ for name in names:
+ _converters[name] = BasicConverter
+ _converters["const "+name+"&"] = ConstRefConverter
+_build_basic_converters()
# create the array and pointer converters; all real work is in the mixins
def _build_array_converters():
@@ -854,16 +709,35 @@
('d', rffi.sizeof(rffi.DOUBLE), ("double",)),
)
- for info in array_info:
+ for tcode, tsize, names in array_info:
class ArrayConverter(ArrayTypeConverterMixin, TypeConverter):
_immutable_ = True
- typecode = info[0]
- typesize = info[1]
+ typecode = tcode
+ typesize = tsize
class PtrConverter(PtrTypeConverterMixin, TypeConverter):
_immutable_ = True
- typecode = info[0]
- typesize = info[1]
- for name in info[2]:
+ typecode = tcode
+ typesize = tsize
+ for name in names:
_a_converters[name+'[]'] = ArrayConverter
_a_converters[name+'*'] = PtrConverter
_build_array_converters()
+
+# add another set of aliased names
+def _add_aliased_converters():
+ "NOT_RPYTHON"
+ aliases = (
+ ("char", "unsigned char"),
+ ("const char*", "char*"),
+
+ ("std::basic_string<char>", "string"),
+ ("const std::basic_string<char>&", "const string&"),
+ ("std::basic_string<char>&", "string&"),
+
+ ("PyObject*", "_object*"),
+ )
+
+ for c_type, alias in aliases:
+ _converters[alias] = _converters[c_type]
+_add_aliased_converters()
+
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
@@ -8,7 +8,7 @@
from pypy.module._rawffi.interp_rawffi import unpack_simple_shape
from pypy.module._rawffi.array import W_Array
-from pypy.module.cppyy import helper, capi
+from pypy.module.cppyy import helper, capi, ffitypes
# Executor objects are used to dispatch C++ methods. They are defined by their
# return type only: arguments are converted by Converter objects, and Executors
@@ -83,6 +83,32 @@
result = libffifunc.call(argchain, self.c_type)
return space.wrap(result)
+class NumericRefExecutorMixin(object):
+ _mixin_ = True
+ _immutable_ = True
+
+ def __init__(self, space, extra):
+ FunctionExecutor.__init__(self, space, extra)
+ self.do_assign = False
+ self.item = rffi.cast(self.c_type, 0)
+
+ def set_item(self, space, w_item):
+ self.item = self._unwrap_object(space, w_item)
+ self.do_assign = True
+
+ def _wrap_result(self, space, rffiptr):
+ if self.do_assign:
+ rffiptr[0] = self.item
+ return space.wrap(rffiptr[0]) # all paths, for rtyper
+
+ def execute(self, space, cppmethod, cppthis, num_args, args):
+ result = rffi.cast(self.c_ptrtype, capi.c_call_r(cppmethod, cppthis, num_args, args))
+ return self._wrap_result(space, result)
+
+ def execute_libffi(self, space, libffifunc, argchain):
+ result = libffifunc.call(argchain, self.c_ptrtype)
+ return self._wrap_result(space, result)
+
class BoolExecutor(FunctionExecutor):
_immutable_ = True
@@ -112,32 +138,6 @@
result = libffifunc.call(argchain, rffi.INTP)
return space.wrap(result[0])
-class IntRefExecutor(FunctionExecutor):
- _immutable_ = True
- libffitype = libffi.types.pointer
-
- def __init__(self, space, extra):
- FunctionExecutor.__init__(self, space, extra)
- self.do_assign = False
- self.item = rffi.cast(rffi.INT, 0)
-
- def set_item(self, space, w_item):
- self.item = rffi.cast(rffi.INT, space.c_int_w(w_item))
- self.do_assign = True
-
- def _wrap_result(self, space, intptr):
- if self.do_assign:
- intptr[0] = self.item
- return space.wrap(intptr[0]) # all paths, for rtyper
-
- def execute(self, space, cppmethod, cppthis, num_args, args):
- result = rffi.cast(rffi.INTP, capi.c_call_r(cppmethod, cppthis, num_args, args))
- return self._wrap_result(space, result)
-
- def execute_libffi(self, space, libffifunc, argchain):
- result = libffifunc.call(argchain, rffi.INTP)
- return self._wrap_result(space, result)
-
class ConstLongRefExecutor(ConstIntRefExecutor):
_immutable_ = True
libffitype = libffi.types.pointer
@@ -162,32 +162,6 @@
result = libffifunc.call(argchain, rffi.FLOAT)
return space.wrap(float(result))
-class DoubleRefExecutor(FunctionExecutor):
- _immutable_ = True
- libffitype = libffi.types.pointer
-
- def __init__(self, space, extra):
- FunctionExecutor.__init__(self, space, extra)
- self.do_assign = False
- self.item = rffi.cast(rffi.DOUBLE, 0)
-
- def set_item(self, space, w_item):
- self.item = rffi.cast(rffi.DOUBLE, space.float_w(w_item))
- self.do_assign = True
-
- def _wrap_result(self, space, dptr):
- if self.do_assign:
- dptr[0] = self.item
- return space.wrap(dptr[0]) # all paths, for rtyper
-
- def execute(self, space, cppmethod, cppthis, num_args, args):
- result = rffi.cast(rffi.DOUBLEP, capi.c_call_r(cppmethod, cppthis, num_args, args))
- return self._wrap_result(space, result)
-
- def execute_libffi(self, space, libffifunc, argchain):
- result = libffifunc.call(argchain, rffi.DOUBLEP)
- return self._wrap_result(space, result)
-
class CStringExecutor(FunctionExecutor):
_immutable_ = True
@@ -358,14 +332,14 @@
_executors["bool"] = BoolExecutor
_executors["const char*"] = CStringExecutor
_executors["const int&"] = ConstIntRefExecutor
-_executors["int&"] = IntRefExecutor
_executors["float"] = FloatExecutor
-_executors["double&"] = DoubleRefExecutor
_executors["constructor"] = ConstructorExecutor
-# special cases (note: CINT backend requires the simple name 'string')
-_executors["std::basic_string<char>"] = StdStringExecutor
+# special cases
+_executors["std::basic_string<char>"] = StdStringExecutor
+_executors["const std::basic_string<char>&"] = StdStringExecutor
+_executors["std::basic_string<char>&"] = StdStringExecutor # TODO: shouldn't copy
_executors["PyObject*"] = PyObjectExecutor
@@ -373,41 +347,29 @@
def _build_basic_executors():
"NOT_RPYTHON"
type_info = (
- (rffi.CHAR, libffi.types.schar, capi.c_call_c, ("char", "unsigned char")),
- (rffi.SHORT, libffi.types.sshort, capi.c_call_h, ("short", "short int", "unsigned short", "unsigned short int")),
- (rffi.INT, libffi.types.sint, capi.c_call_i, ("int",)),
- (rffi.UINT, libffi.types.uint, capi.c_call_l, ("unsigned", "unsigned int")),
- (rffi.LONG, libffi.types.slong, capi.c_call_l, ("long", "long int")),
- (rffi.ULONG, libffi.types.ulong, capi.c_call_l, ("unsigned long", "unsigned long int")),
- (rffi.LONGLONG, libffi.types.sint64, capi.c_call_ll, ("long long", "long long int")),
- (rffi.ULONGLONG, libffi.types.uint64, capi.c_call_ll, ("unsigned long long", "unsigned long long int")),
- (rffi.DOUBLE, libffi.types.double, capi.c_call_d, ("double",))
+ (rffi.CHAR, capi.c_call_c, ("char", "unsigned char")),
+ (rffi.SHORT, capi.c_call_h, ("short", "short int", "unsigned short", "unsigned short int")),
+ (rffi.INT, capi.c_call_i, ("int",)),
+ (rffi.UINT, capi.c_call_l, ("unsigned", "unsigned int")),
+ (rffi.LONG, capi.c_call_l, ("long", "long int")),
+ (rffi.ULONG, capi.c_call_l, ("unsigned long", "unsigned long int")),
+ (rffi.LONGLONG, capi.c_call_ll, ("long long", "long long int")),
+ (rffi.ULONGLONG, capi.c_call_ll, ("unsigned long long", "unsigned long long int")),
+ (rffi.DOUBLE, capi.c_call_d, ("double",))
)
- for t_rffi, t_ffi, stub, names in type_info:
- class BasicExecutor(NumericExecutorMixin, FunctionExecutor):
+ for c_type, stub, names in type_info:
+ class BasicExecutor(ffitypes.typeid(c_type), NumericExecutorMixin, FunctionExecutor):
_immutable_ = True
- libffitype = t_ffi
- c_type = t_rffi
c_stubcall = staticmethod(stub)
+ class BasicRefExecutor(ffitypes.typeid(c_type), NumericRefExecutorMixin, FunctionExecutor):
+ _immutable_ = True
+ libffitype = libffi.types.pointer
for name in names:
- _executors[name] = BasicExecutor
+ _executors[name] = BasicExecutor
+ _executors[name+'&'] = BasicRefExecutor
_build_basic_executors()
-# add the set of aliased names
-def _add_aliased_executors():
- "NOT_RPYTHON"
- alias_info = (
- ("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():
@@ -424,10 +386,23 @@
('d', ("double",)),
)
- for info in ptr_info:
+ for tcode, names in ptr_info:
class PtrExecutor(PtrTypeExecutor):
_immutable_ = True
- typecode = info[0]
- for name in info[1]:
+ typecode = tcode
+ for name in names:
_executors[name+'*'] = PtrExecutor
_build_ptr_executors()
+
+# add another set of aliased names
+def _add_aliased_executors():
+ "NOT_RPYTHON"
+ aliases = (
+ ("const char*", "char*"),
+ ("std::basic_string<char>", "string"),
+ ("PyObject*", "_object*"),
+ )
+
+ for c_type, alias in aliases:
+ _executors[alias] = _executors[c_type]
+_add_aliased_executors()
diff --git a/pypy/module/cppyy/ffitypes.py b/pypy/module/cppyy/ffitypes.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/cppyy/ffitypes.py
@@ -0,0 +1,155 @@
+from pypy.interpreter.error import OperationError
+
+from pypy.rpython.lltypesystem import rffi
+from pypy.rlib.rarithmetic import r_singlefloat
+from pypy.rlib import libffi, rfloat
+
+# Mixins to share between converter and executor classes (in converter.py and
+# executor.py, respectively). Basically these mixins allow grouping of the
+# sets of libffi, rffi, and different space unwrapping calls. To get the right
+# mixin, a non-RPython function typeid() is used.
+
+
+class CharTypeMixin(object):
+ _mixin_ = True
+ _immutable_ = True
+ libffitype = libffi.types.schar
+ c_type = rffi.CHAR
+ c_ptrtype = rffi.CCHARP # there's no such thing as rffi.CHARP
+
+ def _unwrap_object(self, space, w_value):
+ # allow int to pass to char and make sure that str is of length 1
+ if space.isinstance_w(w_value, space.w_int):
+ ival = space.c_int_w(w_value)
+ if ival < 0 or 256 <= ival:
+ raise OperationError(space.w_ValueError,
+ space.wrap("char arg not in range(256)"))
+
+ value = rffi.cast(rffi.CHAR, space.c_int_w(w_value))
+ else:
+ value = space.str_w(w_value)
+
+ if len(value) != 1:
+ raise OperationError(space.w_ValueError,
+ space.wrap("char expected, got string of size %d" % len(value)))
+ return value[0] # turn it into a "char" to the annotator
+
+class ShortTypeMixin(object):
+ _mixin_ = True
+ _immutable_ = True
+ libffitype = libffi.types.sshort
+ c_type = rffi.SHORT
+ c_ptrtype = rffi.SHORTP
+
+ def _unwrap_object(self, space, w_obj):
+ return rffi.cast(rffi.SHORT, space.int_w(w_obj))
+
+class UShortTypeMixin(object):
+ _mixin_ = True
+ _immutable_ = True
+ libffitype = libffi.types.ushort
+ c_type = rffi.USHORT
+ c_ptrtype = rffi.USHORTP
+
+ def _unwrap_object(self, space, w_obj):
+ return rffi.cast(self.c_type, space.int_w(w_obj))
+
+class IntTypeMixin(object):
+ _mixin_ = True
+ _immutable_ = True
+ libffitype = libffi.types.sint
+ c_type = rffi.INT
+ c_ptrtype = rffi.INTP
+
+ def _unwrap_object(self, space, w_obj):
+ return rffi.cast(self.c_type, space.c_int_w(w_obj))
+
+class UIntTypeMixin(object):
+ _mixin_ = True
+ _immutable_ = True
+ libffitype = libffi.types.uint
+ c_type = rffi.UINT
+ c_ptrtype = rffi.UINTP
+
+ def _unwrap_object(self, space, w_obj):
+ return rffi.cast(self.c_type, space.uint_w(w_obj))
+
+class LongTypeMixin(object):
+ _mixin_ = True
+ _immutable_ = True
+ libffitype = libffi.types.slong
+ c_type = rffi.LONG
+ c_ptrtype = rffi.LONGP
+
+ def _unwrap_object(self, space, w_obj):
+ return space.int_w(w_obj)
+
+class ULongTypeMixin(object):
+ _mixin_ = True
+ _immutable_ = True
+ libffitype = libffi.types.ulong
+ c_type = rffi.ULONG
+ c_ptrtype = rffi.ULONGP
+
+ def _unwrap_object(self, space, w_obj):
+ return space.uint_w(w_obj)
+
+class LongLongTypeMixin(object):
+ _mixin_ = True
+ _immutable_ = True
+ libffitype = libffi.types.sint64
+ c_type = rffi.LONGLONG
+ c_ptrtype = rffi.LONGLONGP
+
+ def _unwrap_object(self, space, w_obj):
+ return space.r_longlong_w(w_obj)
+
+class ULongLongTypeMixin(object):
+ _mixin_ = True
+ _immutable_ = True
+ libffitype = libffi.types.uint64
+ c_type = rffi.ULONGLONG
+ c_ptrtype = rffi.ULONGLONGP
+
+ def _unwrap_object(self, space, w_obj):
+ return space.r_ulonglong_w(w_obj)
+
+class FloatTypeMixin(object):
+ _mixin_ = True
+ _immutable_ = True
+ libffitype = libffi.types.float
+ c_type = rffi.FLOAT
+ c_ptrtype = rffi.FLOATP
+ typecode = 'f'
+
+ def _unwrap_object(self, space, w_obj):
+ return r_singlefloat(space.float_w(w_obj))
+
+class DoubleTypeMixin(object):
+ _mixin_ = True
+ _immutable_ = True
+ libffitype = libffi.types.double
+ c_type = rffi.DOUBLE
+ c_ptrtype = rffi.DOUBLEP
+ typecode = 'd'
+
+ def _unwrap_object(self, space, w_obj):
+ return space.float_w(w_obj)
+
+
+def typeid(c_type):
+ "NOT_RPYTHON"
+ if c_type == rffi.CHAR: return CharTypeMixin
+ if c_type == rffi.SHORT: return ShortTypeMixin
+ if c_type == rffi.USHORT: return UShortTypeMixin
+ if c_type == rffi.INT: return IntTypeMixin
+ if c_type == rffi.UINT: return UIntTypeMixin
+ if c_type == rffi.LONG: return LongTypeMixin
+ if c_type == rffi.ULONG: return ULongTypeMixin
+ if c_type == rffi.LONGLONG: return LongLongTypeMixin
+ if c_type == rffi.ULONGLONG: return ULongLongTypeMixin
+ if c_type == rffi.FLOAT: return FloatTypeMixin
+ if c_type == rffi.DOUBLE: return DoubleTypeMixin
+
+ # should never get here
+ raise TypeError("unknown rffi type: %s" % c_type)
More information about the pypy-commit
mailing list