[pypy-svn] r74443 - in pypy/trunk/pypy/module/cpyext: . include test
afa at codespeak.net
afa at codespeak.net
Sat May 8 14:38:30 CEST 2010
Author: afa
Date: Sat May 8 14:38:29 2010
New Revision: 74443
Added:
pypy/trunk/pypy/module/cpyext/include/complexobject.h
Modified:
pypy/trunk/pypy/module/cpyext/complexobject.py
pypy/trunk/pypy/module/cpyext/include/Python.h
pypy/trunk/pypy/module/cpyext/stubs.py
pypy/trunk/pypy/module/cpyext/test/test_complexobject.py
Log:
Implement PyComplex_AsCComplex, it's an inlined function around a cpyext method
because lltype does not handle functions returning structures.
Modified: pypy/trunk/pypy/module/cpyext/complexobject.py
==============================================================================
--- pypy/trunk/pypy/module/cpyext/complexobject.py (original)
+++ pypy/trunk/pypy/module/cpyext/complexobject.py Sat May 8 14:38:29 2010
@@ -1,9 +1,18 @@
-from pypy.rpython.lltypesystem import lltype
-from pypy.module.cpyext.api import cpython_api, PyObject, build_type_checkers
+from pypy.rpython.lltypesystem import lltype, rffi
+from pypy.module.cpyext.api import (
+ cpython_api, cpython_struct, PyObject, build_type_checkers)
+from pypy.module.cpyext.pyerrors import PyErr_BadArgument
+from pypy.module.cpyext.floatobject import PyFloat_AsDouble
from pypy.objspace.std.complexobject import W_ComplexObject
+from pypy.interpreter.error import OperationError
PyComplex_Check, PyComplex_CheckExact = build_type_checkers("Complex")
+Py_complex_t = lltype.ForwardReference()
+Py_complex_ptr = lltype.Ptr(Py_complex_t)
+Py_complex_fields = (("real", rffi.DOUBLE), ("imag", rffi.DOUBLE))
+cpython_struct("Py_complex", Py_complex_fields, Py_complex_t)
+
@cpython_api([lltype.Float, lltype.Float], PyObject)
def PyComplex_FromDoubles(space, real, imag):
return space.newcomplex(real, imag)
@@ -25,3 +34,31 @@
# CPython also accepts anything
return 0.0
+# lltype does not handle functions returning a structure. This implements a
+# helper function, which takes as argument a reference to the return value.
+ at cpython_api([PyObject, Py_complex_ptr], lltype.Void, error=None)
+def _PyComplex_AsCComplex(space, w_obj, result):
+ """Return the Py_complex value of the complex number op.
+
+ If op is not a Python complex number object but has a __complex__()
+ method, this method will first be called to convert op to a Python complex
+ number object."""
+ # return -1 on failure
+ result.c_real = -1.0
+ result.c_imag = 0.0
+ if not PyComplex_Check(space, w_obj):
+ try:
+ w_obj = space.call_method(w_obj, "__complex__")
+ except:
+ # if the above did not work, interpret obj as a float giving the
+ # real part of the result, and fill in the imaginary part as 0.
+ result.c_real = PyFloat_AsDouble(space, w_obj) # -1 on failure
+ return
+
+ if not PyComplex_Check(space, w_obj):
+ raise OperationError(space.w_TypeError, space.wrap(
+ "__complex__ should return a complex object"))
+
+ assert isinstance(w_obj, W_ComplexObject)
+ result.c_real = w_obj.realval
+ result.c_imag = w_obj.imagval
Modified: pypy/trunk/pypy/module/cpyext/include/Python.h
==============================================================================
--- pypy/trunk/pypy/module/cpyext/include/Python.h (original)
+++ pypy/trunk/pypy/module/cpyext/include/Python.h Sat May 8 14:38:29 2010
@@ -11,6 +11,7 @@
# define Py_DEPRECATED(VERSION_UNUSED) __attribute__((__deprecated__))
# define PyAPI_FUNC(RTYPE) RTYPE
# define PyAPI_DATA(RTYPE) extern RTYPE
+# define Py_LOCAL_INLINE(type) static inline type
#else
# define MS_WIN32 1
# include <crtdefs.h>
@@ -23,6 +24,7 @@
# define PyAPI_FUNC(RTYPE) __declspec(dllimport) RTYPE
# define PyAPI_DATA(RTYPE) extern __declspec(dllimport) RTYPE
# endif
+# define Py_LOCAL_INLINE(type) static __inline type __fastcall
#endif
#define Py_ssize_t long
@@ -101,6 +103,7 @@
#include "boolobject.h"
#include "floatobject.h"
+#include "complexobject.h"
#include "methodobject.h"
#include "funcobject.h"
Added: pypy/trunk/pypy/module/cpyext/include/complexobject.h
==============================================================================
--- (empty file)
+++ pypy/trunk/pypy/module/cpyext/include/complexobject.h Sat May 8 14:38:29 2010
@@ -0,0 +1,27 @@
+/* Complex object interface */
+
+#ifndef Py_COMPLEXOBJECT_H
+#define Py_COMPLEXOBJECT_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct Py_complex_t {
+ double real;
+ double imag;
+} Py_complex;
+
+/* generated function */
+PyAPI_FUNC(void) _PyComplex_AsCComplex(PyObject *, Py_complex *);
+
+_inline static Py_complex PyComplex_AsCComplex(PyObject *obj)
+{
+ Py_complex result;
+ _PyComplex_AsCComplex(obj, &result);
+ return result;
+}
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Py_COMPLEXOBJECT_H */
Modified: pypy/trunk/pypy/module/cpyext/stubs.py
==============================================================================
--- pypy/trunk/pypy/module/cpyext/stubs.py (original)
+++ pypy/trunk/pypy/module/cpyext/stubs.py Sat May 8 14:38:29 2010
@@ -450,15 +450,6 @@
"""Create a new Python complex number object from a C Py_complex value."""
raise NotImplementedError
- at cpython_api([PyObject], Py_complex)
-def PyComplex_AsCComplex(space, op):
- """Return the Py_complex value of the complex number op.
-
- If op is not a Python complex number object but has a __complex__()
- method, this method will first be called to convert op to a Python complex
- number object."""
- raise NotImplementedError
-
@cpython_api([rffi.CCHARP, rffi.CCHARPP, PyObject], rffi.DOUBLE, error=-1.0)
def PyOS_string_to_double(space, s, endptr, overflow_exception):
"""Convert a string s to a double, raising a Python
Modified: pypy/trunk/pypy/module/cpyext/test/test_complexobject.py
==============================================================================
--- pypy/trunk/pypy/module/cpyext/test/test_complexobject.py (original)
+++ pypy/trunk/pypy/module/cpyext/test/test_complexobject.py Sat May 8 14:38:29 2010
@@ -1,3 +1,4 @@
+from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
from pypy.module.cpyext.test.test_api import BaseApiTest
class TestComplexObject(BaseApiTest):
@@ -17,3 +18,16 @@
assert api.PyComplex_RealAsDouble(space.w_None) == -1.0
assert api.PyErr_Occurred()
api.PyErr_Clear()
+
+class AppTestCComplex(AppTestCpythonExtensionBase):
+ def test_AsCComplex(self):
+ module = self.import_extension('foo', [
+ ("as_tuple", "METH_O",
+ """
+ Py_complex c = PyComplex_AsCComplex(args);
+ if (PyErr_Occurred()) return NULL;
+ return Py_BuildValue("dd", c.real, c.imag);
+ """)])
+ assert module.as_tuple(12-34j) == (12, -34)
+ assert module.as_tuple(-3.14) == (-3.14, 0.0)
+ raises(TypeError, module.as_tuple, "12")
More information about the Pypy-commit
mailing list