PageRenderTime 129ms CodeModel.GetById 39ms RepoModel.GetById 1ms app.codeStats 0ms

/pypy/module/cpyext/api.py

https://bitbucket.org/kkris/pypy
Python | 1177 lines | 1110 code | 47 blank | 20 comment | 67 complexity | 6757e26eca3607900d4d8b49db30d769 MD5 | raw file
  1. import ctypes
  2. import sys, os
  3. import atexit
  4. import py
  5. from pypy.conftest import pypydir
  6. from rpython.rtyper.lltypesystem import rffi, lltype
  7. from rpython.rtyper.tool import rffi_platform
  8. from rpython.rtyper.lltypesystem import ll2ctypes
  9. from rpython.rtyper.annlowlevel import llhelper
  10. from rpython.rlib.objectmodel import we_are_translated
  11. from rpython.conftest import cdir
  12. from rpython.translator.tool.cbuild import ExternalCompilationInfo
  13. from rpython.translator.gensupp import NameManager
  14. from rpython.tool.udir import udir
  15. from rpython.translator import platform
  16. from pypy.module.cpyext.state import State
  17. from pypy.interpreter.error import OperationError, operationerrfmt
  18. from pypy.interpreter.baseobjspace import W_Root
  19. from pypy.interpreter.gateway import unwrap_spec
  20. from pypy.interpreter.nestedscope import Cell
  21. from pypy.interpreter.module import Module
  22. from pypy.interpreter.function import StaticMethod
  23. from pypy.objspace.std.sliceobject import W_SliceObject
  24. from pypy.module.__builtin__.descriptor import W_Property
  25. from pypy.module.__builtin__.interp_classobj import W_ClassObject
  26. from pypy.module.__builtin__.interp_memoryview import W_MemoryView
  27. from rpython.rlib.entrypoint import entrypoint
  28. from rpython.rlib.rposix import is_valid_fd, validate_fd
  29. from rpython.rlib.unroll import unrolling_iterable
  30. from rpython.rlib.objectmodel import specialize
  31. from rpython.rlib.exports import export_struct
  32. from pypy.module import exceptions
  33. from pypy.module.exceptions import interp_exceptions
  34. # CPython 2.4 compatibility
  35. from py.builtin import BaseException
  36. from rpython.tool.sourcetools import func_with_new_name
  37. from rpython.rtyper.lltypesystem.lloperation import llop
  38. DEBUG_WRAPPER = True
  39. # update these for other platforms
  40. Py_ssize_t = lltype.Typedef(rffi.SSIZE_T, 'Py_ssize_t')
  41. Py_ssize_tP = rffi.CArrayPtr(Py_ssize_t)
  42. size_t = rffi.ULONG
  43. ADDR = lltype.Signed
  44. pypydir = py.path.local(pypydir)
  45. include_dir = pypydir / 'module' / 'cpyext' / 'include'
  46. source_dir = pypydir / 'module' / 'cpyext' / 'src'
  47. translator_c_dir = py.path.local(cdir)
  48. include_dirs = [
  49. include_dir,
  50. translator_c_dir,
  51. udir,
  52. ]
  53. class CConfig:
  54. _compilation_info_ = ExternalCompilationInfo(
  55. include_dirs=include_dirs,
  56. includes=['Python.h', 'stdarg.h'],
  57. compile_extra=['-DPy_BUILD_CORE'],
  58. )
  59. class CConfig2:
  60. _compilation_info_ = CConfig._compilation_info_
  61. class CConfig_constants:
  62. _compilation_info_ = CConfig._compilation_info_
  63. VA_LIST_P = rffi.VOIDP # rffi.COpaquePtr('va_list')
  64. CONST_STRING = lltype.Ptr(lltype.Array(lltype.Char,
  65. hints={'nolength': True}),
  66. use_cache=False)
  67. CONST_WSTRING = lltype.Ptr(lltype.Array(lltype.UniChar,
  68. hints={'nolength': True}),
  69. use_cache=False)
  70. assert CONST_STRING is not rffi.CCHARP
  71. assert CONST_STRING == rffi.CCHARP
  72. assert CONST_WSTRING is not rffi.CWCHARP
  73. assert CONST_WSTRING == rffi.CWCHARP
  74. # FILE* interface
  75. FILEP = rffi.COpaquePtr('FILE')
  76. if sys.platform == 'win32':
  77. fileno = rffi.llexternal('_fileno', [FILEP], rffi.INT)
  78. else:
  79. fileno = rffi.llexternal('fileno', [FILEP], rffi.INT)
  80. fopen = rffi.llexternal('fopen', [CONST_STRING, CONST_STRING], FILEP)
  81. _fclose = rffi.llexternal('fclose', [FILEP], rffi.INT)
  82. def fclose(fp):
  83. if not is_valid_fd(fileno(fp)):
  84. return -1
  85. return _fclose(fp)
  86. _fwrite = rffi.llexternal('fwrite',
  87. [rffi.VOIDP, rffi.SIZE_T, rffi.SIZE_T, FILEP],
  88. rffi.SIZE_T)
  89. def fwrite(buf, sz, n, fp):
  90. validate_fd(fileno(fp))
  91. return _fwrite(buf, sz, n, fp)
  92. _fread = rffi.llexternal('fread',
  93. [rffi.VOIDP, rffi.SIZE_T, rffi.SIZE_T, FILEP],
  94. rffi.SIZE_T)
  95. def fread(buf, sz, n, fp):
  96. validate_fd(fileno(fp))
  97. return _fread(buf, sz, n, fp)
  98. _feof = rffi.llexternal('feof', [FILEP], rffi.INT)
  99. def feof(fp):
  100. validate_fd(fileno(fp))
  101. return _feof(fp)
  102. constant_names = """
  103. Py_TPFLAGS_READY Py_TPFLAGS_READYING Py_TPFLAGS_HAVE_GETCHARBUFFER
  104. METH_COEXIST METH_STATIC METH_CLASS
  105. METH_NOARGS METH_VARARGS METH_KEYWORDS METH_O
  106. Py_TPFLAGS_HEAPTYPE Py_TPFLAGS_HAVE_CLASS
  107. Py_LT Py_LE Py_EQ Py_NE Py_GT Py_GE
  108. """.split()
  109. for name in constant_names:
  110. setattr(CConfig_constants, name, rffi_platform.ConstantInteger(name))
  111. udir.join('pypy_decl.h').write("/* Will be filled later */\n")
  112. udir.join('pypy_macros.h').write("/* Will be filled later */\n")
  113. globals().update(rffi_platform.configure(CConfig_constants))
  114. def copy_header_files(dstdir):
  115. assert dstdir.check(dir=True)
  116. headers = include_dir.listdir('*.h') + include_dir.listdir('*.inl')
  117. for name in ("pypy_decl.h", "pypy_macros.h"):
  118. headers.append(udir.join(name))
  119. for header in headers:
  120. target = dstdir.join(header.basename)
  121. try:
  122. header.copy(dstdir)
  123. except py.error.EACCES:
  124. target.remove() # maybe it was a read-only file
  125. header.copy(dstdir)
  126. target.chmod(0444) # make the file read-only, to make sure that nobody
  127. # edits it by mistake
  128. class NotSpecified(object):
  129. pass
  130. _NOT_SPECIFIED = NotSpecified()
  131. class CannotFail(object):
  132. pass
  133. CANNOT_FAIL = CannotFail()
  134. # The same function can be called in three different contexts:
  135. # (1) from C code
  136. # (2) in the test suite, though the "api" object
  137. # (3) from RPython code, for example in the implementation of another function.
  138. #
  139. # In contexts (2) and (3), a function declaring a PyObject argument type will
  140. # receive a wrapped pypy object if the parameter name starts with 'w_', a
  141. # reference (= rffi pointer) otherwise; conversion is automatic. Context (2)
  142. # only allows calls with a wrapped object.
  143. #
  144. # Functions with a PyObject return type should return a wrapped object.
  145. #
  146. # Functions may raise exceptions. In context (3), the exception flows normally
  147. # through the calling function. In context (1) and (2), the exception is
  148. # caught; if it is an OperationError, it is stored in the thread state; other
  149. # exceptions generate a OperationError(w_SystemError); and the funtion returns
  150. # the error value specifed in the API.
  151. #
  152. cpyext_namespace = NameManager('cpyext_')
  153. class ApiFunction:
  154. def __init__(self, argtypes, restype, callable, error=_NOT_SPECIFIED,
  155. c_name=None):
  156. self.argtypes = argtypes
  157. self.restype = restype
  158. self.functype = lltype.Ptr(lltype.FuncType(argtypes, restype))
  159. self.callable = callable
  160. if error is not _NOT_SPECIFIED:
  161. self.error_value = error
  162. self.c_name = c_name
  163. # extract the signature from the (CPython-level) code object
  164. from pypy.interpreter import pycode
  165. argnames, varargname, kwargname = pycode.cpython_code_signature(callable.func_code)
  166. assert argnames[0] == 'space'
  167. self.argnames = argnames[1:]
  168. assert len(self.argnames) == len(self.argtypes)
  169. def _freeze_(self):
  170. return True
  171. def get_llhelper(self, space):
  172. llh = getattr(self, '_llhelper', None)
  173. if llh is None:
  174. llh = llhelper(self.functype, self.get_wrapper(space))
  175. self._llhelper = llh
  176. return llh
  177. @specialize.memo()
  178. def get_wrapper(self, space):
  179. wrapper = getattr(self, '_wrapper', None)
  180. if wrapper is None:
  181. wrapper = make_wrapper(space, self.callable)
  182. self._wrapper = wrapper
  183. wrapper.relax_sig_check = True
  184. if self.c_name is not None:
  185. wrapper.c_name = cpyext_namespace.uniquename(self.c_name)
  186. return wrapper
  187. def cpython_api(argtypes, restype, error=_NOT_SPECIFIED, external=True):
  188. """
  189. Declares a function to be exported.
  190. - `argtypes`, `restype` are lltypes and describe the function signature.
  191. - `error` is the value returned when an applevel exception is raised. The
  192. special value 'CANNOT_FAIL' (also when restype is Void) turns an eventual
  193. exception into a wrapped SystemError. Unwrapped exceptions also cause a
  194. SytemError.
  195. - set `external` to False to get a C function pointer, but not exported by
  196. the API headers.
  197. """
  198. if isinstance(restype, lltype.Typedef):
  199. real_restype = restype.OF
  200. else:
  201. real_restype = restype
  202. if error is _NOT_SPECIFIED:
  203. if isinstance(real_restype, lltype.Ptr):
  204. error = lltype.nullptr(real_restype.TO)
  205. elif real_restype is lltype.Void:
  206. error = CANNOT_FAIL
  207. if type(error) is int:
  208. error = rffi.cast(real_restype, error)
  209. expect_integer = (isinstance(real_restype, lltype.Primitive) and
  210. rffi.cast(restype, 0) == 0)
  211. def decorate(func):
  212. func_name = func.func_name
  213. if external:
  214. c_name = None
  215. else:
  216. c_name = func_name
  217. api_function = ApiFunction(argtypes, restype, func, error, c_name=c_name)
  218. func.api_func = api_function
  219. if external:
  220. assert func_name not in FUNCTIONS, (
  221. "%s already registered" % func_name)
  222. if error is _NOT_SPECIFIED:
  223. raise ValueError("function %s has no return value for exceptions"
  224. % func)
  225. def make_unwrapper(catch_exception):
  226. names = api_function.argnames
  227. types_names_enum_ui = unrolling_iterable(enumerate(
  228. zip(api_function.argtypes,
  229. [tp_name.startswith("w_") for tp_name in names])))
  230. @specialize.ll()
  231. def unwrapper(space, *args):
  232. from pypy.module.cpyext.pyobject import Py_DecRef
  233. from pypy.module.cpyext.pyobject import make_ref, from_ref
  234. from pypy.module.cpyext.pyobject import Reference
  235. newargs = ()
  236. to_decref = []
  237. assert len(args) == len(api_function.argtypes)
  238. for i, (ARG, is_wrapped) in types_names_enum_ui:
  239. input_arg = args[i]
  240. if is_PyObject(ARG) and not is_wrapped:
  241. # build a reference
  242. if input_arg is None:
  243. arg = lltype.nullptr(PyObject.TO)
  244. elif isinstance(input_arg, W_Root):
  245. ref = make_ref(space, input_arg)
  246. to_decref.append(ref)
  247. arg = rffi.cast(ARG, ref)
  248. else:
  249. arg = input_arg
  250. elif is_PyObject(ARG) and is_wrapped:
  251. # convert to a wrapped object
  252. if input_arg is None:
  253. arg = input_arg
  254. elif isinstance(input_arg, W_Root):
  255. arg = input_arg
  256. else:
  257. arg = from_ref(space,
  258. rffi.cast(PyObject, input_arg))
  259. else:
  260. arg = input_arg
  261. newargs += (arg, )
  262. try:
  263. try:
  264. res = func(space, *newargs)
  265. except OperationError, e:
  266. if not catch_exception:
  267. raise
  268. if not hasattr(api_function, "error_value"):
  269. raise
  270. state = space.fromcache(State)
  271. state.set_exception(e)
  272. if is_PyObject(restype):
  273. return None
  274. else:
  275. return api_function.error_value
  276. if not we_are_translated():
  277. got_integer = isinstance(res, (int, long, float))
  278. assert got_integer == expect_integer
  279. if res is None:
  280. return None
  281. elif isinstance(res, Reference):
  282. return res.get_wrapped(space)
  283. else:
  284. return res
  285. finally:
  286. for arg in to_decref:
  287. Py_DecRef(space, arg)
  288. unwrapper.func = func
  289. unwrapper.api_func = api_function
  290. unwrapper._always_inline_ = 'try'
  291. return unwrapper
  292. unwrapper_catch = make_unwrapper(True)
  293. unwrapper_raise = make_unwrapper(False)
  294. if external:
  295. FUNCTIONS[func_name] = api_function
  296. INTERPLEVEL_API[func_name] = unwrapper_catch # used in tests
  297. return unwrapper_raise # used in 'normal' RPython code.
  298. return decorate
  299. def cpython_struct(name, fields, forward=None, level=1):
  300. configname = name.replace(' ', '__')
  301. if level == 1:
  302. config = CConfig
  303. else:
  304. config = CConfig2
  305. setattr(config, configname, rffi_platform.Struct(name, fields))
  306. if forward is None:
  307. forward = lltype.ForwardReference()
  308. TYPES[configname] = forward
  309. return forward
  310. INTERPLEVEL_API = {}
  311. FUNCTIONS = {}
  312. # These are C symbols which cpyext will export, but which are defined in .c
  313. # files somewhere in the implementation of cpyext (rather than being defined in
  314. # RPython).
  315. SYMBOLS_C = [
  316. 'Py_FatalError', 'PyOS_snprintf', 'PyOS_vsnprintf', 'PyArg_Parse',
  317. 'PyArg_ParseTuple', 'PyArg_UnpackTuple', 'PyArg_ParseTupleAndKeywords',
  318. 'PyArg_VaParse', 'PyArg_VaParseTupleAndKeywords', '_PyArg_NoKeywords',
  319. 'PyString_FromFormat', 'PyString_FromFormatV',
  320. 'PyModule_AddObject', 'PyModule_AddIntConstant', 'PyModule_AddStringConstant',
  321. 'Py_BuildValue', 'Py_VaBuildValue', 'PyTuple_Pack',
  322. 'PyErr_Format', 'PyErr_NewException', 'PyErr_NewExceptionWithDoc',
  323. 'PySys_WriteStdout', 'PySys_WriteStderr',
  324. 'PyEval_CallFunction', 'PyEval_CallMethod', 'PyObject_CallFunction',
  325. 'PyObject_CallMethod', 'PyObject_CallFunctionObjArgs', 'PyObject_CallMethodObjArgs',
  326. 'PyBuffer_FromMemory', 'PyBuffer_FromReadWriteMemory', 'PyBuffer_FromObject',
  327. 'PyBuffer_FromReadWriteObject', 'PyBuffer_New', 'PyBuffer_Type', 'init_bufferobject',
  328. 'PyCObject_FromVoidPtr', 'PyCObject_FromVoidPtrAndDesc', 'PyCObject_AsVoidPtr',
  329. 'PyCObject_GetDesc', 'PyCObject_Import', 'PyCObject_SetVoidPtr',
  330. 'PyCObject_Type', 'init_pycobject',
  331. 'PyCapsule_New', 'PyCapsule_IsValid', 'PyCapsule_GetPointer',
  332. 'PyCapsule_GetName', 'PyCapsule_GetDestructor', 'PyCapsule_GetContext',
  333. 'PyCapsule_SetPointer', 'PyCapsule_SetName', 'PyCapsule_SetDestructor',
  334. 'PyCapsule_SetContext', 'PyCapsule_Import', 'PyCapsule_Type', 'init_capsule',
  335. 'PyObject_AsReadBuffer', 'PyObject_AsWriteBuffer', 'PyObject_CheckReadBuffer',
  336. 'PyOS_getsig', 'PyOS_setsig',
  337. 'PyThread_get_thread_ident', 'PyThread_allocate_lock', 'PyThread_free_lock',
  338. 'PyThread_acquire_lock', 'PyThread_release_lock',
  339. 'PyThread_create_key', 'PyThread_delete_key', 'PyThread_set_key_value',
  340. 'PyThread_get_key_value', 'PyThread_delete_key_value',
  341. 'PyThread_ReInitTLS',
  342. 'PyStructSequence_InitType', 'PyStructSequence_New',
  343. ]
  344. TYPES = {}
  345. GLOBALS = { # this needs to include all prebuilt pto, otherwise segfaults occur
  346. '_Py_NoneStruct#': ('PyObject*', 'space.w_None'),
  347. '_Py_TrueStruct#': ('PyObject*', 'space.w_True'),
  348. '_Py_ZeroStruct#': ('PyObject*', 'space.w_False'),
  349. '_Py_NotImplementedStruct#': ('PyObject*', 'space.w_NotImplemented'),
  350. '_Py_EllipsisObject#': ('PyObject*', 'space.w_Ellipsis'),
  351. 'PyDateTimeAPI': ('PyDateTime_CAPI*', 'None'),
  352. }
  353. FORWARD_DECLS = []
  354. INIT_FUNCTIONS = []
  355. BOOTSTRAP_FUNCTIONS = []
  356. def build_exported_objects():
  357. # Standard exceptions
  358. for exc_name in exceptions.Module.interpleveldefs.keys():
  359. GLOBALS['PyExc_' + exc_name] = (
  360. 'PyTypeObject*',
  361. 'space.gettypeobject(interp_exceptions.W_%s.typedef)'% (exc_name, ))
  362. # Common types with their own struct
  363. for cpyname, pypyexpr in {
  364. "Type": "space.w_type",
  365. "String": "space.w_str",
  366. "Unicode": "space.w_unicode",
  367. "BaseString": "space.w_basestring",
  368. "Dict": "space.w_dict",
  369. "Tuple": "space.w_tuple",
  370. "List": "space.w_list",
  371. "Set": "space.w_set",
  372. "FrozenSet": "space.w_frozenset",
  373. "Int": "space.w_int",
  374. "Bool": "space.w_bool",
  375. "Float": "space.w_float",
  376. "Long": "space.w_long",
  377. "Complex": "space.w_complex",
  378. "ByteArray": "space.w_bytearray",
  379. "MemoryView": "space.gettypeobject(W_MemoryView.typedef)",
  380. "BaseObject": "space.w_object",
  381. 'None': 'space.type(space.w_None)',
  382. 'NotImplemented': 'space.type(space.w_NotImplemented)',
  383. 'Cell': 'space.gettypeobject(Cell.typedef)',
  384. 'Module': 'space.gettypeobject(Module.typedef)',
  385. 'Property': 'space.gettypeobject(W_Property.typedef)',
  386. 'Slice': 'space.gettypeobject(W_SliceObject.typedef)',
  387. 'Class': 'space.gettypeobject(W_ClassObject.typedef)',
  388. 'StaticMethod': 'space.gettypeobject(StaticMethod.typedef)',
  389. 'CFunction': 'space.gettypeobject(cpyext.methodobject.W_PyCFunctionObject.typedef)',
  390. 'WrapperDescr': 'space.gettypeobject(cpyext.methodobject.W_PyCMethodObject.typedef)'
  391. }.items():
  392. GLOBALS['Py%s_Type#' % (cpyname, )] = ('PyTypeObject*', pypyexpr)
  393. for cpyname in 'Method List Long Dict Tuple Class'.split():
  394. FORWARD_DECLS.append('typedef struct { PyObject_HEAD } '
  395. 'Py%sObject' % (cpyname, ))
  396. build_exported_objects()
  397. def get_structtype_for_ctype(ctype):
  398. from pypy.module.cpyext.typeobjectdefs import PyTypeObjectPtr
  399. from pypy.module.cpyext.cdatetime import PyDateTime_CAPI
  400. return {"PyObject*": PyObject, "PyTypeObject*": PyTypeObjectPtr,
  401. "PyDateTime_CAPI*": lltype.Ptr(PyDateTime_CAPI)}[ctype]
  402. PyTypeObject = lltype.ForwardReference()
  403. PyTypeObjectPtr = lltype.Ptr(PyTypeObject)
  404. # It is important that these PyObjects are allocated in a raw fashion
  405. # Thus we cannot save a forward pointer to the wrapped object
  406. # So we need a forward and backward mapping in our State instance
  407. PyObjectStruct = lltype.ForwardReference()
  408. PyObject = lltype.Ptr(PyObjectStruct)
  409. PyObjectFields = (("ob_refcnt", lltype.Signed), ("ob_type", PyTypeObjectPtr))
  410. PyVarObjectFields = PyObjectFields + (("ob_size", Py_ssize_t), )
  411. cpython_struct('PyObject', PyObjectFields, PyObjectStruct)
  412. PyVarObjectStruct = cpython_struct("PyVarObject", PyVarObjectFields)
  413. PyVarObject = lltype.Ptr(PyVarObjectStruct)
  414. Py_buffer = cpython_struct(
  415. "Py_buffer", (
  416. ('buf', rffi.VOIDP),
  417. ('obj', PyObject),
  418. ('len', Py_ssize_t),
  419. ('itemsize', Py_ssize_t),
  420. ('readonly', lltype.Signed),
  421. ('ndim', lltype.Signed),
  422. ('format', rffi.CCHARP),
  423. ('shape', Py_ssize_tP),
  424. ('strides', Py_ssize_tP),
  425. ('suboffsets', Py_ssize_tP),
  426. #('smalltable', rffi.CFixedArray(Py_ssize_t, 2)),
  427. ('internal', rffi.VOIDP)
  428. ))
  429. @specialize.memo()
  430. def is_PyObject(TYPE):
  431. if not isinstance(TYPE, lltype.Ptr):
  432. return False
  433. return hasattr(TYPE.TO, 'c_ob_refcnt') and hasattr(TYPE.TO, 'c_ob_type')
  434. # a pointer to PyObject
  435. PyObjectP = rffi.CArrayPtr(PyObject)
  436. VA_TP_LIST = {}
  437. #{'int': lltype.Signed,
  438. # 'PyObject*': PyObject,
  439. # 'PyObject**': PyObjectP,
  440. # 'int*': rffi.INTP}
  441. def configure_types():
  442. for config in (CConfig, CConfig2):
  443. for name, TYPE in rffi_platform.configure(config).iteritems():
  444. if name in TYPES:
  445. TYPES[name].become(TYPE)
  446. def build_type_checkers(type_name, cls=None):
  447. """
  448. Builds two api functions: Py_XxxCheck() and Py_XxxCheckExact().
  449. - if `cls` is None, the type is space.w_[type].
  450. - if `cls` is a string, it is the name of a space attribute, e.g. 'w_str'.
  451. - else `cls` must be a W_Class with a typedef.
  452. """
  453. if cls is None:
  454. attrname = "w_" + type_name.lower()
  455. def get_w_type(space):
  456. return getattr(space, attrname)
  457. elif isinstance(cls, str):
  458. def get_w_type(space):
  459. return getattr(space, cls)
  460. else:
  461. def get_w_type(space):
  462. return space.gettypeobject(cls.typedef)
  463. check_name = "Py" + type_name + "_Check"
  464. def check(space, w_obj):
  465. "Implements the Py_Xxx_Check function"
  466. w_obj_type = space.type(w_obj)
  467. w_type = get_w_type(space)
  468. return (space.is_w(w_obj_type, w_type) or
  469. space.is_true(space.issubtype(w_obj_type, w_type)))
  470. def check_exact(space, w_obj):
  471. "Implements the Py_Xxx_CheckExact function"
  472. w_obj_type = space.type(w_obj)
  473. w_type = get_w_type(space)
  474. return space.is_w(w_obj_type, w_type)
  475. check = cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL)(
  476. func_with_new_name(check, check_name))
  477. check_exact = cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL)(
  478. func_with_new_name(check_exact, check_name + "Exact"))
  479. return check, check_exact
  480. pypy_debug_catch_fatal_exception = rffi.llexternal('pypy_debug_catch_fatal_exception', [], lltype.Void)
  481. # Make the wrapper for the cases (1) and (2)
  482. def make_wrapper(space, callable):
  483. "NOT_RPYTHON"
  484. names = callable.api_func.argnames
  485. argtypes_enum_ui = unrolling_iterable(enumerate(zip(callable.api_func.argtypes,
  486. [name.startswith("w_") for name in names])))
  487. fatal_value = callable.api_func.restype._defl()
  488. @specialize.ll()
  489. def wrapper(*args):
  490. from pypy.module.cpyext.pyobject import make_ref, from_ref
  491. from pypy.module.cpyext.pyobject import Reference
  492. # we hope that malloc removal removes the newtuple() that is
  493. # inserted exactly here by the varargs specializer
  494. llop.gc_stack_bottom(lltype.Void) # marker for trackgcroot.py
  495. rffi.stackcounter.stacks_counter += 1
  496. retval = fatal_value
  497. boxed_args = ()
  498. try:
  499. if not we_are_translated() and DEBUG_WRAPPER:
  500. print >>sys.stderr, callable,
  501. assert len(args) == len(callable.api_func.argtypes)
  502. for i, (typ, is_wrapped) in argtypes_enum_ui:
  503. arg = args[i]
  504. if is_PyObject(typ) and is_wrapped:
  505. if arg:
  506. arg_conv = from_ref(space, rffi.cast(PyObject, arg))
  507. else:
  508. arg_conv = None
  509. else:
  510. arg_conv = arg
  511. boxed_args += (arg_conv, )
  512. state = space.fromcache(State)
  513. try:
  514. result = callable(space, *boxed_args)
  515. if not we_are_translated() and DEBUG_WRAPPER:
  516. print >>sys.stderr, " DONE"
  517. except OperationError, e:
  518. failed = True
  519. state.set_exception(e)
  520. except BaseException, e:
  521. failed = True
  522. if not we_are_translated():
  523. message = repr(e)
  524. import traceback
  525. traceback.print_exc()
  526. else:
  527. message = str(e)
  528. state.set_exception(OperationError(space.w_SystemError,
  529. space.wrap(message)))
  530. else:
  531. failed = False
  532. if failed:
  533. error_value = callable.api_func.error_value
  534. if error_value is CANNOT_FAIL:
  535. raise SystemError("The function '%s' was not supposed to fail"
  536. % (callable.__name__,))
  537. retval = error_value
  538. elif is_PyObject(callable.api_func.restype):
  539. if result is None:
  540. retval = rffi.cast(callable.api_func.restype,
  541. make_ref(space, None))
  542. elif isinstance(result, Reference):
  543. retval = result.get_ref(space)
  544. elif not rffi._isllptr(result):
  545. retval = rffi.cast(callable.api_func.restype,
  546. make_ref(space, result))
  547. else:
  548. retval = result
  549. elif callable.api_func.restype is not lltype.Void:
  550. retval = rffi.cast(callable.api_func.restype, result)
  551. except Exception, e:
  552. print 'Fatal error in cpyext, CPython compatibility layer, calling', callable.__name__
  553. print 'Either report a bug or consider not using this particular extension'
  554. if not we_are_translated():
  555. import traceback
  556. traceback.print_exc()
  557. print str(e)
  558. # we can't do much here, since we're in ctypes, swallow
  559. else:
  560. print str(e)
  561. pypy_debug_catch_fatal_exception()
  562. rffi.stackcounter.stacks_counter -= 1
  563. return retval
  564. callable._always_inline_ = 'try'
  565. wrapper.__name__ = "wrapper for %r" % (callable, )
  566. return wrapper
  567. def process_va_name(name):
  568. return name.replace('*', '_star')
  569. def setup_va_functions(eci):
  570. for name, TP in VA_TP_LIST.iteritems():
  571. name_no_star = process_va_name(name)
  572. func = rffi.llexternal('pypy_va_get_%s' % name_no_star, [VA_LIST_P],
  573. TP, compilation_info=eci)
  574. globals()['va_get_%s' % name_no_star] = func
  575. def setup_init_functions(eci, translating):
  576. init_buffer = rffi.llexternal('init_bufferobject', [], lltype.Void,
  577. compilation_info=eci, _nowrapper=True)
  578. init_pycobject = rffi.llexternal('init_pycobject', [], lltype.Void,
  579. compilation_info=eci, _nowrapper=True)
  580. init_capsule = rffi.llexternal('init_capsule', [], lltype.Void,
  581. compilation_info=eci, _nowrapper=True)
  582. INIT_FUNCTIONS.extend([
  583. lambda space: init_buffer(),
  584. lambda space: init_pycobject(),
  585. lambda space: init_capsule(),
  586. ])
  587. from pypy.module.posix.interp_posix import add_fork_hook
  588. if translating:
  589. reinit_tls = rffi.llexternal('PyThread_ReInitTLS', [], lltype.Void,
  590. compilation_info=eci)
  591. else:
  592. reinit_tls = rffi.llexternal('PyPyThread_ReInitTLS', [], lltype.Void,
  593. compilation_info=eci)
  594. add_fork_hook('child', reinit_tls)
  595. def init_function(func):
  596. INIT_FUNCTIONS.append(func)
  597. return func
  598. def bootstrap_function(func):
  599. BOOTSTRAP_FUNCTIONS.append(func)
  600. return func
  601. def run_bootstrap_functions(space):
  602. for func in BOOTSTRAP_FUNCTIONS:
  603. func(space)
  604. def c_function_signature(db, func):
  605. restype = db.gettype(func.restype).replace('@', '').strip()
  606. args = []
  607. for i, argtype in enumerate(func.argtypes):
  608. if argtype is CONST_STRING:
  609. arg = 'const char *@'
  610. elif argtype is CONST_WSTRING:
  611. arg = 'const wchar_t *@'
  612. else:
  613. arg = db.gettype(argtype)
  614. arg = arg.replace('@', 'arg%d' % (i,)).strip()
  615. args.append(arg)
  616. args = ', '.join(args) or "void"
  617. return restype, args
  618. #_____________________________________________________
  619. # Build the bridge DLL, Allow extension DLLs to call
  620. # back into Pypy space functions
  621. # Do not call this more than once per process
  622. def build_bridge(space):
  623. "NOT_RPYTHON"
  624. from pypy.module.cpyext.pyobject import make_ref
  625. export_symbols = list(FUNCTIONS) + SYMBOLS_C + list(GLOBALS)
  626. from rpython.translator.c.database import LowLevelDatabase
  627. db = LowLevelDatabase()
  628. generate_macros(export_symbols, rename=True, do_deref=True)
  629. # Structure declaration code
  630. members = []
  631. structindex = {}
  632. for name, func in sorted(FUNCTIONS.iteritems()):
  633. restype, args = c_function_signature(db, func)
  634. members.append('%s (*%s)(%s);' % (restype, name, args))
  635. structindex[name] = len(structindex)
  636. structmembers = '\n'.join(members)
  637. struct_declaration_code = """\
  638. struct PyPyAPI {
  639. %(members)s
  640. } _pypyAPI;
  641. struct PyPyAPI* pypyAPI = &_pypyAPI;
  642. """ % dict(members=structmembers)
  643. functions = generate_decls_and_callbacks(db, export_symbols)
  644. global_objects = []
  645. for name, (typ, expr) in GLOBALS.iteritems():
  646. if "#" in name:
  647. continue
  648. if typ == 'PyDateTime_CAPI*':
  649. continue
  650. elif name.startswith('PyExc_'):
  651. global_objects.append('%s _%s;' % (typ[:-1], name))
  652. else:
  653. global_objects.append('%s %s = NULL;' % (typ, name))
  654. global_code = '\n'.join(global_objects)
  655. prologue = ("#include <Python.h>\n"
  656. "#include <src/thread.c>\n")
  657. code = (prologue +
  658. struct_declaration_code +
  659. global_code +
  660. '\n' +
  661. '\n'.join(functions))
  662. eci = build_eci(True, export_symbols, code)
  663. eci = eci.compile_shared_lib(
  664. outputfilename=str(udir / "module_cache" / "pypyapi"))
  665. modulename = py.path.local(eci.libraries[-1])
  666. run_bootstrap_functions(space)
  667. # load the bridge, and init structure
  668. import ctypes
  669. bridge = ctypes.CDLL(str(modulename), mode=ctypes.RTLD_GLOBAL)
  670. space.fromcache(State).install_dll(eci)
  671. # populate static data
  672. for name, (typ, expr) in GLOBALS.iteritems():
  673. from pypy.module import cpyext
  674. w_obj = eval(expr)
  675. if name.endswith('#'):
  676. name = name[:-1]
  677. isptr = False
  678. else:
  679. isptr = True
  680. if name.startswith('PyExc_'):
  681. isptr = False
  682. INTERPLEVEL_API[name] = w_obj
  683. name = name.replace('Py', 'PyPy')
  684. if isptr:
  685. ptr = ctypes.c_void_p.in_dll(bridge, name)
  686. if typ == 'PyObject*':
  687. value = make_ref(space, w_obj)
  688. elif typ == 'PyDateTime_CAPI*':
  689. value = w_obj
  690. else:
  691. assert False, "Unknown static pointer: %s %s" % (typ, name)
  692. ptr.value = ctypes.cast(ll2ctypes.lltype2ctypes(value),
  693. ctypes.c_void_p).value
  694. elif typ in ('PyObject*', 'PyTypeObject*'):
  695. if name.startswith('PyPyExc_'):
  696. # we already have the pointer
  697. in_dll = ll2ctypes.get_ctypes_type(PyObject).in_dll(bridge, name)
  698. py_obj = ll2ctypes.ctypes2lltype(PyObject, in_dll)
  699. else:
  700. # we have a structure, get its address
  701. in_dll = ll2ctypes.get_ctypes_type(PyObject.TO).in_dll(bridge, name)
  702. py_obj = ll2ctypes.ctypes2lltype(PyObject, ctypes.pointer(in_dll))
  703. from pypy.module.cpyext.pyobject import (
  704. track_reference, get_typedescr)
  705. w_type = space.type(w_obj)
  706. typedescr = get_typedescr(w_type.instancetypedef)
  707. py_obj.c_ob_refcnt = 1
  708. py_obj.c_ob_type = rffi.cast(PyTypeObjectPtr,
  709. make_ref(space, w_type))
  710. typedescr.attach(space, py_obj, w_obj)
  711. track_reference(space, py_obj, w_obj)
  712. else:
  713. assert False, "Unknown static object: %s %s" % (typ, name)
  714. pypyAPI = ctypes.POINTER(ctypes.c_void_p).in_dll(bridge, 'pypyAPI')
  715. # implement structure initialization code
  716. for name, func in FUNCTIONS.iteritems():
  717. if name.startswith('cpyext_'): # XXX hack
  718. continue
  719. pypyAPI[structindex[name]] = ctypes.cast(
  720. ll2ctypes.lltype2ctypes(func.get_llhelper(space)),
  721. ctypes.c_void_p)
  722. setup_va_functions(eci)
  723. setup_init_functions(eci, translating=False)
  724. return modulename.new(ext='')
  725. def generate_macros(export_symbols, rename=True, do_deref=True):
  726. "NOT_RPYTHON"
  727. pypy_macros = []
  728. renamed_symbols = []
  729. for name in export_symbols:
  730. if name.startswith("PyPy"):
  731. renamed_symbols.append(name)
  732. continue
  733. if not rename:
  734. continue
  735. name = name.replace("#", "")
  736. newname = name.replace('Py', 'PyPy')
  737. if not rename:
  738. newname = name
  739. pypy_macros.append('#define %s %s' % (name, newname))
  740. if name.startswith("PyExc_"):
  741. pypy_macros.append('#define _%s _%s' % (name, newname))
  742. renamed_symbols.append(newname)
  743. if rename:
  744. export_symbols[:] = renamed_symbols
  745. else:
  746. export_symbols[:] = [sym.replace("#", "") for sym in export_symbols]
  747. # Generate defines
  748. for macro_name, size in [
  749. ("SIZEOF_LONG_LONG", rffi.LONGLONG),
  750. ("SIZEOF_VOID_P", rffi.VOIDP),
  751. ("SIZEOF_SIZE_T", rffi.SIZE_T),
  752. ("SIZEOF_TIME_T", rffi.TIME_T),
  753. ("SIZEOF_LONG", rffi.LONG),
  754. ("SIZEOF_SHORT", rffi.SHORT),
  755. ("SIZEOF_INT", rffi.INT)
  756. ]:
  757. pypy_macros.append("#define %s %s" % (macro_name, rffi.sizeof(size)))
  758. pypy_macros.append('')
  759. pypy_macros_h = udir.join('pypy_macros.h')
  760. pypy_macros_h.write('\n'.join(pypy_macros))
  761. def generate_decls_and_callbacks(db, export_symbols, api_struct=True):
  762. "NOT_RPYTHON"
  763. # implement function callbacks and generate function decls
  764. functions = []
  765. pypy_decls = []
  766. pypy_decls.append("#ifndef PYPY_STANDALONE\n")
  767. pypy_decls.append("#ifdef __cplusplus")
  768. pypy_decls.append("extern \"C\" {")
  769. pypy_decls.append("#endif\n")
  770. pypy_decls.append('#define Signed long /* xxx temporary fix */\n')
  771. pypy_decls.append('#define Unsigned unsigned long /* xxx temporary fix */\n')
  772. for decl in FORWARD_DECLS:
  773. pypy_decls.append("%s;" % (decl,))
  774. for name, func in sorted(FUNCTIONS.iteritems()):
  775. restype, args = c_function_signature(db, func)
  776. pypy_decls.append("PyAPI_FUNC(%s) %s(%s);" % (restype, name, args))
  777. if api_struct:
  778. callargs = ', '.join('arg%d' % (i,)
  779. for i in range(len(func.argtypes)))
  780. if func.restype is lltype.Void:
  781. body = "{ _pypyAPI.%s(%s); }" % (name, callargs)
  782. else:
  783. body = "{ return _pypyAPI.%s(%s); }" % (name, callargs)
  784. functions.append('%s %s(%s)\n%s' % (restype, name, args, body))
  785. for name in VA_TP_LIST:
  786. name_no_star = process_va_name(name)
  787. header = ('%s pypy_va_get_%s(va_list* vp)' %
  788. (name, name_no_star))
  789. pypy_decls.append(header + ';')
  790. functions.append(header + '\n{return va_arg(*vp, %s);}\n' % name)
  791. export_symbols.append('pypy_va_get_%s' % (name_no_star,))
  792. for name, (typ, expr) in GLOBALS.iteritems():
  793. if name.endswith('#'):
  794. name = name.replace("#", "")
  795. typ = typ.replace("*", "")
  796. elif name.startswith('PyExc_'):
  797. typ = 'PyObject*'
  798. pypy_decls.append('PyAPI_DATA(%s) %s;' % (typ, name))
  799. pypy_decls.append('#undef Signed /* xxx temporary fix */\n')
  800. pypy_decls.append('#undef Unsigned /* xxx temporary fix */\n')
  801. pypy_decls.append("#ifdef __cplusplus")
  802. pypy_decls.append("}")
  803. pypy_decls.append("#endif")
  804. pypy_decls.append("#endif /*PYPY_STANDALONE*/\n")
  805. pypy_decl_h = udir.join('pypy_decl.h')
  806. pypy_decl_h.write('\n'.join(pypy_decls))
  807. return functions
  808. def build_eci(building_bridge, export_symbols, code):
  809. "NOT_RPYTHON"
  810. # Build code and get pointer to the structure
  811. kwds = {}
  812. export_symbols_eci = export_symbols[:]
  813. compile_extra=['-DPy_BUILD_CORE']
  814. if building_bridge:
  815. if sys.platform == "win32":
  816. # '%s' undefined; assuming extern returning int
  817. compile_extra.append("/we4013")
  818. # Sometimes the library is wrapped into another DLL, ensure that
  819. # the correct bootstrap code is installed
  820. kwds["link_extra"] = ["msvcrt.lib"]
  821. elif sys.platform.startswith('linux'):
  822. compile_extra.append("-Werror=implicit-function-declaration")
  823. export_symbols_eci.append('pypyAPI')
  824. compile_extra.append('-g')
  825. else:
  826. kwds["includes"] = ['Python.h'] # this is our Python.h
  827. # Generate definitions for global structures
  828. structs = ["#include <Python.h>"]
  829. for name, (typ, expr) in GLOBALS.iteritems():
  830. if name.endswith('#'):
  831. structs.append('%s %s;' % (typ[:-1], name[:-1]))
  832. elif name.startswith('PyExc_'):
  833. structs.append('extern PyTypeObject _%s;' % (name,))
  834. structs.append('PyObject* %s = (PyObject*)&_%s;' % (name, name))
  835. elif typ == 'PyDateTime_CAPI*':
  836. structs.append('%s %s = NULL;' % (typ, name))
  837. struct_source = '\n'.join(structs)
  838. separate_module_sources = [code, struct_source]
  839. if sys.platform == 'win32':
  840. get_pythonapi_source = '''
  841. #include <windows.h>
  842. HANDLE pypy_get_pythonapi_handle() {
  843. MEMORY_BASIC_INFORMATION mi;
  844. memset(&mi, 0, sizeof(mi));
  845. if( !VirtualQueryEx(GetCurrentProcess(), &pypy_get_pythonapi_handle,
  846. &mi, sizeof(mi)) )
  847. return 0;
  848. return (HMODULE)mi.AllocationBase;
  849. }
  850. '''
  851. separate_module_sources.append(get_pythonapi_source)
  852. export_symbols_eci.append('pypy_get_pythonapi_handle')
  853. eci = ExternalCompilationInfo(
  854. include_dirs=include_dirs,
  855. separate_module_files=[source_dir / "varargwrapper.c",
  856. source_dir / "pyerrors.c",
  857. source_dir / "modsupport.c",
  858. source_dir / "getargs.c",
  859. source_dir / "abstract.c",
  860. source_dir / "stringobject.c",
  861. source_dir / "mysnprintf.c",
  862. source_dir / "pythonrun.c",
  863. source_dir / "sysmodule.c",
  864. source_dir / "bufferobject.c",
  865. source_dir / "cobject.c",
  866. source_dir / "structseq.c",
  867. source_dir / "capsule.c",
  868. source_dir / "pysignals.c",
  869. source_dir / "pythread.c",
  870. ],
  871. separate_module_sources=separate_module_sources,
  872. export_symbols=export_symbols_eci,
  873. compile_extra=compile_extra,
  874. **kwds
  875. )
  876. return eci
  877. def setup_library(space):
  878. "NOT_RPYTHON"
  879. from pypy.module.cpyext.pyobject import make_ref
  880. export_symbols = list(FUNCTIONS) + SYMBOLS_C + list(GLOBALS)
  881. from rpython.translator.c.database import LowLevelDatabase
  882. db = LowLevelDatabase()
  883. generate_macros(export_symbols, rename=False, do_deref=False)
  884. functions = generate_decls_and_callbacks(db, [], api_struct=False)
  885. code = "#include <Python.h>\n" + "\n".join(functions)
  886. eci = build_eci(False, export_symbols, code)
  887. space.fromcache(State).install_dll(eci)
  888. run_bootstrap_functions(space)
  889. setup_va_functions(eci)
  890. # populate static data
  891. for name, (typ, expr) in GLOBALS.iteritems():
  892. name = name.replace("#", "")
  893. if name.startswith('PyExc_'):
  894. name = '_' + name
  895. from pypy.module import cpyext
  896. w_obj = eval(expr)
  897. if typ in ('PyObject*', 'PyTypeObject*'):
  898. struct_ptr = make_ref(space, w_obj)
  899. elif typ == 'PyDateTime_CAPI*':
  900. continue
  901. else:
  902. assert False, "Unknown static data: %s %s" % (typ, name)
  903. struct = rffi.cast(get_structtype_for_ctype(typ), struct_ptr)._obj
  904. struct._compilation_info = eci
  905. export_struct(name, struct)
  906. for name, func in FUNCTIONS.iteritems():
  907. deco = entrypoint("cpyext", func.argtypes, name, relax=True)
  908. deco(func.get_wrapper(space))
  909. setup_init_functions(eci, translating=True)
  910. trunk_include = pypydir.dirpath() / 'include'
  911. copy_header_files(trunk_include)
  912. initfunctype = lltype.Ptr(lltype.FuncType([], lltype.Void))
  913. @unwrap_spec(path=str, name=str)
  914. def load_extension_module(space, path, name):
  915. if os.sep not in path:
  916. path = os.curdir + os.sep + path # force a '/' in the path
  917. state = space.fromcache(State)
  918. if state.find_extension(name, path) is not None:
  919. return
  920. old_context = state.package_context
  921. state.package_context = name, path
  922. try:
  923. from rpython.rlib import rdynload
  924. try:
  925. ll_libname = rffi.str2charp(path)
  926. try:
  927. dll = rdynload.dlopen(ll_libname)
  928. finally:
  929. lltype.free(ll_libname, flavor='raw')
  930. except rdynload.DLOpenError, e:
  931. raise operationerrfmt(
  932. space.w_ImportError,
  933. "unable to load extension module '%s': %s",
  934. path, e.msg)
  935. try:
  936. initptr = rdynload.dlsym(dll, 'init%s' % (name.split('.')[-1],))
  937. except KeyError:
  938. raise operationerrfmt(
  939. space.w_ImportError,
  940. "function init%s not found in library %s",
  941. name, path)
  942. initfunc = rffi.cast(initfunctype, initptr)
  943. generic_cpy_call(space, initfunc)
  944. state.check_and_raise_exception()
  945. finally:
  946. state.package_context = old_context
  947. state.fixup_extension(name, path)
  948. @specialize.ll()
  949. def generic_cpy_call(space, func, *args):
  950. FT = lltype.typeOf(func).TO
  951. return make_generic_cpy_call(FT, True, False)(space, func, *args)
  952. @specialize.ll()
  953. def generic_cpy_call_dont_decref(space, func, *args):
  954. FT = lltype.typeOf(func).TO
  955. return make_generic_cpy_call(FT, False, False)(space, func, *args)
  956. @specialize.ll()
  957. def generic_cpy_call_expect_null(space, func, *args):
  958. FT = lltype.typeOf(func).TO
  959. return make_generic_cpy_call(FT, True, True)(space, func, *args)
  960. @specialize.memo()
  961. def make_generic_cpy_call(FT, decref_args, expect_null):
  962. from pypy.module.cpyext.pyobject import make_ref, from_ref, Py_DecRef
  963. from pypy.module.cpyext.pyobject import RefcountState
  964. from pypy.module.cpyext.pyerrors import PyErr_Occurred
  965. unrolling_arg_types = unrolling_iterable(enumerate(FT.ARGS))
  966. RESULT_TYPE = FT.RESULT
  967. # copied and modified from rffi.py
  968. # We need tons of care to ensure that no GC operation and no
  969. # exception checking occurs in call_external_function.
  970. argnames = ', '.join(['a%d' % i for i in range(len(FT.ARGS))])
  971. source = py.code.Source("""
  972. def cpy_call_external(funcptr, %(argnames)s):
  973. # NB. it is essential that no exception checking occurs here!
  974. res = funcptr(%(argnames)s)
  975. return res
  976. """ % locals())
  977. miniglobals = {'__name__': __name__, # for module name propagation
  978. }
  979. exec source.compile() in miniglobals
  980. call_external_function = miniglobals['cpy_call_external']
  981. call_external_function._dont_inline_ = True
  982. call_external_function._annspecialcase_ = 'specialize:ll'
  983. call_external_function._gctransformer_hint_close_stack_ = True
  984. # don't inline, as a hack to guarantee that no GC pointer is alive
  985. # anywhere in call_external_function
  986. @specialize.ll()
  987. def generic_cpy_call(space, func, *args):
  988. boxed_args = ()
  989. to_decref = []
  990. assert len(args) == len(FT.ARGS)
  991. for i, ARG in unrolling_arg_types:
  992. arg = args[i]
  993. if is_PyObject(ARG):
  994. if arg is None:
  995. boxed_args += (lltype.nullptr(PyObject.TO),)
  996. elif isinstance(arg, W_Root):
  997. ref = make_ref(space, arg)
  998. boxed_args += (ref,)
  999. if decref_args:
  1000. to_decref.append(ref)
  1001. else:
  1002. boxed_args += (arg,)
  1003. else:
  1004. boxed_args += (arg,)
  1005. try:
  1006. # create a new container for borrowed references
  1007. state = space.fromcache(RefcountState)
  1008. old_container = state.swap_borrow_container(None)
  1009. try:
  1010. # Call the function
  1011. result = call_external_function(func, *boxed_args)
  1012. finally:
  1013. state.swap_borrow_container(old_container)
  1014. if is_PyObject(RESULT_TYPE):
  1015. if result is None:
  1016. ret = result
  1017. elif isinstance(result, W_Root):
  1018. ret = result
  1019. else:
  1020. ret = from_ref(space, result)
  1021. # The object reference returned from a C function
  1022. # that is called from Python must be an owned reference
  1023. # - ownership is transferred from the function to its caller.
  1024. if result:
  1025. Py_DecRef(space, result)
  1026. # Check for exception consistency
  1027. has_error = PyErr_Occurred(space) is not None
  1028. has_result = ret is not None
  1029. if has_error and has_result:
  1030. raise OperationError(space.w_SystemError, space.wrap(
  1031. "An exception was set, but function returned a value"))
  1032. elif not expect_null and not has_error and not has_result:
  1033. raise OperationError(space.w_SystemError, space.wrap(
  1034. "Function returned a NULL result without setting an exception"))
  1035. if has_error:
  1036. state = space.fromcache(State)
  1037. state.check_and_raise_exception()
  1038. return ret
  1039. return result
  1040. finally:
  1041. if decref_args:
  1042. for ref in to_decref:
  1043. Py_DecRef(space, ref)
  1044. return generic_cpy_call