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

afa at codespeak.net afa at codespeak.net
Fri Mar 19 20:20:23 CET 2010


Author: afa
Date: Fri Mar 19 20:20:21 2010
New Revision: 72423

Added:
   pypy/trunk/pypy/module/cpyext/floatobject.py   (contents, props changed)
   pypy/trunk/pypy/module/cpyext/include/floatobject.h
   pypy/trunk/pypy/module/cpyext/include/methodobject.h
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/include/modsupport.h
   pypy/trunk/pypy/module/cpyext/modsupport.py
   pypy/trunk/pypy/module/cpyext/test/test_cpyext.py
Log:
Start to iterate over the PyMethodDef array,
this needed some support for "configure".

Next step: really expose the function object.


Modified: pypy/trunk/pypy/module/cpyext/__init__.py
==============================================================================
--- pypy/trunk/pypy/module/cpyext/__init__.py	(original)
+++ pypy/trunk/pypy/module/cpyext/__init__.py	Fri Mar 19 20:20:21 2010
@@ -27,7 +27,8 @@
                       space.wrap(state.api_lib))
 
 # import these modules to register api functions by side-effect
+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	Fri Mar 19 20:20:21 2010
@@ -1,10 +1,22 @@
 from pypy.rpython.lltypesystem import rffi, lltype
+from pypy.rpython.tool import rffi_platform
 from pypy.rpython.lltypesystem import ll2ctypes
 from pypy.rpython.annlowlevel import llhelper
 from pypy.translator.c.database import LowLevelDatabase
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
 from pypy.translator import platform
 
+import py, autopath
+
+include_dir = py.path.local(autopath.pypydir).join(
+    'module', 'cpyext', 'include')
+
+class CConfig:
+    _compilation_info_ = ExternalCompilationInfo(
+        include_dirs=[include_dir],
+        includes=['Python.h']
+        )
+
 class ApiFunction:
     def __init__(self, argtypes, restype, callable):
         self.argtypes = argtypes
@@ -18,14 +30,21 @@
         return func
     return decorate
 
-def cpython_struct(name):
-    struct = rffi.CStruct('PyMethodDef')
-    TYPES[name] = struct
-    return struct
+def cpython_struct(name, fields):
+    setattr(CConfig, name, rffi_platform.Struct(name, fields))
+    forward = lltype.ForwardReference()
+    TYPES[name] = forward
+    return forward
 
 FUNCTIONS = {}
 TYPES = {}
 
+PyObject = cpython_struct('PyObject', [])
+
+def configure():
+    for name, TYPE in rffi_platform.configure(CConfig).iteritems():
+        TYPES[name].become(TYPE)
+
 #_____________________________________________________
 # Build the bridge DLL, Allow extension DLLs to call
 # back into Pypy space functions
@@ -42,6 +61,7 @@
         structindex[name] = len(structindex)
     structmembers = '\n'.join(members)
     struct_declaration_code = """\
+    #include <Python.h>
     struct PyPyAPI {
     %(members)s
     } _pypyAPI;
@@ -67,6 +87,7 @@
 
     # Build code and get pointer to the structure
     eci = ExternalCompilationInfo(
+        include_dirs=[include_dir],
         separate_module_sources=[code],
         export_symbols=['pypyAPI'] + list(FUNCTIONS),
         )

Added: pypy/trunk/pypy/module/cpyext/floatobject.py
==============================================================================
--- (empty file)
+++ pypy/trunk/pypy/module/cpyext/floatobject.py	Fri Mar 19 20:20:21 2010
@@ -0,0 +1,6 @@
+from pypy.rpython.lltypesystem import rffi, lltype
+from pypy.module.cpyext.api import cpython_api, PyObject
+
+ at cpython_api([lltype.Float], lltype.Ptr(PyObject))
+def PyFloat_FromDouble(space, 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	Fri Mar 19 20:20:21 2010
@@ -1,7 +1,15 @@
 #ifndef Py_PYTHON_H
 #define Py_PYTHON_H
 
+typedef struct _object {
+    int __dummy;
+} PyObject;
+
 #include <stdio.h>
+
+#include "floatobject.h"
+#include "methodobject.h"
+
 #include "modsupport.h"
 #include "pythonrun.h"
 

Added: pypy/trunk/pypy/module/cpyext/include/floatobject.h
==============================================================================
--- (empty file)
+++ pypy/trunk/pypy/module/cpyext/include/floatobject.h	Fri Mar 19 20:20:21 2010
@@ -0,0 +1,16 @@
+
+/* Float object interface */
+
+#ifndef Py_FLOATOBJECT_H
+#define Py_FLOATOBJECT_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+PyObject* PyFloat_FromDouble(double);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Py_FLOATOBJECT_H */

Added: pypy/trunk/pypy/module/cpyext/include/methodobject.h
==============================================================================
--- (empty file)
+++ pypy/trunk/pypy/module/cpyext/include/methodobject.h	Fri Mar 19 20:20:21 2010
@@ -0,0 +1,36 @@
+
+/* Method object interface */
+
+#ifndef Py_METHODOBJECT_H
+#define Py_METHODOBJECT_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef PyObject *(*PyCFunction)(PyObject *, PyObject *);
+typedef PyObject *(*PyCFunctionWithKeywords)(PyObject *, PyObject *,
+                                             PyObject *);
+typedef PyObject *(*PyNoArgsFunction)(PyObject *);
+
+struct PyMethodDef {
+    const char  *ml_name;   /* The name of the built-in function/method */
+    PyCFunction  ml_meth;   /* The C function that implements it */
+    int          ml_flags;  /* Combination of METH_xxx flags, which mostly
+                               describe the args expected by the C func */
+    const char  *ml_doc;    /* The __doc__ attribute, or NULL */
+};
+typedef struct PyMethodDef PyMethodDef;
+
+/* Flag passed to newmethodobject */
+#define METH_OLDARGS  0x0000
+#define METH_VARARGS  0x0001
+#define METH_KEYWORDS 0x0002
+/* METH_NOARGS and METH_O must not be combined with the flags above. */
+#define METH_NOARGS   0x0004
+#define METH_O        0x0008
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Py_METHODOBJECT_H */

Modified: pypy/trunk/pypy/module/cpyext/include/modsupport.h
==============================================================================
--- pypy/trunk/pypy/module/cpyext/include/modsupport.h	(original)
+++ pypy/trunk/pypy/module/cpyext/include/modsupport.h	Fri Mar 19 20:20:21 2010
@@ -1,2 +1,15 @@
-typedef struct PyMethodDef PyMethodDef;
+
+/* Module support interface */
+
+#ifndef Py_MODSUPPORT_H
+#define Py_MODSUPPORT_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 void Py_InitModule(const char* name, PyMethodDef* methods);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Py_MODSUPPORT_H */

Modified: pypy/trunk/pypy/module/cpyext/modsupport.py
==============================================================================
--- pypy/trunk/pypy/module/cpyext/modsupport.py	(original)
+++ pypy/trunk/pypy/module/cpyext/modsupport.py	Fri Mar 19 20:20:21 2010
@@ -2,7 +2,10 @@
 from pypy.module.cpyext.api import cpython_api, cpython_struct
 from pypy.interpreter.module import Module
 
-PyMethodDef = cpython_struct('PyMethodDef')
+PyMethodDef = cpython_struct(
+    'PyMethodDef',
+    [('ml_name', rffi.CCHARP),
+     ])
 
 def PyImport_AddModule(space, name):
     w_name = space.wrap(name)
@@ -15,5 +18,15 @@
 @cpython_api([rffi.CCHARP, lltype.Ptr(PyMethodDef)], lltype.Void)
 def Py_InitModule(space, name, methods):
     name = rffi.charp2str(name)
-    PyImport_AddModule(space, name)
-    assert not methods # For the moment
+    w_mod = PyImport_AddModule(space, name)
+    methods = rffi.cast(rffi.CArrayPtr(PyMethodDef), methods)
+    if methods:
+        i = 0
+        while True:
+            method = methods[i]
+            if not method.c_ml_name: break
+            methodname = rffi.charp2str(method.c_ml_name)
+            space.setattr(w_mod,
+                          space.wrap(methodname),
+                          space.w_None) # XXX for the moment
+            i = i + 1

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	Fri Mar 19 20:20:21 2010
@@ -46,6 +46,9 @@
         import ctypes
         initfunc = ctypes.CDLL(mod)['init%s' % (name,)]
         initfunc()
+        return self.space.getitem(
+            self.space.sys.get('modules'),
+            self.space.wrap(name))
 
     def setup_method(self, func):
         self.w_import_module = self.space.wrap(self.import_module)
@@ -65,3 +68,24 @@
         """
         self.import_module(name='foo', init=init)
         assert 'foo' in sys.modules
+
+    def test_export_function(self):
+        import sys
+        init = """
+        if (Py_IsInitialized())
+            Py_InitModule("foo", methods);
+        """
+        body = """
+        PyObject* foo_pi(PyObject* self, PyObject *args)
+        {
+            return PyFloat_FromDouble(3.14);
+        }
+        static PyMethodDef methods[] = {
+            { "return_pi", foo_pi, METH_NOARGS },
+            { NULL }
+        };
+        """
+        module = self.import_module(name='foo', init=init, body=body)
+        assert 'foo' in sys.modules
+        assert 'return_pi' in dir(module)
+        assert module.return_pi is None # XXX for the moment



More information about the Pypy-commit mailing list