[pypy-svn] r72433 - in pypy/trunk/pypy/module/cpyext: . include test
xoraxax at codespeak.net
xoraxax at codespeak.net
Sat Mar 20 05:23:00 CET 2010
Author: xoraxax
Date: Sat Mar 20 05:22:58 2010
New Revision: 72433
Added:
pypy/trunk/pypy/module/cpyext/state.py
Modified:
pypy/trunk/pypy/module/cpyext/__init__.py
pypy/trunk/pypy/module/cpyext/api.py
pypy/trunk/pypy/module/cpyext/floatobject.py
pypy/trunk/pypy/module/cpyext/include/Python.h
pypy/trunk/pypy/module/cpyext/test/test_cpyext.py
Log:
After hours of fighting with ll2ctypes (probably should be implemented differently anyway with Addresses - are those hashable?), here is PyObject support for cpyext.
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 05:22:58 2010
@@ -1,13 +1,8 @@
from pypy.interpreter.mixedmodule import MixedModule
from pypy.rlib.objectmodel import we_are_translated
import pypy.module.cpyext.api
+from pypy.module.cpyext.state import State
-class State:
- def __init__(self, space):
- if not we_are_translated():
- self.api_lib = str(api.build_bridge(space))
- else:
- XXX # build an import library when translating pypy.
class Module(MixedModule):
interpleveldefs = {
@@ -30,5 +25,4 @@
import pypy.module.cpyext.floatobject
import pypy.module.cpyext.modsupport
import pypy.module.cpyext.pythonrun
-from pypy.module.cpyext import api
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 05:22:58 2010
@@ -1,3 +1,7 @@
+import py
+import autopath
+import ctypes
+
from pypy.rpython.lltypesystem import rffi, lltype
from pypy.rpython.tool import rffi_platform
from pypy.rpython.lltypesystem import ll2ctypes
@@ -6,8 +10,8 @@
from pypy.translator.tool.cbuild import ExternalCompilationInfo
from pypy.tool.udir import udir
from pypy.translator import platform
+from pypy.module.cpyext.state import State
-import py, autopath
include_dirs = [
py.path.local(autopath.pypydir).join('module', 'cpyext', 'include'),
@@ -29,7 +33,9 @@
def cpython_api(argtypes, restype):
def decorate(func):
- FUNCTIONS[func.func_name] = ApiFunction(argtypes, restype, func)
+ api_function = ApiFunction(argtypes, restype, func)
+ FUNCTIONS[func.func_name] = api_function
+ func.api_func = api_function
return func
return decorate
@@ -43,19 +49,34 @@
FUNCTIONS = {}
TYPES = {}
-PyObject = lltype.Ptr(cpython_struct('struct _object', []))
+# It is important that these PyObjects are allocated in a raw fashion
+# Thus we cannot save a forward pointer to the wrapped object
+# So we need a forward and backward mapping in our State instance
+PyObject = lltype.Ptr(cpython_struct('struct _object', [("refcnt", lltype.Signed)]))
def configure():
for name, TYPE in rffi_platform.configure(CConfig).iteritems():
TYPES[name].become(TYPE)
-def make_ref(w_obj):
- return lltype.nullptr(PyObject.TO) # XXX for the moment
+def make_ref(space, w_obj):
+ state = space.fromcache(State)
+ py_obj = state.py_objects_w2r.get(w_obj)
+ if py_obj is None:
+ py_obj = lltype.malloc(PyObject.TO, None, flavor="raw")
+ ctypes_obj = ll2ctypes.lltype2ctypes(py_obj)
+ ptr = ctypes.cast(ctypes_obj, ctypes.c_void_p).value
+ py_obj = ll2ctypes.ctypes2lltype(PyObject, ctypes_obj)
+ state.py_objects_w2r[w_obj] = py_obj
+ state.py_objects_r2w[ptr] = w_obj
+ return py_obj
def from_ref(space, ref):
+ state = space.fromcache(State)
if not ref:
- return space.w_None # XXX for the moment, should be an exception
- assert False
+ raise RuntimeError("Null pointer dereference!")
+ ptr = ctypes.addressof(ref._obj._storage)
+ obj = state.py_objects_r2w[ptr]
+ return obj
#_____________________________________________________
# Build the bridge DLL, Allow extension DLLs to call
@@ -138,7 +159,16 @@
def make_wrapper(callable):
def wrapper(*args):
- return callable(space, *args)
+ boxed_args = []
+ # XXX use unrolling_iterable here
+ for typ, arg in zip(callable.api_func.argtypes, args):
+ if typ is PyObject:
+ arg = from_ref(space, arg)
+ boxed_args.append(arg)
+ retval = callable(space, *boxed_args)
+ if callable.api_func.restype is PyObject:
+ retval = make_ref(space, retval)
+ return retval
return wrapper
# implement structure initialization code
Modified: pypy/trunk/pypy/module/cpyext/floatobject.py
==============================================================================
--- pypy/trunk/pypy/module/cpyext/floatobject.py (original)
+++ pypy/trunk/pypy/module/cpyext/floatobject.py Sat Mar 20 05:22:58 2010
@@ -3,4 +3,4 @@
@cpython_api([lltype.Float], PyObject)
def PyFloat_FromDouble(space, value):
- return make_ref(space.wrap(value))
+ return space.wrap(value)
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 05:22:58 2010
@@ -2,7 +2,7 @@
#define Py_PYTHON_H
typedef struct _object {
- int __dummy;
+ long refcnt;
} PyObject;
#include <stdio.h>
Added: pypy/trunk/pypy/module/cpyext/state.py
==============================================================================
--- (empty file)
+++ pypy/trunk/pypy/module/cpyext/state.py Sat Mar 20 05:22:58 2010
@@ -0,0 +1,14 @@
+from pypy.rlib.objectmodel import we_are_translated
+from pypy.lib.identity_dict import identity_dict
+
+
+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 05:22:58 2010
@@ -94,4 +94,4 @@
assert 'foo' in sys.modules
assert 'return_pi' in dir(module)
assert module.return_pi is not None
- assert module.return_pi() is None # XXX for the moment
+ assert module.return_pi() == 3.14
More information about the Pypy-commit
mailing list