[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