[pypy-commit] pypy pypy-in-a-box: try to add some minimal embedding API

fijal noreply at buildbot.pypy.org
Wed Jul 18 12:06:32 CEST 2012


Author: Maciej Fijalkowski <fijall at gmail.com>
Branch: pypy-in-a-box
Changeset: r56124:d5cbfd2fe88a
Date: 2012-07-18 12:06 +0200
http://bitbucket.org/pypy/pypy/changeset/d5cbfd2fe88a/

Log:	try to add some minimal embedding API

diff --git a/pypy/config/pypyoption.py b/pypy/config/pypyoption.py
--- a/pypy/config/pypyoption.py
+++ b/pypy/config/pypyoption.py
@@ -346,6 +346,10 @@
                    default=False,
                    # weakrefs needed, because of get_subclasses()
                    requires=[("translation.rweakref", True)]),
+        BoolOption("withembeddingapi",
+                   "enable embedding API",
+                   default=True),
+        
      ]),
 ])
 
diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py
--- a/pypy/module/cpyext/api.py
+++ b/pypy/module/cpyext/api.py
@@ -13,7 +13,6 @@
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
 from pypy.translator.gensupp import NameManager
 from pypy.tool.udir import udir
-from pypy.translator import platform
 from pypy.module.cpyext.state import State
 from pypy.interpreter.error import OperationError, operationerrfmt
 from pypy.interpreter.baseobjspace import W_Root
diff --git a/pypy/objspace/std/embedding.py b/pypy/objspace/std/embedding.py
new file mode 100644
--- /dev/null
+++ b/pypy/objspace/std/embedding.py
@@ -0,0 +1,69 @@
+
+from pypy.rpython.lltypesystem import rffi, lltype
+from pypy.rpython.lltypesystem.lloperation import llop
+from pypy.interpreter.pyopcode import prepare_exec
+from pypy.interpreter.pycode import PyCode
+from pypy.interpreter.error import OperationError
+from pypy.interpreter import eval
+
+FUNCTIONS = {}
+
+class Cache(object):
+    def __init__(self, space):
+        self.w_globals = space.newdict(module=True)
+        space.call_method(self.w_globals, 'setdefault',
+                          space.wrap('__builtins__'),
+                          space.wrap(space.builtin))
+
+def export_function(argtypes, restype):
+    """ Export the function, sans the space argument
+    """
+    def wrapper(func):
+        def newfunc(*args):
+            llop.gc_stack_bottom(lltype.Void)   # marker for trackgcroot.py
+            try:
+                rffi.stackcounter.stacks_counter += 1
+                res = func(*args)
+            except Exception, e:
+                print "Fatal error embedding API, cannot proceed"
+                print str(e)
+            rffi.stackcounter.stacks_counter -= 1
+            return res
+        FUNCTIONS[func.func_name] = (func, argtypes, restype)
+        return func
+    return wrapper
+
+ at export_function([rffi.CArrayPtr(rffi.CCHARP), rffi.CCHARP], lltype.Void)
+def prepare_function(space, ll_names, ll_s):
+    s = rffi.charp2str(ll_s)
+    w_globals = space.fromcache(Cache).w_globals
+    ec = space.getexecutioncontext()
+    code_w = ec.compiler.compile(s, '<input>', 'exec', 0)
+    code_w.exec_code(space, w_globals, w_globals)
+
+ at export_function([rffi.CCHARP, lltype.Signed, rffi.CArrayPtr(rffi.VOIDP)],
+                 rffi.VOIDP)
+def call_function(space, ll_name, numargs, ll_args):
+    name = rffi.charp2str(ll_name)
+    w_globals = space.fromcache(Cache).w_globals
+    try:
+        w_item = space.getitem(w_globals, space.wrap(name))
+    except OperationError:
+        print "Cannot find name %s" % name
+        return lltype.nullptr(rffi.VOIDP.TO)
+    args = [rffi.cast(lltype.Signed, ll_args[i]) for i in range(numargs)]
+    try:
+        w_res = space.call(w_item, space.newtuple([space.wrap(i) for i in args]))
+    except OperationError:
+        print "Error calling the function"
+        return lltype.nullptr(rffi.VOIDP)
+    try:
+        res = space.int_w(w_res)
+    except OperationError:
+        print "Function did not return int"
+        return lltype.nullptr(rffi.VOIDP)
+    return res
+
+def initialize(space):
+    for name, func in FUNCTIONS.iteritems():
+        pass
diff --git a/pypy/objspace/std/objspace.py b/pypy/objspace/std/objspace.py
--- a/pypy/objspace/std/objspace.py
+++ b/pypy/objspace/std/objspace.py
@@ -84,6 +84,10 @@
             transparent.setup(self)
 
         self.setup_isinstance_cache()
+        # setup embedding API if enabled
+        if self.config.objspace.std.withembeddingapi:
+            from pypy.objspace.std import embedding
+            embedding.initialize(self)
 
     def get_builtin_types(self):
         return self.builtin_types
diff --git a/pypy/objspace/std/test/test_embedding.py b/pypy/objspace/std/test/test_embedding.py
new file mode 100644
--- /dev/null
+++ b/pypy/objspace/std/test/test_embedding.py
@@ -0,0 +1,32 @@
+
+from pypy.objspace.std.embedding import prepare_function, Cache, call_function
+from pypy.rpython.lltypesystem import rffi, lltype
+from pypy.interpreter.function import Function
+
+class TestEmbedding(object):
+    def test_prepare_function(self):
+        space = self.space
+        TP = rffi.CArray(rffi.CCHARP)
+        ll_arr = lltype.malloc(TP, 2, flavor='raw')
+        ll_arr[0] = rffi.str2charp("f")
+        ll_arr[1] = rffi.str2charp("g")
+        ll_source = rffi.str2charp('''
+def f(a, b):
+    return a + b
+def g(a):
+    return a - 2
+''')
+        prepare_function(space, ll_arr, ll_source)
+        w_f = space.getitem(space.fromcache(Cache).w_globals, space.wrap('f'))
+        assert isinstance(w_f, Function)
+        w_res = space.call_function(w_f, space.wrap(1), space.wrap(2))
+        assert space.int_w(w_res) == 3
+        ll_args = lltype.malloc(rffi.CArray(lltype.Signed), 2, flavor='raw')
+        ll_args[0] = 1
+        ll_args[1] = 2
+        call_function(space, ll_arr[0], 2, ll_args)
+        lltype.free(ll_arr[0], flavor='raw')
+        lltype.free(ll_arr[1], flavor='raw')
+        lltype.free(ll_arr, flavor='raw')
+        lltype.free(ll_source, flavor='raw')
+        lltype.free(ll_args, flavor='raw')


More information about the pypy-commit mailing list