[pypy-svn] r72434 - in pypy/trunk/pypy/module/cpyext: . include test

xoraxax at codespeak.net xoraxax at codespeak.net
Sat Mar 20 06:17:20 CET 2010


Author: xoraxax
Date: Sat Mar 20 06:17:18 2010
New Revision: 72434

Added:
   pypy/trunk/pypy/module/cpyext/macros.py
Modified:
   pypy/trunk/pypy/module/cpyext/__init__.py
   pypy/trunk/pypy/module/cpyext/api.py
   pypy/trunk/pypy/module/cpyext/include/Python.h
   pypy/trunk/pypy/module/cpyext/state.py
   pypy/trunk/pypy/module/cpyext/test/test_cpyext.py
Log:
Added new test and Py_None support.

Modified: pypy/trunk/pypy/module/cpyext/__init__.py
==============================================================================
--- pypy/trunk/pypy/module/cpyext/__init__.py	(original)
+++ pypy/trunk/pypy/module/cpyext/__init__.py	Sat Mar 20 06:17:18 2010
@@ -14,6 +14,10 @@
     def setup_after_space_initialization(self):
         """NOT_RPYTHON"""
         state = self.space.fromcache(State)
+        if not we_are_translated():
+            state.api_lib = str(pypy.module.cpyext.api.build_bridge(space))
+        else:
+            XXX # build an import library when translating pypy.
 
     def startup(self, space):
         state = space.fromcache(State)
@@ -25,4 +29,5 @@
 import pypy.module.cpyext.floatobject
 import pypy.module.cpyext.modsupport
 import pypy.module.cpyext.pythonrun
+import pypy.module.cpyext.macros
 api.configure()

Modified: pypy/trunk/pypy/module/cpyext/api.py
==============================================================================
--- pypy/trunk/pypy/module/cpyext/api.py	(original)
+++ pypy/trunk/pypy/module/cpyext/api.py	Sat Mar 20 06:17:18 2010
@@ -63,6 +63,7 @@
     py_obj = state.py_objects_w2r.get(w_obj)
     if py_obj is None:
         py_obj = lltype.malloc(PyObject.TO, None, flavor="raw")
+        py_obj.c_refcnt = 1
         ctypes_obj = ll2ctypes.lltype2ctypes(py_obj)
         ptr = ctypes.cast(ctypes_obj, ctypes.c_void_p).value
         py_obj = ll2ctypes.ctypes2lltype(PyObject, ctypes_obj)
@@ -75,7 +76,10 @@
     if not ref:
         raise RuntimeError("Null pointer dereference!")
     ptr = ctypes.addressof(ref._obj._storage)
-    obj = state.py_objects_r2w[ptr]
+    try:
+        obj = state.py_objects_r2w[ptr]
+    except KeyError:
+        raise RuntimeError("Got invalid reference to a PyObject")
     return obj
 
 #_____________________________________________________
@@ -136,8 +140,12 @@
         body = "{ return _pypyAPI.%s(%s); }" % (name, callargs)
         functions.append('%s\n%s\n' % (header, body))
 
+    global_objects = """
+    PyObject *PyPy_None = NULL;
+    """
     code = (prologue +
             struct_declaration_code +
+            global_objects +
             '\n' +
             '\n'.join(functions))
 
@@ -156,6 +164,7 @@
     import ctypes
     bridge = ctypes.CDLL(str(modulename))
     pypyAPI = ctypes.POINTER(ctypes.c_void_p).in_dll(bridge, 'pypyAPI')
+    Py_NONE = ctypes.c_void_p.in_dll(bridge, 'PyPy_None')
 
     def make_wrapper(callable):
         def wrapper(*args):
@@ -176,6 +185,8 @@
         pypyAPI[structindex[name]] = ctypes.cast(
             ll2ctypes.lltype2ctypes(llhelper(func.functype, make_wrapper(func.callable))),
             ctypes.c_void_p)
+    Py_NONE.value = ctypes.cast(ll2ctypes.lltype2ctypes(make_ref(space, space.w_None)),
+            ctypes.c_void_p).value
 
     return modulename.new(ext='')
 

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 Mar 20 06:17:18 2010
@@ -4,6 +4,8 @@
 typedef struct _object {
     long refcnt;
 } PyObject;
+extern PyObject *PyPy_None;
+#define Py_None PyPy_None
 
 #include <stdio.h>
 

Added: pypy/trunk/pypy/module/cpyext/macros.py
==============================================================================
--- (empty file)
+++ pypy/trunk/pypy/module/cpyext/macros.py	Sat Mar 20 06:17:18 2010
@@ -0,0 +1,20 @@
+import ctypes
+
+from pypy.rpython.lltypesystem import rffi, lltype
+from pypy.module.cpyext.api import cpython_api, PyObject, make_ref
+from pypy.module.cpyext.state import State
+
+# XXX Optimize these functions and put them into macro definitions
+ at cpython_api([PyObject], lltype.Void)
+def Py_DECREF(space, w_obj):
+    state = space.fromcache(State)
+    obj = state.py_objects_w2r.get(w_obj)
+    obj.c_refcnt -= 1
+    return
+
+ at cpython_api([PyObject], lltype.Void)
+def Py_INCREF(space, w_obj):
+    state = space.fromcache(State)
+    obj = state.py_objects_w2r.get(w_obj)
+    obj.c_refcnt += 1
+    return

Modified: pypy/trunk/pypy/module/cpyext/state.py
==============================================================================
--- pypy/trunk/pypy/module/cpyext/state.py	(original)
+++ pypy/trunk/pypy/module/cpyext/state.py	Sat Mar 20 06:17:18 2010
@@ -4,11 +4,6 @@
 
 class State:
     def __init__(self, space):
-        from pypy.module.cpyext import api
         self.py_objects_w2r = identity_dict() # w_obj -> raw PyObject
         self.py_objects_r2w = {} # addr of raw PyObject -> w_obj
-        if not we_are_translated():
-            self.api_lib = str(api.build_bridge(space))
-        else:
-            XXX # build an import library when translating pypy.
 

Modified: pypy/trunk/pypy/module/cpyext/test/test_cpyext.py
==============================================================================
--- pypy/trunk/pypy/module/cpyext/test/test_cpyext.py	(original)
+++ pypy/trunk/pypy/module/cpyext/test/test_cpyext.py	Sat Mar 20 06:17:18 2010
@@ -95,3 +95,47 @@
         assert 'return_pi' in dir(module)
         assert module.return_pi is not None
         assert module.return_pi() == 3.14
+
+    def test_export_function2(self):
+        import sys
+        init = """
+        if (Py_IsInitialized())
+            Py_InitModule("foo", methods);
+        """
+        body = """
+        static PyObject* my_objects[1];
+        static PyObject* foo_cached_pi(PyObject* self, PyObject *args)
+        {
+            if (my_objects[0] == NULL) {
+                my_objects[0] = PyFloat_FromDouble(3.14);
+                Py_INCREF(my_objects[0]);
+            }
+            return my_objects[0];
+        }
+        static PyObject* foo_drop_pi(PyObject* self, PyObject *args)
+        {
+            if (my_objects[0] != NULL) {
+                Py_DECREF(my_objects[0]);
+                my_objects[0] = NULL;
+            }
+            Py_INCREF(Py_None);
+            return Py_None;
+        }
+        static PyObject* foo_retinvalid(PyObject* self, PyObject *args)
+        {
+            return (PyObject*)0xAFFEBABE;
+        }
+        static PyMethodDef methods[] = {
+            { "return_pi", foo_cached_pi, METH_NOARGS },
+            { "drop_pi",   foo_drop_pi, METH_NOARGS },
+            { "return_invalid_pointer", foo_retinvalid, METH_NOARGS },
+            { NULL }
+        };
+        """
+        module = self.import_module(name='foo', init=init, body=body)
+        raises(RuntimeError, module.return_invalid_pointer)
+        assert module.return_pi() == 3.14
+        module.drop_pi()
+        module.drop_pi()
+        assert module.return_pi() == 3.14
+        assert module.return_pi() == 3.14



More information about the Pypy-commit mailing list