def test_opaque_obj(self): eci = ExternalCompilationInfo(includes=['sys/time.h', 'time.h']) TIMEVALP = rffi.COpaquePtr('struct timeval', compilation_info=eci) TIMEZONEP = rffi.COpaquePtr('struct timezone', compilation_info=eci) gettimeofday = rffi.llexternal('gettimeofday', [TIMEVALP, TIMEZONEP], rffi.INT, compilation_info=eci) ll_timevalp = lltype.malloc(TIMEVALP.TO, flavor='raw') ll_timezonep = lltype.malloc(TIMEZONEP.TO, flavor='raw') res = gettimeofday(ll_timevalp, ll_timezonep) assert res != -1 lltype.free(ll_timezonep, flavor='raw') lltype.free(ll_timevalp, flavor='raw') assert not ALLOCATED # detects memory leaks in the test
for k, v in rffi_platform.configure(CConfig).items(): globals()[k] = v def winexternal(name, args, result, **kwds): return rffi.llexternal(name, args, result, compilation_info=eci, calling_conv='win', **kwds) if WIN32: HANDLE = rffi.COpaquePtr(typedef='HANDLE') assert rffi.cast(HANDLE, -1) == rffi.cast(HANDLE, -1) LPHANDLE = rffi.CArrayPtr(HANDLE) HMODULE = HANDLE NULL_HANDLE = rffi.cast(HANDLE, 0) INVALID_HANDLE_VALUE = rffi.cast(HANDLE, -1) PFILETIME = rffi.CArrayPtr(FILETIME) _GetLastError = winexternal('GetLastError', [], DWORD, threadsafe=False) _SetLastError = winexternal('SetLastError', [DWORD], lltype.Void) def GetLastError(): return rffi.cast(lltype.Signed, _GetLastError()) def SetLastError(err):
try: ident = thread.start_new_thread(func, ()) except thread.error: ident = -1 return rffi.cast(rffi.INT, ident) CALLBACK = lltype.Ptr(lltype.FuncType([], lltype.Void)) c_thread_start = llexternal('RPyThreadStart', [CALLBACK], rffi.INT, _callable=_emulated_start_new_thread, threadsafe=True) # release the GIL, but most # importantly, reacquire it # around the callback c_thread_get_ident = llexternal('RPyThreadGetIdent', [], rffi.INT, _nowrapper=True) # always call directly TLOCKP = rffi.COpaquePtr('struct RPyOpaque_ThreadLock', compilation_info=eci) c_thread_lock_init = llexternal('RPyThreadLockInit', [TLOCKP], lltype.Void) c_thread_acquirelock = llexternal('RPyThreadAcquireLock', [TLOCKP, rffi.INT], rffi.INT, threadsafe=True) # release the GIL c_thread_releaselock = llexternal('RPyThreadReleaseLock', [TLOCKP], lltype.Void, threadsafe=True) # release the GIL # another set of functions, this time in versions that don't cause the # GIL to be released. To use to handle the GIL lock itself. c_thread_acquirelock_NOAUTO = llexternal('RPyThreadAcquireLock', [TLOCKP, rffi.INT], rffi.INT, _nowrapper=True) c_thread_releaselock_NOAUTO = llexternal('RPyThreadReleaseLock', [TLOCKP], lltype.Void,
@cpython_api([PyThreadState], lltype.Void) def PyEval_ReleaseThread(space, tstate): """Reset the current thread state to NULL and release the global interpreter lock. The lock must have been created earlier and must be held by the current thread. The tstate argument, which must not be NULL, is only used to check that it represents the current thread state --- if it isn't, a fatal error is reported. This function is not available when thread support is disabled at compile time.""" # All cpyext calls release and acquire the GIL, so this is not necessary. pass PyGILState_STATE = rffi.COpaquePtr('PyGILState_STATE', typedef='PyGILState_STATE', compilation_info=CConfig._compilation_info_) @cpython_api([], PyGILState_STATE, error=CANNOT_FAIL) def PyGILState_Ensure(space): # All cpyext calls release and acquire the GIL, so this is not necessary. return 0 @cpython_api([PyGILState_STATE], lltype.Void) def PyGILState_Release(space, state): # All cpyext calls release and acquire the GIL, so this is not necessary. return
"pypy_cjk_dec_replace_on_error", "pypy_cjk_enc_new", "pypy_cjk_enc_init", "pypy_cjk_enc_free", "pypy_cjk_enc_chunk", "pypy_cjk_enc_reset", "pypy_cjk_enc_outbuf", "pypy_cjk_enc_outlen", "pypy_cjk_enc_inbuf_remaining", "pypy_cjk_enc_inbuf_consumed", "pypy_cjk_enc_replace_on_error", ] + ["pypy_cjkcodec_%s" % codec for codec in codecs], ) MBERR_TOOSMALL = -1 # insufficient output buffer space MBERR_TOOFEW = -2 # incomplete input buffer MBERR_INTERNAL = -3 # internal runtime error MBERR_NOMEMORY = -4 # out of memory MULTIBYTECODEC_P = rffi.COpaquePtr('struct MultibyteCodec_s', compilation_info=eci) def llexternal(*args, **kwds): kwds.setdefault('compilation_info', eci) kwds.setdefault('sandboxsafe', True) kwds.setdefault('_nowrapper', True) return rffi.llexternal(*args, **kwds) def getter_for(name): return llexternal('pypy_cjkcodec_%s' % name, [], MULTIBYTECODEC_P) _codecs_getters = dict([(name, getter_for(name)) for name in codecs]) assert len(_codecs_getters) == len(codecs) def getcodec(name): getter = _codecs_getters[name]
def register_os_listdir(self): # we need a different approach on Windows and on Posix if sys.platform.startswith('win'): class CConfig: _compilation_info_ = ExternalCompilationInfo( includes = ['windows.h'] ) WIN32_FIND_DATA = platform.Struct('struct _WIN32_FIND_DATAA', [('cFileName', lltype.FixedSizeArray(rffi.CHAR, 1))]) INVALID_HANDLE_VALUE = platform.ConstantInteger( 'INVALID_HANDLE_VALUE') ERROR_FILE_NOT_FOUND = platform.ConstantInteger( 'ERROR_FILE_NOT_FOUND') ERROR_NO_MORE_FILES = platform.ConstantInteger( 'ERROR_NO_MORE_FILES') config = platform.configure(CConfig) WIN32_FIND_DATA = config['WIN32_FIND_DATA'] INVALID_HANDLE_VALUE = config['INVALID_HANDLE_VALUE'] ERROR_FILE_NOT_FOUND = config['ERROR_FILE_NOT_FOUND'] ERROR_NO_MORE_FILES = config['ERROR_NO_MORE_FILES'] LPWIN32_FIND_DATA = lltype.Ptr(WIN32_FIND_DATA) HANDLE = rffi.ULONG #MAX_PATH = WIN32_FIND_DATA.c_cFileName.length GetLastError = self.llexternal('GetLastError', [], lltype.Signed) FindFirstFile = self.llexternal('FindFirstFile', [rffi.CCHARP, LPWIN32_FIND_DATA], HANDLE) FindNextFile = self.llexternal('FindNextFile', [HANDLE, LPWIN32_FIND_DATA], rffi.INT) FindClose = self.llexternal('FindClose', [HANDLE], rffi.INT) def os_listdir_llimpl(path): if path and path[-1] not in ('/', '\\', ':'): path += '/' path += '*.*' filedata = lltype.malloc(WIN32_FIND_DATA, flavor='raw') try: result = [] hFindFile = FindFirstFile(path, filedata) if hFindFile == INVALID_HANDLE_VALUE: error = GetLastError() if error == ERROR_FILE_NOT_FOUND: return result else: # XXX guess error code :-( raise OSError(errno.ENOENT, "FindFirstFile failed") while True: name = rffi.charp2str(rffi.cast(rffi.CCHARP, filedata.c_cFileName)) if name != "." and name != "..": # skip these result.append(name) if not FindNextFile(hFindFile, filedata): break # FindNextFile sets error to ERROR_NO_MORE_FILES if # it got to the end of the directory error = GetLastError() FindClose(hFindFile) if error == ERROR_NO_MORE_FILES: return result else: # XXX guess error code :-( raise OSError(errno.EIO, "FindNextFile failed") finally: lltype.free(filedata, flavor='raw') else: compilation_info = ExternalCompilationInfo( includes = ['sys/types.h', 'dirent.h'] ) class CConfig: _compilation_info_ = compilation_info DIRENT = platform.Struct('struct dirent', [('d_name', lltype.FixedSizeArray(rffi.CHAR, 1))]) DIRP = rffi.COpaquePtr('DIR') config = platform.configure(CConfig) DIRENT = config['DIRENT'] DIRENTP = lltype.Ptr(DIRENT) os_opendir = self.llexternal('opendir', [rffi.CCHARP], DIRP, compilation_info=compilation_info) os_readdir = self.llexternal('readdir', [DIRP], DIRENTP, compilation_info=compilation_info) os_closedir = self.llexternal('closedir', [DIRP], rffi.INT, compilation_info=compilation_info) def os_listdir_llimpl(path): dirp = os_opendir(path) if not dirp: raise OSError(rposix.get_errno(), "os_opendir failed") rposix.set_errno(0) result = [] while True: direntp = os_readdir(dirp) if not direntp: error = rposix.get_errno() break namep = rffi.cast(rffi.CCHARP, direntp.c_d_name) name = rffi.charp2str(namep) if name != '.' and name != '..': result.append(name) os_closedir(dirp) if error: raise OSError(error, "os_readdir failed") return result return extdef([str], # a single argument which is a str [str], # returns a list of strings "ll_os.ll_os_listdir", llimpl=os_listdir_llimpl)
FormatError = rwin32.FormatError LoadLibrary = rwin32.LoadLibrary get_libc_handle = external('get_libc_handle', [], rwin32.HANDLE) libc_name = rwin32.GetModuleFileName(get_libc_handle()) FFI_OK = cConfig.FFI_OK FFI_BAD_TYPEDEF = cConfig.FFI_BAD_TYPEDEF FFI_DEFAULT_ABI = rffi.cast(rffi.USHORT, cConfig.FFI_DEFAULT_ABI) if _MS_WINDOWS: FFI_STDCALL = rffi.cast(rffi.USHORT, cConfig.FFI_STDCALL) FFI_TYPE_STRUCT = rffi.cast(rffi.USHORT, cConfig.FFI_TYPE_STRUCT) FFI_CIFP = rffi.COpaquePtr('ffi_cif', compilation_info=eci) FFI_CLOSUREP = lltype.Ptr(cConfig.ffi_closure) VOIDPP = rffi.CArrayPtr(rffi.VOIDP) c_ffi_prep_cif = external('ffi_prep_cif', [FFI_CIFP, rffi.USHORT, rffi.UINT, FFI_TYPE_P, FFI_TYPE_PP], rffi.INT) c_ffi_call = external('ffi_call', [FFI_CIFP, rffi.VOIDP, rffi.VOIDP, VOIDPP], lltype.Void) CALLBACK_TP = rffi.CCallback([FFI_CIFP, rffi.VOIDP, rffi.VOIDPP, rffi.VOIDP], lltype.Void) c_ffi_prep_closure = external('ffi_prep_closure', [FFI_CLOSUREP, FFI_CIFP, CALLBACK_TP, rffi.VOIDP], rffi.INT)
rffi_platform.verify_eci(eci.convert_sources_to_files()) def llexternal(name, args, result, **kwds): return rffi.llexternal(name, args, result, compilation_info=eci, _nowrapper=True, **kwds) # ----- types ----- handle = rffi.COpaquePtr(typedef='stacklet_handle', compilation_info=eci) thread_handle = rffi.COpaquePtr(typedef='stacklet_thread_handle', compilation_info=eci) run_fn = lltype.Ptr(lltype.FuncType([handle, llmemory.Address], handle)) # ----- constants ----- null_handle = lltype.nullptr(handle.TO) def is_empty_handle(h): return rffi.cast(lltype.Signed, h) == -1 # ----- functions -----
from pypy.module.thread import ll_thread from pypy.module.cpyext.api import CANNOT_FAIL, cpython_api from pypy.rpython.lltypesystem import lltype, rffi @cpython_api([], rffi.LONG, error=CANNOT_FAIL) def PyThread_get_thread_ident(space): return ll_thread.get_ident() LOCKP = rffi.COpaquePtr(typedef='PyThread_type_lock') @cpython_api([], LOCKP) def PyThread_allocate_lock(space): lock = ll_thread.allocate_ll_lock() return rffi.cast(LOCKP, lock) @cpython_api([LOCKP], lltype.Void) def PyThread_free_lock(space, lock): lock = rffi.cast(ll_thread.TLOCKP, lock) ll_thread.free_ll_lock(lock) @cpython_api([LOCKP, rffi.INT], rffi.INT, error=CANNOT_FAIL) def PyThread_acquire_lock(space, lock, waitflag): lock = rffi.cast(ll_thread.TLOCKP, lock) return ll_thread.c_thread_acquirelock(lock, waitflag)
[('fd', socketfd_type), ('events', rffi.SHORT), ('revents', rffi.SHORT)]) if _WIN32: CConfig.WSAEVENT = platform.SimpleType('WSAEVENT', rffi.VOIDP) CConfig.WSANETWORKEVENTS = platform.Struct( 'struct _WSANETWORKEVENTS', [ ('lNetworkEvents', rffi.LONG), ('iErrorCode', rffi.CFixedArray(rffi.INT, 10)), #FD_MAX_EVENTS ]) CConfig.timeval = platform.Struct('struct timeval', [('tv_sec', rffi.LONG), ('tv_usec', rffi.LONG)]) fd_set = rffi.COpaquePtr('fd_set', compilation_info=eci) if _WIN32: CConfig.WSAData = platform.Struct( 'struct WSAData', [ ('wVersion', rffi.USHORT), ('wHighVersion', rffi.USHORT), ('szDescription', rffi.CFixedArray(lltype.Char, 1)), # (WSADESCRIPTION_LEN+1) ('szSystemStatus', rffi.CFixedArray(lltype.Char, 1)), # (WSASYS_STATUS_LEN+1) ('iMaxSockets', rffi.USHORT), ('iMaxUdpDg', rffi.USHORT), ('lpVendorInfo', CCHARP) ])
_compilation_info_ = eci TIMEVAL = platform.Struct('struct timeval', [('tv_sec', rffi.LONG), ('tv_usec', rffi.LONG)]) TIMESPEC = platform.Struct('struct timespec', [('tv_sec', rffi.TIME_T), ('tv_nsec', rffi.LONG)]) SEM_FAILED = platform.ConstantInteger('SEM_FAILED') SEM_VALUE_MAX = platform.ConstantInteger('SEM_VALUE_MAX') SEM_TIMED_WAIT = platform.Has('sem_timedwait') SEM_T_SIZE = platform.SizeOf('sem_t') config = platform.configure(CConfig) TIMEVAL = config['TIMEVAL'] TIMESPEC = config['TIMESPEC'] TIMEVALP = rffi.CArrayPtr(TIMEVAL) TIMESPECP = rffi.CArrayPtr(TIMESPEC) SEM_T = rffi.COpaquePtr('sem_t', compilation_info=eci) SEM_FAILED = config['SEM_FAILED'] # rffi.cast(SEM_T, config['SEM_FAILED']) SEM_VALUE_MAX = config['SEM_VALUE_MAX'] SEM_TIMED_WAIT = config['SEM_TIMED_WAIT'] SEM_T_SIZE = config['SEM_T_SIZE'] if sys.platform == 'darwin': HAVE_BROKEN_SEM_GETVALUE = True else: HAVE_BROKEN_SEM_GETVALUE = False def external(name, args, result, **kwargs): return rffi.llexternal(name, args, result, compilation_info=eci, **kwargs)
from pypy.interpreter.gateway import interp2app from pypy.interpreter.error import OperationError, operationerrfmt from pypy.interpreter.function import BuiltinFunction, Method, StaticMethod from pypy.rpython.lltypesystem import rffi, lltype from pypy.module.cpyext.pyobject import (PyObject, from_ref, make_ref, make_typedescr, Py_DecRef) from pypy.module.cpyext.api import (generic_cpy_call, cpython_api, PyObject, cpython_struct, METH_KEYWORDS, METH_O, CONST_STRING, METH_CLASS, METH_STATIC, METH_COEXIST, METH_NOARGS, METH_VARARGS, build_type_checkers, PyObjectFields, bootstrap_function) from pypy.module.cpyext.pyerrors import PyErr_Occurred from pypy.rlib.objectmodel import we_are_translated PyCFunction_typedef = rffi.COpaquePtr(typedef='PyCFunction') PyCFunction = lltype.Ptr(lltype.FuncType([PyObject, PyObject], PyObject)) PyCFunctionKwArgs = lltype.Ptr( lltype.FuncType([PyObject, PyObject, PyObject], PyObject)) PyMethodDef = cpython_struct('PyMethodDef', [ ('ml_name', rffi.CCHARP), ('ml_meth', PyCFunction_typedef), ('ml_flags', rffi.INT_real), ('ml_doc', rffi.CCHARP), ]) PyCFunctionObjectStruct = cpython_struct( 'PyCFunctionObject', PyObjectFields + ( ('m_ml', lltype.Ptr(PyMethodDef)), ('m_self', PyObject),
_compilation_info_ = CConfig._compilation_info_ VA_LIST_P = rffi.VOIDP # rffi.COpaquePtr('va_list') CONST_STRING = lltype.Ptr(lltype.Array(lltype.Char, hints={'nolength': True}), use_cache=False) CONST_WSTRING = lltype.Ptr(lltype.Array(lltype.UniChar, hints={'nolength': True}), use_cache=False) assert CONST_STRING is not rffi.CCHARP assert CONST_STRING == rffi.CCHARP assert CONST_WSTRING is not rffi.CWCHARP assert CONST_WSTRING == rffi.CWCHARP # FILE* interface FILEP = rffi.COpaquePtr('FILE') fopen = rffi.llexternal('fopen', [CONST_STRING, CONST_STRING], FILEP) fclose = rffi.llexternal('fclose', [FILEP], rffi.INT) fwrite = rffi.llexternal('fwrite', [rffi.VOIDP, rffi.SIZE_T, rffi.SIZE_T, FILEP], rffi.SIZE_T) fread = rffi.llexternal('fread', [rffi.VOIDP, rffi.SIZE_T, rffi.SIZE_T, FILEP], rffi.SIZE_T) feof = rffi.llexternal('feof', [FILEP], rffi.INT) if sys.platform == 'win32': fileno = rffi.llexternal('_fileno', [FILEP], rffi.INT) else: fileno = rffi.llexternal('fileno', [FILEP], rffi.INT) constant_names = """ Py_TPFLAGS_READY Py_TPFLAGS_READYING Py_TPFLAGS_HAVE_GETCHARBUFFER
bz_stream = platform.Struct('bz_stream', [('next_in', rffi.CCHARP), ('avail_in', rffi.UINT), ('total_in_lo32', rffi.UINT), ('total_in_hi32', rffi.UINT), ('next_out', rffi.CCHARP), ('avail_out', rffi.UINT), ('total_out_lo32', rffi.UINT), ('total_out_hi32', rffi.UINT), ('state', rffi.VOIDP), ('bzalloc', lltype.Ptr(_alloc_type)), ('bzfree', lltype.Ptr(_free_type)), ('opaque', rffi.VOIDP), ]) FILE = rffi.COpaquePtr('FILE') BZFILE = rffi.COpaquePtr('BZFILE') constants = {} constant_names = ['BZ_RUN', 'BZ_FLUSH', 'BZ_FINISH', 'BZ_OK', 'BZ_RUN_OK', 'BZ_FLUSH_OK', 'BZ_FINISH_OK', 'BZ_STREAM_END', 'BZ_SEQUENCE_ERROR', 'BZ_PARAM_ERROR', 'BZ_MEM_ERROR', 'BZ_DATA_ERROR', 'BZ_DATA_ERROR_MAGIC', 'BZ_IO_ERROR', 'BZ_UNEXPECTED_EOF', 'BZ_OUTBUFF_FULL', 'BZ_CONFIG_ERROR'] for name in constant_names: setattr(CConfig, name, platform.DefinedConstantInteger(name)) class cConfig(object): pass for k, v in platform.configure(CConfig).items():
libname = 'expat' eci = ExternalCompilationInfo( libraries=[libname], library_dirs=platform.preprocess_library_dirs([]), includes=['expat.h'], include_dirs=platform.preprocess_include_dirs([]), ) eci = rffi_platform.configure_external_library( libname, eci, [dict(prefix='expat-', include_dir='lib', library_dir='win32/bin/release'), ]) XML_Content_Ptr = lltype.Ptr(lltype.ForwardReference()) XML_Parser = rffi.COpaquePtr(typedef='XML_Parser') xml_error_list = [ "XML_ERROR_NO_MEMORY", "XML_ERROR_SYNTAX", "XML_ERROR_NO_ELEMENTS", "XML_ERROR_INVALID_TOKEN", "XML_ERROR_UNCLOSED_TOKEN", "XML_ERROR_PARTIAL_CHAR", "XML_ERROR_TAG_MISMATCH", "XML_ERROR_DUPLICATE_ATTRIBUTE", "XML_ERROR_JUNK_AFTER_DOC_ELEMENT", "XML_ERROR_PARAM_ENTITY_REF", "XML_ERROR_UNDEFINED_ENTITY", "XML_ERROR_RECURSIVE_ENTITY_REF", "XML_ERROR_ASYNC_ENTITY",
def copaqueptr(name): return rffi.COpaquePtr(name, compilation_info=eci)
], ) eci = rffi_platform.configure_external_library('openssl', eci, [ dict(prefix='openssl-', include_dir='inc32', library_dir='out32'), ]) # WinSock does not use a bitmask in select, and uses # socket handles greater than FD_SETSIZE if sys.platform == 'win32': MAX_FD_SIZE = None else: from pypy.rlib._rsocket_rffi import FD_SETSIZE as MAX_FD_SIZE ASN1_STRING = lltype.Ptr(lltype.ForwardReference()) ASN1_ITEM = rffi.COpaquePtr('ASN1_ITEM') ASN1_ITEM_EXP = lltype.Ptr(lltype.FuncType([], ASN1_ITEM)) X509_NAME = rffi.COpaquePtr('X509_NAME') class CConfig: _compilation_info_ = eci OPENSSL_VERSION_NUMBER = rffi_platform.ConstantInteger( "OPENSSL_VERSION_NUMBER") SSLEAY_VERSION = rffi_platform.DefinedConstantString( "SSLEAY_VERSION", "SSLeay_version(SSLEAY_VERSION)") OPENSSL_NO_SSL2 = rffi_platform.Defined("OPENSSL_NO_SSL2") SSL_FILETYPE_PEM = rffi_platform.ConstantInteger("SSL_FILETYPE_PEM") SSL_OP_ALL = rffi_platform.ConstantInteger("SSL_OP_ALL") SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS = rffi_platform.ConstantInteger(