def llexternal_use_eci(compilation_info): """Return a dummy function that, if called in a RPython program, adds the given ExternalCompilationInfo to it.""" eci = ExternalCompilationInfo(post_include_bits=['#define PYPY_NO_OP()']) eci = eci.merge(compilation_info) return llexternal('PYPY_NO_OP', [], lltype.Void, compilation_info=eci, sandboxsafe=True, _nowrapper=True, _callable=lambda: None)
def try_tools(): try: yield ExternalCompilationInfo.from_pkg_config("ncurses") except Exception: pass try: yield ExternalCompilationInfo.from_config_tool("ncurses5-config") except Exception: pass
def test_convert_sources_to_c_files(self): eci = ExternalCompilationInfo( separate_module_sources = ['xxx'], separate_module_files = ['x.c'], ) cache_dir = udir.join('test_convert_sources').ensure(dir=1) neweci = eci.convert_sources_to_files(cache_dir) assert not neweci.separate_module_sources res = neweci.separate_module_files assert len(res) == 2 assert res[0] == 'x.c' assert str(res[1]).startswith(str(cache_dir)) e = ExternalCompilationInfo() assert e.convert_sources_to_files() is e
def test_from_linker_flags(self): flags = ('-L/some/lib/path -L/other/lib/path ' '-lmylib1 -lmylib2 -?1 -!2') eci = ExternalCompilationInfo.from_linker_flags(flags) assert eci.libraries == ('mylib1', 'mylib2') assert eci.library_dirs == ('/some/lib/path', '/other/lib/path') assert eci.link_extra == ('-?1', '-!2')
def test_merge2(self): e1 = ExternalCompilationInfo( pre_include_bits = ['1'], link_files = ['1.c'] ) e2 = ExternalCompilationInfo( pre_include_bits = ['2'], link_files = ['1.c', '2.c'] ) e3 = ExternalCompilationInfo( pre_include_bits = ['3'], link_files = ['1.c', '2.c', '3.c'] ) e = e1.merge(e2) e = e.merge(e3, e3) assert e.pre_include_bits == ('1', '2', '3') assert e.link_files == ('1.c', '2.c', '3.c')
def compile_extension_module(space, modname, **kwds): """ Build an extension module and return the filename of the resulting native code file. modname is the name of the module, possibly including dots if it is a module inside a package. Any extra keyword arguments are passed on to ExternalCompilationInfo to build the module (so specify your source with one of those). """ state = space.fromcache(State) api_library = state.api_lib if sys.platform == 'win32': kwds["libraries"] = [api_library] # '%s' undefined; assuming extern returning int kwds["compile_extra"] = ["/we4013"] # prevent linking with PythonXX.lib w_maj, w_min = space.fixedview(space.sys.get('version_info'), 5)[:2] kwds["link_extra"] = ["/NODEFAULTLIB:Python%d%d.lib" % (space.int_w(w_maj), space.int_w(w_min))] elif sys.platform == 'darwin': kwds["link_files"] = [str(api_library + '.dylib')] else: kwds["link_files"] = [str(api_library + '.so')] if sys.platform.startswith('linux'): kwds["compile_extra"]=["-Werror=implicit-function-declaration", "-g", "-O0"] kwds["link_extra"]=["-g"] modname = modname.split('.')[-1] eci = ExternalCompilationInfo( include_dirs=api.include_dirs, **kwds ) eci = eci.convert_sources_to_files() dirname = (udir/uniquemodulename('module')).ensure(dir=1) soname = platform.platform.compile( [], eci, outputfilename=str(dirname/modname), standalone=False) from pypy.module.imp.importing import get_so_extension pydname = soname.new(purebasename=modname, ext=get_so_extension(space)) soname.rename(pydname) return str(pydname)
def test_platforms(self): from rpython.translator.platform import Platform class Maemo(Platform): def __init__(self, cc=None): self.cc = cc eci = ExternalCompilationInfo(platform=Maemo()) eci2 = ExternalCompilationInfo() assert eci != eci2 assert hash(eci) != hash(eci2) assert repr(eci) != repr(eci2) py.test.raises(Exception, eci2.merge, eci) assert eci.merge(eci).platform == Maemo() assert (ExternalCompilationInfo(platform=Maemo(cc='xxx')) != ExternalCompilationInfo(platform=Maemo(cc='yyy'))) assert (repr(ExternalCompilationInfo(platform=Maemo(cc='xxx'))) != repr(ExternalCompilationInfo(platform=Maemo(cc='yyy'))))
def test_from_compiler_flags(self): flags = ('-I/some/include/path -I/other/include/path ' '-DMACRO1 -D_MACRO2=baz -?1 -!2') eci = ExternalCompilationInfo.from_compiler_flags(flags) assert eci.pre_include_bits == ('#define MACRO1 1', '#define _MACRO2 baz') assert eci.includes == () assert eci.include_dirs == ('/some/include/path', '/other/include/path') assert eci.compile_extra == ('-?1', '-!2')
def test_from_pkg_config(self): try: cmd = ['pkg-config', 'ncurses', '--exists'] popen = Popen(cmd) result = popen.wait() except OSError: result = -1 if result != 0: py.test.skip("failed: %r" % (' '.join(cmd),)) eci = ExternalCompilationInfo.from_pkg_config('ncurses') assert 'ncurses' in eci.libraries
def test_merge(self): e1 = ExternalCompilationInfo( pre_include_bits = ['1'], includes = ['x.h'], post_include_bits = ['p1'] ) e2 = ExternalCompilationInfo( pre_include_bits = ['2'], includes = ['x.h', 'y.h'], post_include_bits = ['p2'], ) e3 = ExternalCompilationInfo( pre_include_bits = ['3'], includes = ['y.h', 'z.h'], post_include_bits = ['p1', 'p3'] ) e = e1.merge(e2, e3) assert e.pre_include_bits == ('1', '2', '3') assert e.includes == ('x.h', 'y.h', 'z.h') assert e.post_include_bits == ('p1', 'p2', 'p3')
def test_make_shared_lib(self): eci = ExternalCompilationInfo( separate_module_sources = [''' RPY_EXTERN int get() { return 42; } int shouldnt_export() { return 43; }'''], ) neweci = eci.compile_shared_lib() assert len(neweci.libraries) == 1 try: import ctypes except ImportError: py.test.skip("Need ctypes for that test") assert ctypes.CDLL(neweci.libraries[0]).get() == 42 assert not hasattr(ctypes.CDLL(neweci.libraries[0]), 'shouldnt_export') assert not neweci.separate_module_sources assert not neweci.separate_module_files
from __future__ import with_statement import os, sys import errno from rpython.rtyper.lltypesystem import lltype, rffi from rpython.rlib.objectmodel import not_rpython from rpython.translator.tool.cbuild import ExternalCompilationInfo from rpython.rtyper.tool import rffi_platform if sys.platform == 'win32': from rpython.rlib import rwin32 eci = ExternalCompilationInfo( includes = ['windows.h', 'wincrypt.h'], libraries = ['advapi32'], ) class CConfig: _compilation_info_ = eci PROV_RSA_FULL = rffi_platform.ConstantInteger( "PROV_RSA_FULL") CRYPT_VERIFYCONTEXT = rffi_platform.ConstantInteger( "CRYPT_VERIFYCONTEXT") globals().update(rffi_platform.configure(CConfig)) HCRYPTPROV = rwin32.ULONG_PTR CryptAcquireContext = rffi.llexternal( 'CryptAcquireContextA',
def configure_external_library(name, eci, configurations, symbol=None, _cache={}): """try to find the external library. On Unix, this simply tests and returns the given eci. On Windows, various configurations may be tried to compile the given eci object. These configurations are a list of dicts, containing: - prefix: if an absolute path, will prefix each include and library directories. If a relative path, the external directory is searched for directories which names start with the prefix. The last one in alphabetical order chosen, and becomes the prefix. - include_dir: prefix + include_dir is added to the include directories - library_dir: prefix + library_dir is added to the library directories """ if sys.platform != 'win32': configurations = [] key = (name, eci) try: return _cache[key] except KeyError: last_error = None # Always try the default configuration if {} not in configurations: configurations.append({}) for configuration in configurations: prefix = configuration.get('prefix', '') include_dir = configuration.get('include_dir', '') library_dir = configuration.get('library_dir', '') if prefix and not os.path.isabs(prefix): import glob entries = glob.glob(str(PYPY_EXTERNAL_DIR.join(prefix + '*'))) if entries: # Get last version prefix = sorted(entries)[-1] else: continue include_dir = os.path.join(prefix, include_dir) library_dir = os.path.join(prefix, library_dir) eci_lib = ExternalCompilationInfo( include_dirs=include_dir and [include_dir] or [], library_dirs=library_dir and [library_dir] or [], ) eci_lib = eci_lib.merge(eci) # verify that this eci can be compiled try: verify_eci(eci_lib) except CompilationError, e: last_error = e else: _cache[key] = eci_lib return eci_lib # Nothing found if last_error: raise last_error else: raise CompilationError("Library %s is not installed" % (name,))
from rpython.rlib import jit, rposix from rpython.rlib.rfloat import INFINITY, NAN, isfinite, isinf, isnan from rpython.rlib.rposix import UNDERSCORE_ON_WIN32 from rpython.rtyper.lltypesystem import lltype, rffi from rpython.tool.sourcetools import func_with_new_name from rpython.translator.tool.cbuild import ExternalCompilationInfo from rpython.translator.platform import platform use_library_isinf_isnan = False if sys.platform == "win32": if platform.name == "msvc": # When compiled with /O2 or /Oi (enable intrinsic functions) # It's no more possible to take the address of some math functions. # Ensure that the compiler chooses real functions instead. eci = ExternalCompilationInfo( includes=['math.h', 'float.h'], post_include_bits=['#pragma function(floor)'], ) use_library_isinf_isnan = True else: eci = ExternalCompilationInfo() # Some math functions are C99 and not defined by the Microsoft compiler cdir = py.path.local(cdir) math_eci = ExternalCompilationInfo( include_dirs=[cdir], includes=['src/ll_math.h'], separate_module_files=[cdir.join('src', 'll_math.c')], ) math_prefix = '_pypy_math_' else: eci = ExternalCompilationInfo(libraries=['m']) math_eci = eci
def build(self, option): eci = ExternalCompilationInfo(compile_extra=[option], link_extra=[option]) return self.compiler._build(eci)
from rpython.rlib.rposix_environ import make_env_impls from rpython.rtyper.tool import rffi_platform from rpython.tool.udir import udir from rpython.translator.tool.cbuild import ExternalCompilationInfo from rpython.translator.platform import CompilationError from rpython.rtyper.lltypesystem import lltype, rffi from rpython.rlib.rarithmetic import intmask from rpython.rlib import jit # This module can be imported on any platform, # but most symbols are not usable... WIN32 = os.name == "nt" if WIN32: eci = ExternalCompilationInfo( includes = ['windows.h', 'stdio.h', 'stdlib.h', 'io.h'], libraries = ['kernel32'], ) else: eci = ExternalCompilationInfo() class CConfig: _compilation_info_ = eci if WIN32: DWORD_PTR = rffi_platform.SimpleType("DWORD_PTR", rffi.LONG) WORD = rffi_platform.SimpleType("WORD", rffi.UINT) DWORD = rffi_platform.SimpleType("DWORD", rffi.UINT) BOOL = rffi_platform.SimpleType("BOOL", rffi.LONG) BYTE = rffi_platform.SimpleType("BYTE", rffi.UCHAR) WCHAR = rffi_platform.SimpleType("WCHAR", rffi.UCHAR) INT = rffi_platform.SimpleType("INT", rffi.INT)
_source_code += """ inline void _pypy_init_free(char *p) { free(p); } """ if we_are_translated(): post_include_bits = [] else: # for tests post_include_bits = [ 'RPY_EXPORTED char *_pypy_init_home(void);', 'RPY_EXPORTED void _pypy_init_free(char*);', ] _eci = ExternalCompilationInfo(separate_module_sources=[_source_code], post_include_bits=post_include_bits) _eci = _eci.merge(rdynload.eci) pypy_init_home = rffi.llexternal("_pypy_init_home", [], rffi.CCHARP, _nowrapper=True, compilation_info=_eci) pypy_init_free = rffi.llexternal("_pypy_init_free", [rffi.CCHARP], lltype.Void, _nowrapper=True, compilation_info=_eci)
def setup_class(cls): if cls.runappdirect: _cffi_backend = py.test.importorskip('_cffi_backend') if _cffi_backend.__version__ != TEST_VERSION: py.test.skip( "These tests are for cffi version %s, this Python " "has version %s installed" % (TEST_VERSION, _cffi_backend.__version__)) testfuncs_w = [] keepalive_funcs = [] UniqueCache.for_testing = True def find_and_load_library_for_test(space, w_name, w_is_global=None): if w_is_global is None: w_is_global = space.wrap(0) if space.is_w(w_name, space.w_None): path = None else: import ctypes.util path = ctypes.util.find_library(space.str_w(w_name)) if path is None: py.test.skip("cannot find library '%s'" % (space.str_w(w_name), )) return space.appexec([space.wrap(path), w_is_global], """(path, is_global): import _cffi_backend return _cffi_backend.load_library(path, is_global)""") test_lib_c = tmpdir.join('_test_lib.c') src_test_lib_c = py.path.local(__file__).dirpath().join('_test_lib.c') src_test_lib_c.copy(test_lib_c) eci = ExternalCompilationInfo(include_dirs=[cdir]) test_lib = host.compile([test_lib_c], eci, standalone=False) cdll = ctypes.CDLL(str(test_lib)) cdll.gettestfunc.restype = ctypes.c_void_p def testfunc_for_test(space, w_num): if hasattr(space, 'int_w'): w_num = space.int_w(w_num) addr = cdll.gettestfunc(w_num) return space.wrap(addr) space = cls.space if cls.runappdirect: def interp2app(func): def run(*args): return func(space, *args) return run else: interp2app = gateway.interp2app w_func = space.wrap(interp2app(find_and_load_library_for_test)) w_testfunc = space.wrap(interp2app(testfunc_for_test)) space.appexec([ space.wrap(str(tmpdir)), w_func, w_testfunc, space.wrap(sys.version[:3]) ], """(path, func, testfunc, underlying_version): import sys sys.path.append(path) import _all_test_c _all_test_c.PY_DOT_PY = underlying_version _all_test_c.find_and_load_library = func _all_test_c._testfunc = testfunc """)
class CConfig: _compilation_info_ = ExternalCompilationInfo( includes=['windows.h', 'winbase.h', 'sys/stat.h'], ) WIN32_FIND_DATA = platform.Struct( 'struct _WIN32_FIND_DATA' + suffix, # Only interesting fields [('dwFileAttributes', rwin32.DWORD), ('nFileSizeHigh', rwin32.DWORD), ('nFileSizeLow', rwin32.DWORD), ('ftCreationTime', rwin32.FILETIME), ('ftLastAccessTime', rwin32.FILETIME), ('ftLastWriteTime', rwin32.FILETIME), ('cFileName', lltype.FixedSizeArray(traits.CHAR, 250))]) ERROR_FILE_NOT_FOUND = platform.ConstantInteger('ERROR_FILE_NOT_FOUND') ERROR_NO_MORE_FILES = platform.ConstantInteger('ERROR_NO_MORE_FILES') GetFileExInfoStandard = platform.ConstantInteger( 'GetFileExInfoStandard') FILE_ATTRIBUTE_DIRECTORY = platform.ConstantInteger( 'FILE_ATTRIBUTE_DIRECTORY') FILE_ATTRIBUTE_READONLY = platform.ConstantInteger( 'FILE_ATTRIBUTE_READONLY') INVALID_FILE_ATTRIBUTES = platform.ConstantInteger( 'INVALID_FILE_ATTRIBUTES') ERROR_SHARING_VIOLATION = platform.ConstantInteger( 'ERROR_SHARING_VIOLATION') MOVEFILE_REPLACE_EXISTING = platform.ConstantInteger( 'MOVEFILE_REPLACE_EXISTING') _S_IFDIR = platform.ConstantInteger('_S_IFDIR') _S_IFREG = platform.ConstantInteger('_S_IFREG') _S_IFCHR = platform.ConstantInteger('_S_IFCHR') _S_IFIFO = platform.ConstantInteger('_S_IFIFO') FILE_TYPE_UNKNOWN = platform.ConstantInteger('FILE_TYPE_UNKNOWN') FILE_TYPE_CHAR = platform.ConstantInteger('FILE_TYPE_CHAR') FILE_TYPE_PIPE = platform.ConstantInteger('FILE_TYPE_PIPE') FILE_WRITE_ATTRIBUTES = platform.ConstantInteger( 'FILE_WRITE_ATTRIBUTES') OPEN_EXISTING = platform.ConstantInteger('OPEN_EXISTING') FILE_FLAG_BACKUP_SEMANTICS = platform.ConstantInteger( 'FILE_FLAG_BACKUP_SEMANTICS') VOLUME_NAME_DOS = platform.ConstantInteger('VOLUME_NAME_DOS') VOLUME_NAME_NT = platform.ConstantInteger('VOLUME_NAME_NT') WIN32_FILE_ATTRIBUTE_DATA = platform.Struct( 'WIN32_FILE_ATTRIBUTE_DATA', [('dwFileAttributes', rwin32.DWORD), ('nFileSizeHigh', rwin32.DWORD), ('nFileSizeLow', rwin32.DWORD), ('ftCreationTime', rwin32.FILETIME), ('ftLastAccessTime', rwin32.FILETIME), ('ftLastWriteTime', rwin32.FILETIME)]) BY_HANDLE_FILE_INFORMATION = platform.Struct( 'BY_HANDLE_FILE_INFORMATION', [('dwFileAttributes', rwin32.DWORD), ('ftCreationTime', rwin32.FILETIME), ('ftLastAccessTime', rwin32.FILETIME), ('ftLastWriteTime', rwin32.FILETIME), ('dwVolumeSerialNumber', rwin32.DWORD), ('nFileSizeHigh', rwin32.DWORD), ('nFileSizeLow', rwin32.DWORD), ('nNumberOfLinks', rwin32.DWORD), ('nFileIndexHigh', rwin32.DWORD), ('nFileIndexLow', rwin32.DWORD)])
from rpython.rlib.debug import ll_assert from rpython.rlib.objectmodel import we_are_translated, specialize from rpython.rlib.objectmodel import CDefinedIntSymbolic from rpython.rtyper.lltypesystem.lloperation import llop from rpython.rtyper.tool import rffi_platform from rpython.rtyper.extregistry import ExtRegistryEntry class RThreadError(Exception): pass error = RThreadError translator_c_dir = py.path.local(cdir) eci = ExternalCompilationInfo( includes = ['src/thread.h'], separate_module_files = [translator_c_dir / 'src' / 'thread.c'], include_dirs = [translator_c_dir], ) def llexternal(name, args, result, **kwds): kwds.setdefault('sandboxsafe', True) return rffi.llexternal(name, args, result, compilation_info=eci, **kwds) def _emulated_start_new_thread(func): "NOT_RPYTHON" import thread try: ident = thread.start_new_thread(func, ()) except thread.error: ident = -1
class StreamError(Exception): def __init__(self, message): self.message = message StreamErrors = (OSError, StreamError) # errors that can generally be raised if sys.platform == "win32": from rpython.rlib.rwin32 import BOOL, HANDLE, get_osfhandle from rpython.rlib.rwin32 import GetLastError_saved from rpython.translator.tool.cbuild import ExternalCompilationInfo from rpython.rtyper.lltypesystem import rffi _eci = ExternalCompilationInfo() _setmode = rffi.llexternal('_setmode', [rffi.INT, rffi.INT], rffi.INT, compilation_info=_eci) SetEndOfFile = rffi.llexternal('SetEndOfFile', [HANDLE], BOOL, compilation_info=_eci, save_err=rffi.RFFI_SAVE_LASTERROR) def _setfd_binary(fd): # Allow this to succeed on invalid fd's if rposix.is_valid_fd(fd): _setmode(fd, os.O_BINARY) def ftruncate_win32(fd, size): curpos = os.lseek(fd, 0, 1)
/* Show a dialog box, but in a background thread, and never show multiple dialog boxes at once. */ HANDLE h; _cffi_bootstrap_text = text; h = CreateThread(NULL, 0, _cffi_bootstrap_dialog, NULL, 0, NULL); if (h != NULL) CloseHandle(h); } """ if MESSAGEBOX: eci = ExternalCompilationInfo( separate_module_sources=[MODULE], post_include_bits=["RPY_EXTERN int _cffi_errorbox1(void);\n" "RPY_EXTERN void _cffi_errorbox(char *);\n"]) cffi_errorbox1 = rffi.llexternal("_cffi_errorbox1", [], rffi.INT, compilation_info=eci) cffi_errorbox = rffi.llexternal("_cffi_errorbox", [rffi.CCHARP], lltype.Void, compilation_info=eci) class Message: def __init__(self, space): self.space = space self.text_p = lltype.nullptr(rffi.CCHARP.TO) def start_error_capture(self): ok = cffi_errorbox1() if rffi.cast(lltype.Signed, ok) != 1:
def test_ret_struct_val(self): from rpython.translator.tool.cbuild import ExternalCompilationInfo from rpython.translator.platform import platform from rpython.tool.udir import udir c_file = udir.ensure("test_libffi", dir=1).join("xlib.c") c_file.write( py.code.Source(''' #include "src/precommondefs.h" #include <stdlib.h> #include <stdio.h> struct s2h { short x; short y; }; RPY_EXPORTED struct s2h give(short x, short y) { struct s2h out; out.x = x; out.y = y; return out; } RPY_EXPORTED struct s2h perturb(struct s2h inp) { inp.x *= 2; inp.y *= 3; return inp; } ''')) eci = ExternalCompilationInfo(include_dirs=[cdir]) lib_name = str(platform.compile([c_file], eci, 'x', standalone=False)) lib = CDLL(lib_name) size = ffi_type_sshort.c_size * 2 alignment = ffi_type_sshort.c_alignment tpe = make_struct_ffitype_e(size, alignment, [ffi_type_sshort] * 2) give = lib.getrawpointer('give', [ffi_type_sshort, ffi_type_sshort], tpe.ffistruct) inbuffer = lltype.malloc(rffi.SHORTP.TO, 2, flavor='raw') inbuffer[0] = rffi.cast(rffi.SHORT, 40) inbuffer[1] = rffi.cast(rffi.SHORT, 72) outbuffer = lltype.malloc(rffi.SHORTP.TO, 2, flavor='raw') give.call([ rffi.cast(rffi.VOIDP, inbuffer), rffi.cast(rffi.VOIDP, rffi.ptradd(inbuffer, 1)) ], rffi.cast(rffi.VOIDP, outbuffer)) assert outbuffer[0] == 40 assert outbuffer[1] == 72 perturb = lib.getrawpointer('perturb', [tpe.ffistruct], tpe.ffistruct) inbuffer[0] = rffi.cast(rffi.SHORT, 7) inbuffer[1] = rffi.cast(rffi.SHORT, 11) perturb.call([rffi.cast(rffi.VOIDP, inbuffer)], rffi.cast(rffi.VOIDP, outbuffer)) assert inbuffer[0] == 7 assert inbuffer[1] == 11 assert outbuffer[0] == 14 assert outbuffer[1] == 33 lltype.free(outbuffer, flavor='raw') lltype.free(inbuffer, flavor='raw') del give del perturb lltype.free(tpe, flavor='raw') gc.collect() del lib assert not ALLOCATED
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. import os from rpython.rtyper.lltypesystem import lltype, rffi from rpython.rtyper.tool import rffi_platform as platform from rpython.rlib import rarithmetic, rposix from rpython.translator.tool.cbuild import ExternalCompilationInfo from Builtins import * eci = ExternalCompilationInfo(includes=["stdlib.h"]) system = rffi.llexternal("system", [rffi.CCHARP], rffi.INT, compilation_info=eci) class CConfig: _compilation_info_ = eci cconfig = platform.configure(CConfig) def init(vm): return new_c_con_module(vm, "C_Platform_Exec", "C_Platform_Exec", __file__, import_, \
separate_module_sources=[""" int pypy_vmprof_init(void) { return vmprof_set_mainloop(pypy_execute_frame_trampoline, 0, NULL); } """], ) if DYNAMIC_VMPROF: eci_kwds['libraries'] += ['vmprof'] eci_kwds['link_extra'] = ['-Wl,-rpath,%s' % SRC, '-L%s' % SRC] else: eci_kwds['separate_module_files'] += [SRC.join('vmprof.c')] eci = ExternalCompilationInfo(**eci_kwds) check_eci = eci.merge(ExternalCompilationInfo(separate_module_files=[ SRC.join('fake_pypy_api.c')])) platform.verify_eci(check_eci) pypy_execute_frame_trampoline = rffi.llexternal( "pypy_execute_frame_trampoline", [llmemory.GCREF, llmemory.GCREF, llmemory.GCREF, lltype.Signed], llmemory.GCREF, compilation_info=eci, _nowrapper=True, sandboxsafe=True, random_effects_on_gcobjs=True) pypy_vmprof_init = rffi.llexternal("pypy_vmprof_init", [], rffi.INT,
def test_precompiled_headers(self): if self.platform.cc != 'cl.exe': py.test.skip("Only MSVC profits from precompiled headers") import time tmpdir = udir.join('precompiled_headers').ensure(dir=1) # Create an eci that should not use precompiled headers eci = ExternalCompilationInfo(include_dirs=[tmpdir]) main_c = tmpdir.join('main_no_pch.c') eci.separate_module_files = [main_c] ncfiles = 10 nprecompiled_headers = 20 txt = '' for i in range(ncfiles): txt += "int func%03d();\n" % i txt += "\nint main(int argc, char * argv[])\n" txt += "{\n int i=0;\n" for i in range(ncfiles): txt += " i += func%03d();\n" % i txt += ' printf("%d\\n", i);\n' txt += " return 0;\n};\n" main_c.write(txt) # Create some large headers with dummy functions to be precompiled cfiles_precompiled_headers = [] for i in range(nprecompiled_headers): pch_name =tmpdir.join('pcheader%03d.h' % i) txt = '#ifndef PCHEADER%03d_H\n#define PCHEADER%03d_H\n' %(i, i) for j in range(3000): txt += "int pcfunc%03d_%03d();\n" %(i, j) txt += '#endif' pch_name.write(txt) cfiles_precompiled_headers.append(pch_name) # Create some cfiles with headers we want precompiled cfiles = [] for i in range(ncfiles): c_name =tmpdir.join('implement%03d.c' % i) txt = '' for pch_name in cfiles_precompiled_headers: txt += '#include "%s"\n' % pch_name txt += "int func%03d(){ return %d;};\n" % (i, i) c_name.write(txt) cfiles.append(c_name) if sys.platform == 'win32': clean = ('clean', '', 'for %f in ( $(OBJECTS) $(TARGET) ) do @if exist %f del /f %f') get_time = time.clock else: clean = ('clean', '', 'rm -f $(OBJECTS) $(TARGET) ') get_time = time.time #write a non-precompiled header makefile mk = self.platform.gen_makefile(cfiles, eci, path=tmpdir) mk.rule(*clean) mk.write() t0 = get_time() self.platform.execute_makefile(mk) t1 = get_time() t_normal = t1 - t0 self.platform.execute_makefile(mk, extra_opts=['clean']) # Write a super-duper makefile with precompiled headers mk = self.platform.gen_makefile(cfiles, eci, path=tmpdir, headers_to_precompile=cfiles_precompiled_headers,) mk.rule(*clean) mk.write() t0 = get_time() self.platform.execute_makefile(mk) t1 = get_time() t_precompiled = t1 - t0 res = self.platform.execute(mk.exe_name) self.check_res(res, '%d\n' %sum(range(ncfiles))) print "precompiled haeder 'make' time %.2f, non-precompiled header time %.2f" %(t_precompiled, t_normal) assert t_precompiled < t_normal * 0.5
def test_from_config_tool(self): sdlconfig = py.path.local.sysfind('sdl-config') if not sdlconfig: py.test.skip("sdl-config not installed") eci = ExternalCompilationInfo.from_config_tool('sdl-config') assert 'SDL' in eci.libraries
import py from rpython.rtyper.lltypesystem import lltype, llmemory, rffi, rstr from rpython.translator import cdir from rpython.translator.tool.cbuild import ExternalCompilationInfo cwd = py.path.local(__file__).dirpath() eci = ExternalCompilationInfo( includes=[cwd.join('faulthandler.h')], include_dirs=[str(cwd), cdir], separate_module_files=[cwd.join('faulthandler.c')]) eci_later = eci.merge( ExternalCompilationInfo( pre_include_bits=['#define PYPY_FAULTHANDLER_LATER\n'])) eci_user = eci.merge( ExternalCompilationInfo( pre_include_bits=['#define PYPY_FAULTHANDLER_USER\n'])) def direct_llexternal(*args, **kwargs): kwargs.setdefault('_nowrapper', True) kwargs.setdefault('compilation_info', eci) return rffi.llexternal(*args, **kwargs) DUMP_CALLBACK = lltype.Ptr( lltype.FuncType([rffi.INT, rffi.SIGNEDP, lltype.Signed], lltype.Void)) pypy_faulthandler_setup = direct_llexternal('pypy_faulthandler_setup', [DUMP_CALLBACK], rffi.CCHARP)
from rpython.rlib.rstring import StringBuilder from rpython.rtyper.annlowlevel import llstr from rpython.rtyper.lltypesystem import rffi, lltype from rpython.rtyper.lltypesystem.rstr import copy_string_to_raw from rpython.rtyper.tool import rffi_platform from rpython.translator.platform import platform as compiler, CompilationError from rpython.translator.tool.cbuild import ExternalCompilationInfo if compiler.name == "msvc": libname = 'zlib' # use the static lib, not zlib1 which is dll import lib testonly_libraries = ['zlib1'] else: libname = 'z' testonly_libraries = [] eci = ExternalCompilationInfo(libraries=[libname], includes=['zlib.h'], testonly_libraries=testonly_libraries) eci = rffi_platform.configure_external_library(libname, eci, [ dict(prefix='zlib-'), ]) constantnames = ''' Z_OK Z_STREAM_ERROR Z_BUF_ERROR Z_MEM_ERROR Z_STREAM_END Z_DATA_ERROR Z_DEFLATED Z_DEFAULT_STRATEGY Z_DEFAULT_COMPRESSION Z_NO_FLUSH Z_FINISH Z_SYNC_FLUSH Z_FULL_FLUSH MAX_WBITS MAX_MEM_LEVEL Z_BEST_SPEED Z_BEST_COMPRESSION Z_DEFAULT_COMPRESSION Z_FILTERED Z_HUFFMAN_ONLY Z_DEFAULT_STRATEGY Z_NEED_DICT '''.split()
sys.path.append(os.getenv("PYPY_SRC")) print sys.path try: import pypy except: sys.setrecursionlimit(20000) from rpython.rlib import rarithmetic, rposix from rpython.rlib.jit import * from rpython.rtyper.lltypesystem import lltype, rffi from rpython.rtyper.tool import rffi_platform as platform from rpython.translator.tool.cbuild import ExternalCompilationInfo import os, os.path, sys import Builtins, Bytecode, Config, Stdlib_Modules, VM eci = ExternalCompilationInfo(includes=["limits.h", "stdlib.h", "string.h"]) class CConfig: _compilation_info_ = eci BUFSIZ = platform.DefinedConstantInteger("BUFSIZ") PATH_MAX = platform.DefinedConstantInteger("PATH_MAX") cconfig = platform.configure(CConfig) BUFSIZ = cconfig["BUFSIZ"] PATH_MAX = cconfig["PATH_MAX"] getenv = rffi.llexternal("getenv", [rffi.CCHARP], rffi.CCHARP, compilation_info=eci)
unsigned int i; _ssl_locks_count = CRYPTO_num_locks(); _ssl_locks = calloc(_ssl_locks_count, sizeof(struct RPyOpaque_ThreadLock)); if (_ssl_locks == NULL) return 0; for (i=0; i<_ssl_locks_count; i++) { if (RPyThreadLockInit(_ssl_locks + i) == 0) return 0; } CRYPTO_set_locking_callback(_ssl_thread_locking_function); CRYPTO_set_id_callback(_ssl_thread_id_function); return 1; } """ eci = rthread.eci.merge(ExternalCompilationInfo( separate_module_sources=[separate_module_source], post_include_bits=[ "RPY_EXTERN int _PyPy_SSL_SetupThreads(void);"], libraries = libraries, )) _PyPy_SSL_SetupThreads = rffi.llexternal('_PyPy_SSL_SetupThreads', [], rffi.INT, compilation_info=eci) def setup_ssl_threads(): result = _PyPy_SSL_SetupThreads() if rffi.cast(lltype.Signed, result) == 0: raise MemoryError
from rpython.rlib import rwin32 from rpython.rtyper.lltypesystem import rffi, lltype from rpython.rtyper.tool import rffi_platform from rpython.translator.tool.cbuild import ExternalCompilationInfo from pypy.interpreter.gateway import unwrap_spec from pypy.interpreter.error import wrap_windowserror from rpython.rlib.rarithmetic import intmask eci = ExternalCompilationInfo( includes=['windows.h', 'wincrypt.h'], libraries=['crypt32'], ) class CConfig: _compilation_info_ = eci X509_ASN_ENCODING = rffi_platform.ConstantInteger('X509_ASN_ENCODING') PKCS_7_ASN_ENCODING = rffi_platform.ConstantInteger('PKCS_7_ASN_ENCODING') CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG = rffi_platform.ConstantInteger( 'CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG') CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG = rffi_platform.ConstantInteger( 'CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG') CRYPT_E_NOT_FOUND = rffi_platform.ConstantInteger('CRYPT_E_NOT_FOUND') CERT_ENHKEY_USAGE = rffi_platform.Struct( 'CERT_ENHKEY_USAGE', [('cUsageIdentifier', rwin32.DWORD), ('rgpszUsageIdentifier', rffi.CCHARPP)]) CERT_CONTEXT = rffi_platform.Struct('CERT_CONTEXT', [('pbCertEncoded', rffi.CCHARP), ('cbCertEncoded', rwin32.DWORD), ('dwCertEncodingType', rwin32.DWORD)])
def get_eci(self): pypy_include_dir = py.path.local(__file__).join('..') include_dirs = [pypy_include_dir] return ExternalCompilationInfo(include_dirs=include_dirs)
eci = ExternalCompilationInfo(post_include_bits=[ """ #ifndef __event_filter_h #define __event_filter_h #ifdef _WIN32 #define DLLEXPORT __declspec(dllexport) #else #define DLLEXPORT __attribute__((__visibility__("default"))) #endif #ifdef __cplusplus extern "C" { #endif DLLEXPORT int SetEventFilter(intptr_t* target); #ifdef __cplusplus } #endif #endif""" ], separate_module_sources=[ """ int InterruptEventFilter(void* userdata, SDL_Event *event) { int interrupt_key = 15 << 8; if (event->type == SDL_KEYDOWN || event->type == SDL_KEYUP) { if (((SDL_KeyboardEvent*)event)->keysym.sym == SDLK_PERIOD) { if ((((SDL_KeyboardEvent*)event)->keysym.mod & (KMOD_ALT|KMOD_GUI)) != 0) { if (event->type == SDL_KEYUP) { // only keyup generates the interrupt ((intptr_t*)userdata)[0] = 1; // an interrupt flushes all pending events preceding it, so we don't // get spurious events processing when the debugger opens SDL_FlushEvents(SDL_FIRSTEVENT, SDL_LASTEVENT); } return 0; } } } return 1; } int SetEventFilter(intptr_t* target) { SDL_SetEventFilter(InterruptEventFilter, (void*)target); return 0; } """ ]).merge(get_rsdl_compilation_info())
from rpython.translator.platform import platform import sys import weakref import py if sys.platform == "win32": libname = 'libexpat' pre_include_bits = ["#define XML_STATIC"] else: libname = 'expat' pre_include_bits = [] eci = ExternalCompilationInfo( libraries=[libname], library_dirs=platform.preprocess_library_dirs([]), includes=['expat.h'], include_dirs=platform.preprocess_include_dirs([]), pre_include_bits=pre_include_bits, ) 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",
void asmbuf_free(void* buf, size_t size) { (void)(size); VirtualFree(buf, 0, MEM_RELEASE); } ''' if sys.platform == "win32": MMAN_ASMBUF_C = MMAN_ASMBUF_C_WIN32 else: MMAN_ASMBUF_C = MMAN_ASMBUF_C_UNIX asmbuf_eci = ExternalCompilationInfo( separate_module_sources=[MMAN_ASMBUF_C], post_include_bits=[ 'RPY_EXTERN size_t asmbuf_get_pagesize();\n' 'RPY_EXTERN void* asmbuf_create(size_t);\n' 'RPY_EXTERN void asmbuf_finalize(void*, size_t);\n' 'RPY_EXTERN void asmbuf_free(void*, size_t);\n' ]) asmbuf_get_pagesize = rffi.llexternal("asmbuf_get_pagesize", [], rffi.SIZE_T, compilation_info=asmbuf_eci) asmbuf_create = rffi.llexternal("asmbuf_create", [rffi.SIZE_T], rffi.VOIDP, compilation_info=asmbuf_eci) asmbuf_finalize = rffi.llexternal("asmbuf_finalize", [rffi.VOIDP, rffi.SIZE_T], lltype.Void, compilation_info=asmbuf_eci)
from rpython.translator.tool.cbuild import ExternalCompilationInfo from rpython.rtyper.tool import rffi_platform as platform from rpython.rtyper.lltypesystem import rffi, lltype from rpython.rlib.rarithmetic import intmask eci = ExternalCompilationInfo(includes=['glob.h']) class CConfig: _compilation_info_ = eci glob_t = platform.Struct('glob_t', [ ('gl_pathc', lltype.Unsigned), ('gl_pathv', rffi.CCHARPP), ('gl_offs', lltype.Unsigned), ]) globals().update(platform.configure(CConfig)) def external(name, args, result): return rffi.llexternal(name, args, result, compilation_info=eci, releasegil=False) callback = lltype.Ptr(lltype.FuncType([rffi.CCHARP, rffi.INT], rffi.INT)) PTR_GLOB_T = lltype.Ptr(glob_t)
if not _WIN32: includes = ['ffi.h'] if _MAC_OS: pre_include_bits = ['#define MACOSX'] else: pre_include_bits = [] libraries = ['ffi'] link_files = [] eci = ExternalCompilationInfo( pre_include_bits=pre_include_bits, includes=includes, libraries=libraries, separate_module_sources=separate_module_sources, include_dirs=platform.include_dirs_for_libffi(), library_dirs=platform.library_dirs_for_libffi(), link_files=link_files, testonly_libraries=['ffi'], ) elif _MINGW: includes = ['ffi.h'] libraries = ['libffi-5'] eci = ExternalCompilationInfo( libraries=libraries, includes=includes, separate_module_sources=separate_module_sources, ) eci = rffi_platform.configure_external_library('ffi-5', eci, [
import py from rpython.rtyper.lltypesystem import lltype, llmemory, rffi from rpython.translator.tool.cbuild import ExternalCompilationInfo from rpython.rtyper.tool import rffi_platform from rpython.rlib.rarithmetic import is_emulated_long from rpython.translator import cdir cdir = py.path.local(cdir) eci = ExternalCompilationInfo( include_dirs = [cdir], includes = ['src/stacklet/stacklet.h'], separate_module_files = [cdir / 'src' / 'stacklet' / 'stacklet.c'], ) if 'masm' in dir(eci.platform): # Microsoft compiler if is_emulated_long: asmsrc = 'switch_x64_msvc.asm' else: asmsrc = 'switch_x86_msvc.asm' eci.separate_module_files += (cdir / 'src' / 'stacklet' / asmsrc, ) 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)
OperationError, exception_from_saved_errno, oefmt, wrap_oserror) from pypy.interpreter.gateway import unwrap_spec from pypy.module.posix.interp_posix import run_fork_hooks thisdir = py.path.local(__file__).dirpath() class CConfig: _compilation_info_ = ExternalCompilationInfo( includes=['unistd.h', 'sys/syscall.h']) HAVE_SYS_SYSCALL_H = platform.Has("syscall") HAVE_SETSID = platform.Has("setsid") config = platform.configure(CConfig) eci = ExternalCompilationInfo( includes=[thisdir.join('_posixsubprocess.h')], include_dirs=[str(thisdir), cdir], separate_module_files=[thisdir.join('_posixsubprocess.c')]) compile_extra = [] if config['HAVE_SYS_SYSCALL_H']: compile_extra.append("-DHAVE_SYS_SYSCALL_H") if config['HAVE_SETSID']: compile_extra.append("-DHAVE_SETSID") eci = eci.merge( ExternalCompilationInfo( compile_extra=compile_extra)) c_child_exec = rffi.llexternal( 'pypy_subprocess_child_exec', [rffi.CCHARPP, rffi.CCHARPP, rffi.CCHARPP, rffi.CCHARP,
else: includes = ['dlfcn.h'] if _MAC_OS: pre_include_bits = ['#define MACOSX'] else: pre_include_bits = [] if _FREEBSD or _NETBSD or _WIN32: libraries = [] else: libraries = ['dl'] eci = ExternalCompilationInfo( pre_include_bits=pre_include_bits, includes=includes, libraries=libraries, ) class CConfig: _compilation_info_ = eci RTLD_LOCAL = rffi_platform.DefinedConstantInteger('RTLD_LOCAL') RTLD_GLOBAL = rffi_platform.DefinedConstantInteger('RTLD_GLOBAL') RTLD_NOW = rffi_platform.DefinedConstantInteger('RTLD_NOW') RTLD_LAZY = rffi_platform.DefinedConstantInteger('RTLD_LAZY') RTLD_NODELETE = rffi_platform.DefinedConstantInteger('RTLD_NODELETE') RTLD_NOLOAD = rffi_platform.DefinedConstantInteger('RTLD_NOLOAD') RTLD_DEEPBIND = rffi_platform.DefinedConstantInteger('RTLD_DEEPBIND')
#include <string.h> #include <stdio.h> #include <stdlib.h> RPY_EXPORTED char *_pypy_init_home(void) { Dl_info info; dlerror(); /* reset */ if (dladdr(&_pypy_init_home, &info) == 0) { fprintf(stderr, "PyPy initialization: dladdr() failed: %s\n", dlerror()); return NULL; } char *p = realpath(info.dli_fname, NULL); if (p == NULL) { p = strdup(info.dli_fname); } return p; } """ _eci = ExternalCompilationInfo(separate_module_sources=[_source_code], post_include_bits=['RPY_EXPORTED char *_pypy_init_home(void);']) _eci = _eci.merge(rdynload.eci) pypy_init_home = rffi.llexternal("_pypy_init_home", [], rffi.CCHARP, _nowrapper=True, compilation_info=_eci) pypy_init_free = rffi.llexternal("free", [rffi.CCHARP], lltype.Void, _nowrapper=True, compilation_info=_eci)
class CConfig: _compilation_info_ = ExternalCompilationInfo(includes=["float.h"])
need_rusage = False else: TIME_H = 'sys/time.h' FTIME = 'ftime' STRUCT_TIMEB = 'struct timeb' includes = [TIME_H, 'time.h', 'errno.h', 'sys/select.h', 'sys/types.h', 'unistd.h', 'sys/time.h', 'sys/resource.h'] if not sys.platform.startswith("openbsd"): includes.append('sys/timeb.h') need_rusage = True eci = ExternalCompilationInfo(includes=includes) class CConfig: _compilation_info_ = eci TIMEVAL = rffi_platform.Struct('struct timeval', [('tv_sec', rffi.INT), ('tv_usec', rffi.INT)]) HAVE_GETTIMEOFDAY = rffi_platform.Has('gettimeofday') HAVE_FTIME = rffi_platform.Has(FTIME) if need_rusage: RUSAGE = rffi_platform.Struct('struct rusage', [('ru_utime', TIMEVAL), ('ru_stime', TIMEVAL)]) if sys.platform.startswith('freebsd') or sys.platform.startswith('netbsd'): libraries = ['compat'] elif sys.platform == 'linux2': libraries = ['rt']
class CConfig: _compilation_info_ = ExternalCompilationInfo(includes=['float.h']) DBL_MAX = rffi_platform.DefinedConstantDouble('DBL_MAX') DBL_MIN = rffi_platform.DefinedConstantDouble('DBL_MIN') DBL_MANT_DIG = rffi_platform.ConstantInteger('DBL_MANT_DIG')
from __future__ import with_statement from rpython.rtyper.lltypesystem import lltype, rffi from rpython.rtyper.tool import rffi_platform as platform from rpython.translator.tool.cbuild import ExternalCompilationInfo from rpython.rlib.rarithmetic import intmask from rpython.rlib import rwin32 eci = ExternalCompilationInfo( includes = ['windows.h', ], libraries = ('Advapi32', 'kernel32') ) class CConfig: _compilation_info_ = eci constant_names = ''' KEY_QUERY_VALUE KEY_SET_VALUE KEY_CREATE_SUB_KEY KEY_ENUMERATE_SUB_KEYS KEY_NOTIFY KEY_CREATE_LINK KEY_READ KEY_WRITE KEY_EXECUTE KEY_ALL_ACCESS KEY_WOW64_64KEY KEY_WOW64_32KEY REG_OPTION_RESERVED REG_OPTION_NON_VOLATILE REG_OPTION_VOLATILE REG_OPTION_CREATE_LINK REG_OPTION_BACKUP_RESTORE REG_OPTION_OPEN_LINK REG_LEGAL_OPTION REG_CREATED_NEW_KEY REG_OPENED_EXISTING_KEY REG_WHOLE_HIVE_VOLATILE REG_REFRESH_HIVE REG_NO_LAZY_FLUSH REG_NOTIFY_CHANGE_NAME REG_NOTIFY_CHANGE_ATTRIBUTES REG_NOTIFY_CHANGE_LAST_SET REG_NOTIFY_CHANGE_SECURITY REG_LEGAL_CHANGE_FILTER REG_NONE REG_SZ REG_EXPAND_SZ REG_BINARY REG_DWORD REG_DWORD_LITTLE_ENDIAN REG_DWORD_BIG_ENDIAN REG_LINK REG_MULTI_SZ REG_RESOURCE_LIST REG_FULL_RESOURCE_DESCRIPTOR REG_RESOURCE_REQUIREMENTS_LIST HKEY_LOCAL_MACHINE HKEY_CLASSES_ROOT HKEY_CURRENT_CONFIG HKEY_CURRENT_USER HKEY_DYN_DATA HKEY_LOCAL_MACHINE HKEY_PERFORMANCE_DATA HKEY_USERS
def llexternal(name, args, result, _callable=None, compilation_info=ExternalCompilationInfo(), sandboxsafe=False, releasegil='auto', _nowrapper=False, calling_conv='c', elidable_function=False, macro=None, random_effects_on_gcobjs='auto', save_err=RFFI_ERR_NONE): """Build an external function that will invoke the C function 'name' with the given 'args' types and 'result' type. You get by default a wrapper that casts between number types as needed to match the arguments. You can also pass an RPython string when a CCHARP argument is expected, and the C function receives a 'const char*' pointing to a read-only null-terminated character of arrays, as usual for C. The C function can have callbacks, but they must be specified explicitly as constant RPython functions. We don't support yet C functions that invoke callbacks passed otherwise (e.g. set by a previous C call). releasegil: whether it's ok to release the GIL around the call. Default is yes, unless sandboxsafe is set, in which case we consider that the function is really short-running and don't bother releasing the GIL. An explicit True or False overrides this logic. """ if _callable is not None: assert callable(_callable) ext_type = lltype.FuncType(args, result) if _callable is None: if macro is not None: if macro is True: macro = name _callable = generate_macro_wrapper( name, macro, ext_type, compilation_info) else: _callable = ll2ctypes.LL2CtypesCallable(ext_type, calling_conv) else: assert macro is None, "'macro' is useless if you specify '_callable'" if elidable_function: _callable._elidable_function_ = True kwds = {} has_callback = False for ARG in args: if _isfunctype(ARG): has_callback = True if has_callback: kwds['_callbacks'] = callbackholder = CallbackHolder() else: callbackholder = None if releasegil in (False, True): # invoke the around-handlers, which release the GIL, if and only if # the C function is thread-safe. invoke_around_handlers = releasegil else: # default case: # invoke the around-handlers only for "not too small" external calls; # sandboxsafe is a hint for "too-small-ness" (e.g. math functions). # Also, _nowrapper functions cannot release the GIL, by default. invoke_around_handlers = not sandboxsafe and not _nowrapper if random_effects_on_gcobjs not in (False, True): random_effects_on_gcobjs = ( invoke_around_handlers or # because it can release the GIL has_callback) # because the callback can do it assert not (elidable_function and random_effects_on_gcobjs) funcptr = lltype.functionptr(ext_type, name, external='C', compilation_info=compilation_info, _callable=_callable, _safe_not_sandboxed=sandboxsafe, _debugexc=True, # on top of llinterp canraise=False, random_effects_on_gcobjs= random_effects_on_gcobjs, calling_conv=calling_conv, **kwds) if isinstance(_callable, ll2ctypes.LL2CtypesCallable): _callable.funcptr = funcptr if _nowrapper: assert save_err == RFFI_ERR_NONE return funcptr if invoke_around_handlers: # The around-handlers are releasing the GIL in a threaded pypy. # We need tons of care to ensure that no GC operation and no # exception checking occurs while the GIL is released. # The actual call is done by this small piece of non-inlinable # generated code in order to avoid seeing any GC pointer: # neither '*args' nor the GC objects originally passed in as # argument to wrapper(), if any (e.g. RPython strings). argnames = ', '.join(['a%d' % i for i in range(len(args))]) source = py.code.Source(""" from rpython.rlib import rgil def call_external_function(%(argnames)s): rgil.release() # NB. it is essential that no exception checking occurs here! if %(save_err)d: from rpython.rlib import rposix rposix._errno_before(%(save_err)d) res = funcptr(%(argnames)s) if %(save_err)d: from rpython.rlib import rposix rposix._errno_after(%(save_err)d) rgil.acquire() return res """ % locals()) miniglobals = {'funcptr': funcptr, '__name__': __name__, # for module name propagation } exec source.compile() in miniglobals call_external_function = miniglobals['call_external_function'] call_external_function._dont_inline_ = True call_external_function._annspecialcase_ = 'specialize:ll' call_external_function._gctransformer_hint_close_stack_ = True # # '_call_aroundstate_target_' is used by the JIT to generate a # CALL_RELEASE_GIL directly to 'funcptr'. This doesn't work if # 'funcptr' might be a C macro, though. if macro is None: call_external_function._call_aroundstate_target_ = funcptr, save_err # call_external_function = func_with_new_name(call_external_function, 'ccall_' + name) # don't inline, as a hack to guarantee that no GC pointer is alive # anywhere in call_external_function else: # if we don't have to invoke the GIL handling, we can just call # the low-level function pointer carelessly if macro is None and save_err == RFFI_ERR_NONE: call_external_function = funcptr else: # ...well, unless it's a macro, in which case we still have # to hide it from the JIT... argnames = ', '.join(['a%d' % i for i in range(len(args))]) source = py.code.Source(""" def call_external_function(%(argnames)s): if %(save_err)d: from rpython.rlib import rposix rposix._errno_before(%(save_err)d) res = funcptr(%(argnames)s) if %(save_err)d: from rpython.rlib import rposix rposix._errno_after(%(save_err)d) return res """ % locals()) miniglobals = {'funcptr': funcptr, '__name__': __name__, } exec source.compile() in miniglobals call_external_function = miniglobals['call_external_function'] call_external_function = func_with_new_name(call_external_function, 'ccall_' + name) call_external_function = jit.dont_look_inside( call_external_function) unrolling_arg_tps = unrolling_iterable(enumerate(args)) def wrapper(*args): real_args = () to_free = () for i, TARGET in unrolling_arg_tps: arg = args[i] freeme = None if TARGET == CCHARP: if arg is None: arg = lltype.nullptr(CCHARP.TO) # None => (char*)NULL freeme = arg elif isinstance(arg, str): arg = str2charp(arg) # XXX leaks if a str2charp() fails with MemoryError # and was not the first in this function freeme = arg elif TARGET == CWCHARP: if arg is None: arg = lltype.nullptr(CWCHARP.TO) # None => (wchar_t*)NULL freeme = arg elif isinstance(arg, unicode): arg = unicode2wcharp(arg) # XXX leaks if a unicode2wcharp() fails with MemoryError # and was not the first in this function freeme = arg elif TARGET is VOIDP: if arg is None: arg = lltype.nullptr(VOIDP.TO) elif isinstance(arg, str): arg = str2charp(arg) freeme = arg elif isinstance(arg, unicode): arg = unicode2wcharp(arg) freeme = arg elif _isfunctype(TARGET) and not _isllptr(arg): # XXX pass additional arguments use_gil = invoke_around_handlers arg = llhelper(TARGET, _make_wrapper_for(TARGET, arg, callbackholder, use_gil)) else: SOURCE = lltype.typeOf(arg) if SOURCE != TARGET: if TARGET is lltype.Float: arg = float(arg) elif ((isinstance(SOURCE, lltype.Number) or SOURCE is lltype.Bool) and (isinstance(TARGET, lltype.Number) or TARGET is lltype.Bool)): arg = cast(TARGET, arg) real_args = real_args + (arg,) to_free = to_free + (freeme,) res = call_external_function(*real_args) for i, TARGET in unrolling_arg_tps: if to_free[i]: lltype.free(to_free[i], flavor='raw') if rarithmetic.r_int is not r_int: if result is INT: return cast(lltype.Signed, res) elif result is UINT: return cast(lltype.Unsigned, res) return res wrapper._annspecialcase_ = 'specialize:ll' wrapper._always_inline_ = 'try' # for debugging, stick ll func ptr to that wrapper._ptr = funcptr wrapper = func_with_new_name(wrapper, name) if calling_conv != "c": wrapper = jit.dont_look_inside(wrapper) return wrapper
#else pcre_free(x); #endif pcre_free(p); } pcre_extra* hippy_pcre_extra_malloc() { pcre_extra* res; res = (pcre_extra*)pcre_malloc(sizeof(pcre_extra)); memset((void*)res, 0, sizeof(pcre_extra)); return res; } """ eci = ExternalCompilationInfo(includes=includes, libraries=libraries, post_include_bits=post_include_bits, separate_module_sources=[source]) def llexternal(*args, **kwds): kwds['compilation_info'] = eci return rffi.llexternal(*args, **kwds) # ____________________________________________________________ class CConfig: _compilation_info_ = eci pcre_extra = platform.Struct('pcre_extra', [
import pixie.vm.libs.ffi as ffi import rpython.rlib.rgc as rgc pkgpath = py.path.local(__file__).dirpath() srcpath = pkgpath.join("c") shutil.copyfile(str(srcpath / "uv_ffi.c"), str(udir.udir / "uv_ffi.c")) shutil.copyfile(str(srcpath / "uv_ffi.h"), str(udir.udir / "uv_ffi.h")) compilation_info = ExternalCompilationInfo( includes=['uv.h', "ffi.h", "uv_ffi.h"], include_dirs=[srcpath], libraries=["uv", "ffi"], separate_module_files=[udir.udir / "uv_ffi.c"]).merge(ExternalCompilationInfo.from_pkg_config("libffi")) def llexternal(*args, **kwargs): return rffi.llexternal(*args, compilation_info=compilation_info, **kwargs) uv_work = rffi_platform.Struct("uv_work_t", [("data", rffi.VOIDP)]) uv_timer_t = rffi.COpaque("uv_timer_t", compilation_info=compilation_info) uv_baton_t = rffi.COpaque("work_baton_t", compilation_info=compilation_info) uv_timer = lltype.Ptr(uv_timer_t) uv_timer_cb = lltype.Ptr(lltype.FuncType([uv_timer, rffi.INT], lltype.Void))
def build_winerror_to_errno(): """Build a dictionary mapping windows error numbers to POSIX errno. The function returns the dict, and the default value for codes not in the dict.""" # Prior to Visual Studio 8, the MSVCRT dll doesn't export the # _dosmaperr() function, which is available only when compiled # against the static CRT library. from rpython.translator.platform import host_factory static_platform = host_factory() if static_platform.name == 'msvc': static_platform.cflags = ['/MT'] # static CRT static_platform.version = 0 # no manifest cfile = udir.join('dosmaperr.c') cfile.write(r''' #include <errno.h> #include <WinError.h> #include <stdio.h> #ifdef __GNUC__ #define _dosmaperr mingw_dosmaperr #endif int main() { int i; for(i=1; i < 65000; i++) { _dosmaperr(i); if (errno == EINVAL) { /* CPython issue #12802 */ if (i == ERROR_DIRECTORY) errno = ENOTDIR; else continue; } printf("%d\t%d\n", i, errno); } return 0; }''') try: exename = static_platform.compile( [cfile], ExternalCompilationInfo(), outputfilename = "dosmaperr", standalone=True) except (CompilationError, WindowsError): # Fallback for the mingw32 compiler assert static_platform.name == 'mingw32' errors = { 2: 2, 3: 2, 4: 24, 5: 13, 6: 9, 7: 12, 8: 12, 9: 12, 10: 7, 11: 8, 15: 2, 16: 13, 17: 18, 18: 2, 19: 13, 20: 13, 21: 13, 22: 13, 23: 13, 24: 13, 25: 13, 26: 13, 27: 13, 28: 13, 29: 13, 30: 13, 31: 13, 32: 13, 33: 13, 34: 13, 35: 13, 36: 13, 53: 2, 65: 13, 67: 2, 80: 17, 82: 13, 83: 13, 89: 11, 108: 13, 109: 32, 112: 28, 114: 9, 128: 10, 129: 10, 130: 9, 132: 13, 145: 41, 158: 13, 161: 2, 164: 11, 167: 13, 183: 17, 188: 8, 189: 8, 190: 8, 191: 8, 192: 8, 193: 8, 194: 8, 195: 8, 196: 8, 197: 8, 198: 8, 199: 8, 200: 8, 201: 8, 202: 8, 206: 2, 215: 11, 267: 20, 1816: 12, } else: output = os.popen(str(exename)) errors = dict(map(int, line.split()) for line in output) return errors, errno.EINVAL
import py from rpython.rtyper.lltypesystem import lltype, llmemory, rffi, rstr from rpython.translator import cdir from rpython.translator.tool.cbuild import ExternalCompilationInfo cwd = py.path.local(__file__).dirpath() eci = ExternalCompilationInfo( includes=[cwd.join('faulthandler.h')], include_dirs=[str(cwd), cdir], separate_module_files=[cwd.join('faulthandler.c')]) eci_later = eci.merge(ExternalCompilationInfo( pre_include_bits=['#define PYPY_FAULTHANDLER_LATER\n'])) eci_user = eci.merge(ExternalCompilationInfo( pre_include_bits=['#define PYPY_FAULTHANDLER_USER\n'])) def direct_llexternal(*args, **kwargs): kwargs.setdefault('_nowrapper', True) kwargs.setdefault('compilation_info', eci) return rffi.llexternal(*args, **kwargs) DUMP_CALLBACK = lltype.Ptr(lltype.FuncType( [rffi.INT, rffi.SIGNEDP, lltype.Signed], lltype.Void)) pypy_faulthandler_setup = direct_llexternal( 'pypy_faulthandler_setup', [DUMP_CALLBACK], rffi.CCHARP) pypy_faulthandler_teardown = direct_llexternal( 'pypy_faulthandler_teardown', [], lltype.Void)
include_dirs = platform.include_dirs_for_openssl() library_dirs = platform.library_dirs_for_openssl() includes += [ 'openssl/ssl.h', 'openssl/err.h', 'openssl/rand.h', 'openssl/evp.h', 'openssl/ossl_typ.h', 'openssl/x509v3.h', 'openssl/comp.h' ] eci = ExternalCompilationInfo( libraries=libraries, includes=includes, library_dirs=library_dirs, include_dirs=include_dirs, post_include_bits=[ # Unnamed structures are not supported by rffi_platform. # So we replace an attribute access with a macro call. '#define pypy_GENERAL_NAME_dirn(name) (name->d.dirn)', '#define pypy_GENERAL_NAME_uri(name) (name->d.uniformResourceIdentifier)', '#define pypy_GENERAL_NAME_pop_free(names) (sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free))', '#define pypy_X509_OBJECT_data_x509(obj) (obj->data.x509)', '#define pypy_DIST_POINT_fullname(obj) (obj->distpoint->name.fullname)', ], ) eci = rffi_platform.configure_external_library('openssl', eci, [ dict(prefix='openssl-', include_dir='inc32', library_dir='out32'), ]) ASN1_STRING = lltype.Ptr(lltype.ForwardReference()) ASN1_IA5STRING = ASN1_STRING ASN1_ITEM = rffi.COpaquePtr('ASN1_ITEM')