[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