Commits

Maciej Fijalkowski  committed 8362150

shuffle stuff around a lot. also a test and a fix for exported symbols

  • Participants
  • Parent commits cd7048f

Comments (0)

Files changed (5)

File pypy/module/cpyext/api.py

         from pypy.module.cpyext.pyobject import Reference
         # we hope that malloc removal removes the newtuple() that is
         # inserted exactly here by the varargs specializer
-        rffi.stackcounter.stacks_counter += 1
-        llop.gc_stack_bottom(lltype.Void)   # marker for trackgcroot.py
         retval = fatal_value
         boxed_args = ()
         try:
             else:
                 print str(e)
                 pypy_debug_catch_fatal_exception()
-        rffi.stackcounter.stacks_counter -= 1
         return retval
     callable._always_inline_ = 'try'
     wrapper.__name__ = "wrapper for %r" % (callable, )

File rpython/rlib/entrypoint.py

 secondary_entrypoints = {}
 
+from rpython.rtyper.lltypesystem import lltype, rffi
+from rpython.rtyper.lltypesystem.lloperation import llop
+from rpython.rlib.objectmodel import we_are_translated
+
+pypy_debug_catch_fatal_exception = rffi.llexternal('pypy_debug_catch_fatal_exception', [], lltype.Void)
 
 def entrypoint(key, argtypes, c_name=None, relax=False):
     """ Note: entrypoint should call llop.gc_stack_bottom on it's own.
     from rpython.translator.tool.cbuild import ExternalCompilationInfo
 
     def deco(func):
-        secondary_entrypoints.setdefault(key, []).append((func, argtypes))
+        def wrapper(*args):
+            # the tuple has to be killed, but it's fine because this is
+            # called from C
+            rffi.stackcounter.stacks_counter += 1
+            llop.gc_stack_bottom(lltype.Void)   # marker for trackgcroot.py
+            # this should not raise
+            try:
+                res = func(*args)
+            except Exception, e:
+                if not we_are_translated():
+                    import traceback
+                    traceback.print_exc()
+                else:
+                    print str(e)
+                    pypy_debug_catch_fatal_exception()
+                    llop.debug_fatalerror(lltype.Void)
+                    assert 0 # dead code
+            rffi.stackcounter.stacks_counter -= 1
+            return res
+
+        secondary_entrypoints.setdefault(key, []).append((wrapper, argtypes))
+        wrapper.func_name = func.func_name
         if c_name is not None:
-            func.c_name = c_name
+            wrapper.c_name = c_name
         if relax:
-            func.relax_sig_check = True
-        func._compilation_info = ExternalCompilationInfo(
+            wrapper.relax_sig_check = True
+        wrapper._compilation_info = ExternalCompilationInfo(
             export_symbols=[c_name or func.func_name])
-        return func
+        return wrapper
     return deco
 
 # the point of dance below is so the call to rpython_startup_code actually
 # This thing is imported by any target which has any API, so it'll get
 # registered
 
-from rpython.rtyper.lltypesystem import lltype, rffi
-
 RPython_StartupCode = rffi.llexternal('RPython_StartupCode', [], lltype.Void)
 
 @entrypoint('main', [], c_name='rpython_startup_code')

File rpython/rtyper/lltypesystem/lltype.py

     def _names_without_voids(self):
         names_without_voids = [name for name in self._names if self._flds[name] is not Void]
         return names_without_voids
-    
+
     def _str_fields_without_voids(self):
         return ', '.join(['%s: %s' % (name, self._flds[name])
                           for name in self._names_without_voids(False)])
     _gckind = 'raw'
     __name__ = 'array'
     _anonym_struct = False
-    
+
     def __init__(self, *fields, **kwds):
         if len(fields) == 1 and isinstance(fields[0], LowLevelType):
             self.OF = fields[0]
 
     def normalized(self):
         return build_number(None, normalizedinttype(self._type))
-        
+
 
 _numbertypes = {int: Number("Signed", int, intmask)}
 _numbertypes[r_int] = _numbertypes[int]
                          adtmeths=TO._adtmeths)
         else:
             R = GcStruct("Interior", ('ptr', self), ('index', Signed),
-                         hints={'interior_ptr_type':True})            
+                         hints={'interior_ptr_type':True})
         return R
 
 class InteriorPtr(LowLevelType):
             return dwn
         OUTSIDE = getattr(OUTSIDE, first)
     return -1
- 
+
 def castable(PTRTYPE, CURTYPE):
     if CURTYPE.TO._gckind != PTRTYPE.TO._gckind:
         raise TypeError("cast_pointer() cannot change the gc status: %s to %s"
 
     # _setobj, _getobj and _obj0 are really _internal_ implementations details of _ptr,
     # use _obj if necessary instead !
-    def _setobj(self, pointing_to, solid=False):        
+    def _setobj(self, pointing_to, solid=False):
         if pointing_to is None:
             obj0 = None
         elif (solid or self._T._gckind != 'raw' or
             obj0 = weakref.ref(pointing_to)
         self._set_solid(solid)
         self._set_obj0(obj0)
-        
+
     def _getobj(self, check=True):
         obj = self._obj0
         if obj is not None:
             return result
 
 class _ptr(_abstract_ptr):
-    __slots__ = ('_TYPE', 
+    __slots__ = ('_TYPE',
                  '_weak', '_solid',
                  '_obj0', '__weakref__')
 
             assert T._gckind == 'raw'
             val = _interior_ptr(T, self._parent, self._offsets + [offset])
         return val
-    
-    
-        
+
+
+
 assert not '__dict__' in dir(_interior_ptr)
 
 class _container(object):
             __slots__ = flds
         cache[tag] = _struct1
         return _struct1
- 
+
 #for pickling support:
 def _get_empty_instance_of_struct_variety(flds):
     cls = _struct_variety(flds)
         return r
 
     # for FixedSizeArray kind of structs:
-    
+
     def getlength(self):
         assert isinstance(self._TYPE, FixedSizeArray)
         return self._TYPE.length
         attrs.setdefault('_name', '?')
         attrs.setdefault('_callable', None)
         self.__dict__.update(attrs)
+        if '_callable' in attrs:
+            self.__dict__['compilation_info'] = getattr(attrs['_callable'], '_compilation_info', None)
 
     def __repr__(self):
         return '<%s>' % (self,)
         # if we are an opaque containing a normal Struct/GcStruct,
         # unwrap it
         if hasattr(self, 'container'):
-            # an integer, cast to a ptr, cast to an opaque    
+            # an integer, cast to a ptr, cast to an opaque
             if type(self.container) is int:
                 return self.container
             if getattr(self.container, '_carry_around_for_tests', False):
     if not isinstance(GCSTRUCT, RttiStruct):
         raise TypeError, "expected a RttiStruct: %s" % GCSTRUCT
     if GCSTRUCT._runtime_type_info is None:
-        raise ValueError, ("no attached runtime type info for GcStruct %s" % 
+        raise ValueError, ("no attached runtime type info for GcStruct %s" %
                            GCSTRUCT._name)
     return _ptr(Ptr(RuntimeTypeInfo), GCSTRUCT._runtime_type_info)
 

File rpython/translator/c/node.py

 
 class ContainerNode(Node):
     if USESLOTS:      # keep the number of slots down!
-        __slots__ = """db obj 
+        __slots__ = """db obj
                        typename implementationtypename
                         name
                         _funccodegen_owner

File rpython/translator/c/test/test_standalone.py

 import py
 import sys, os, re
 
+from rpython.config.translationoption import get_combined_translation_config
 from rpython.rlib.objectmodel import keepalive_until_here
 from rpython.rlib.rarithmetic import r_longlong
 from rpython.rlib.debug import ll_assert, have_debug_prints, debug_flush
 from rpython.rlib.debug import debug_print, debug_start, debug_stop, debug_offset
+from rpython.rlib.entrypoint import entrypoint, secondary_entrypoints
+from rpython.rtyper.lltypesystem import lltype
 from rpython.translator.translator import TranslationContext
 from rpython.translator.backendopt import all
 from rpython.translator.c.genc import CStandaloneBuilder, ExternalCompilationInfo
     config = None
 
     def compile(self, entry_point, debug=True, shared=False,
-                stackcheck=False):
+                stackcheck=False, entrypoints=None):
         t = TranslationContext(self.config)
-        t.buildannotator().build_types(entry_point, [s_list_of_strings])
+        ann = t.buildannotator()
+        ann.build_types(entry_point, [s_list_of_strings])
+        if secondary_entrypoints is not None:
+            anns = {}
+            for func, annotation in secondary_entrypoints['test']:
+                anns[func] = annotation
+            for item in entrypoints:
+                ann.build_types(item, anns[item])
         t.buildrtyper().specialize()
 
         if stackcheck:
 
         t.config.translation.shared = shared
 
-        cbuilder = CStandaloneBuilder(t, entry_point, t.config)
+        cbuilder = CStandaloneBuilder(t, entry_point, t.config,
+               secondary_entrypoints=[(i, None) for i in entrypoints])
         if debug:
             cbuilder.generate_source(defines=cbuilder.DEBUG_DEFINES)
         else:
             llop.instrument_count(lltype.Void, 'test', 1)
             llop.instrument_count(lltype.Void, 'test', 1)
             llop.instrument_count(lltype.Void, 'test', 2)
-            llop.instrument_count(lltype.Void, 'test', 1)        
+            llop.instrument_count(lltype.Void, 'test', 1)
             return 0
         t = TranslationContext(self.config)
         t.config.translation.instrument = True
 
     def test_debug_print_start_stop(self):
         from rpython.rtyper.lltypesystem import rffi
-        
+
         def entry_point(argv):
             x = "got:"
             debug_start  ("mycat")
         assert 'bok' in data
         #
         # finally, check compiling with logging disabled
-        from rpython.config.translationoption import get_combined_translation_config
         config = get_combined_translation_config(translating=True)
         config.translation.log = False
         self.config = config
         py.test.skip("TestMaemo: tests skipped for now")
         from rpython.translator.platform.maemo import check_scratchbox
         check_scratchbox()
-        from rpython.config.translationoption import get_combined_translation_config
         config = get_combined_translation_config(translating=True)
         config.translation.platform = 'maemo'
         cls.config = config
                 and result.count('c') == result.count('p') == 5
                 and result.count('a') == 1
                 and result.count('d') == 6)
+
+
+class TestShared(StandaloneTests):
+
+    def test_entrypoint(self):
+        import ctypes
+
+        config = get_combined_translation_config(translating=True)
+        self.config = config
+
+        @entrypoint('test', [lltype.Signed], relax=True, c_name='foo')
+        def f(a):
+            return a + 3
+
+        def entry_point(argv):
+            return 0
+
+        t, cbuilder = self.compile(entry_point, shared=True,
+                                   entrypoints=[f])
+        libname = cbuilder.executable_name.join('..', 'lib' +
+                                                cbuilder.modulename + '.so')
+        lib = ctypes.CDLL(str(libname))
+        assert lib.foo(13) == 16