def try_compile_cache(c_files, eci): "Try to compile a program. Cache success, and error message on failure" # Import 'platform' every time, the compiler may have been changed from rpython.translator.platform import platform, CompilationError path = cache_file_path(c_files, eci, 'try_compile_cache') try: data = path.read() if data == 'True': return True else: raise CompilationError(data, '') except py.error.Error: pass # _previous = platform.log_errors try: platform.log_errors = False platform.compile(c_files, eci) except CompilationError as e: msg = e.out + e.err if msg != 'True': try_atomic_write(path, msg) raise finally: del platform.log_errors # ^^^remove from the instance --- needed so that it can # compare equal to another instance without it if platform.log_errors != _previous: platform.log_errors = _previous try_atomic_write(path, "True") return True
def try_compile_cache(c_files, eci): "Try to compile a program. If it works, caches this fact." # Import 'platform' every time, the compiler may have been changed from rpython.translator.platform import platform path = cache_file_path(c_files, eci, 'try_compile_cache') try: data = path.read() if data == 'True': return True except py.error.Error: pass # _previous = platform.log_errors try: platform.log_errors = False platform.compile(c_files, eci) # ^^^ may raise CompilationError. We don't cache such results. finally: del platform.log_errors # ^^^remove from the instance --- needed so that it can # compare equal to another instance without it if platform.log_errors != _previous: platform.log_errors = _previous path.write('True') return True
def test_cdll_life_time(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(''' long fun(long i) { return i + 42; } ''')) eci = ExternalCompilationInfo(export_symbols=['fun']) lib_name = str(platform.compile([c_file], eci, 'x', standalone=False)) lib = CDLL(lib_name) slong = cast_type_to_ffitype(rffi.LONG) fun = lib.getrawpointer('fun', [slong], slong) del lib # already delete here buffer = lltype.malloc(rffi.LONGP.TO, 2, flavor='raw') buffer[0] = 200 buffer[1] = -1 fun.call([rffi.cast(rffi.VOIDP, buffer)], rffi.cast(rffi.VOIDP, rffi.ptradd(buffer, 1))) assert buffer[1] == 242 lltype.free(buffer, flavor='raw') del fun assert not ALLOCATED
def test_cdll_life_time(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" RPY_EXPORTED long fun(long i) { return i + 42; } ''')) eci = ExternalCompilationInfo(include_dirs=[cdir]) lib_name = str(platform.compile([c_file], eci, 'x', standalone=False)) lib = CDLL(lib_name) slong = cast_type_to_ffitype(rffi.LONG) fun = lib.getrawpointer('fun', [slong], slong) del lib # already delete here buffer = lltype.malloc(rffi.LONGP.TO, 2, flavor='raw') buffer[0] = 200 buffer[1] = -1 fun.call([rffi.cast(rffi.VOIDP, buffer)], rffi.cast(rffi.VOIDP, rffi.ptradd(buffer, 1))) assert buffer[1] == 242 lltype.free(buffer, flavor='raw') del fun gc.collect() assert not ALLOCATED
def setup_class(cls): from rpython.tool.udir import udir from rpython.translator.tool.cbuild import ExternalCompilationInfo from rpython.translator.tool.cbuild import STANDARD_DEFINES from rpython.translator.platform import platform BaseFfiTest.setup_class() # prepare C code as an example, so we can load it and call # it via rlib.libffi c_file = udir.ensure("test_libffi", dir=1).join("foolib.c") # automatically collect the C source from the docstrings of the tests snippets = [] exports = [] for name in dir(cls): if name.startswith('test_'): meth = getattr(cls, name) # the heuristic to determine it it's really C code could be # improved: so far we just check that there is a '{' :-) if meth.__doc__ is not None and '{' in meth.__doc__: snippets.append(meth.__doc__) import re for match in re.finditer(" ([A-Za-z_]+)\(", meth.__doc__): exports.append(match.group(1)) # c_file.write(STANDARD_DEFINES + str(py.code.Source('\n'.join(snippets)))) eci = ExternalCompilationInfo(export_symbols=exports) cls.libfoo_name = str(platform.compile([c_file], eci, 'x', standalone=False)) cls.dll = cls.CDLL(cls.libfoo_name)
def build_executable_cache(c_files, eci, ignore_errors=False): "Builds and run a program; caches the result" # Import 'platform' every time, the compiler may have been changed from rpython.translator.platform import platform path = cache_file_path(c_files, eci, 'build_executable_cache') try: return path.read() except py.error.Error: _previous = platform.log_errors try: if ignore_errors: platform.log_errors = False result = platform.execute(platform.compile(c_files, eci)) if result.err: sys.stderr.write(result.err) finally: if ignore_errors: del platform.log_errors # ^^^remove from the instance --- needed so that it can # compare equal to another instance without it if platform.log_errors != _previous: platform.log_errors = _previous if not result.err: try_atomic_write(path, result.out) return result.out
def prepare_c_example(cls): from rpython.tool.udir import udir from rpython.translator.tool.cbuild import ExternalCompilationInfo from rpython.translator.platform import platform c_file = udir.ensure("test__ffi", dir=1).join("foolib.c") # automatically collect the C source from the docstrings of the tests snippets = [ """ #ifdef _WIN32 #define DLLEXPORT __declspec(dllexport) #else #define DLLEXPORT #endif """ ] for name in dir(cls): if name.startswith('test_'): meth = getattr(cls, name) # the heuristic to determine it it's really C code could be # improved: so far we just check that there is a '{' :-) if meth.__doc__ is not None and '{' in meth.__doc__: snippets.append(meth.__doc__) # c_file.write(py.code.Source('\n'.join(snippets))) eci = ExternalCompilationInfo(export_symbols=[]) return str(platform.compile([c_file], eci, 'x', standalone=False))
def setup_class(cls): import ctypes from rpython.tool.udir import udir from rpython.translator.platform import platform from rpython.translator.tool.cbuild import ExternalCompilationInfo if platform.name == 'msvc': export = '__declspec(dllexport) ' else: export = '' c_source = """ {0} void *int_to_void_p(int arg) {{}} {0} struct random_strucutre {{ int one; int *two; }}; {0} struct random_structure* int_int_to_struct_p(int one, int two) {{}} """.format(export) c_file = udir.join('rffilib.c') c_file.write(c_source) libname = platform.compile([c_file], ExternalCompilationInfo(), standalone=False) cls.lib = ctypes.CDLL(str(libname))
def pytest_configure(config): if py.path.local.sysfind('genreflex') is None: import pypy.module.cppyy.capi.loadable_capi as lcapi try: import ctypes ctypes.CDLL(lcapi.reflection_library) except Exception, e: if config.option.runappdirect: return # "can't run dummy tests in -A" # build dummy backend (which has reflex info and calls hard-wired) import os from rpython.translator.tool.cbuild import ExternalCompilationInfo from rpython.translator.platform import platform from rpython.rtyper.lltypesystem import rffi pkgpath = py.path.local(__file__).dirpath().join(os.pardir) srcpath = pkgpath.join('src') incpath = pkgpath.join('include') tstpath = pkgpath.join('test') eci = ExternalCompilationInfo( separate_module_files=[srcpath.join('dummy_backend.cxx')], include_dirs=[incpath, tstpath], use_cpp_linker=True, ) soname = platform.compile( [], eci, outputfilename='libcppyy_dummy_backend', standalone=False) lcapi.reflection_library = str(soname)
def setup_class(cls): from rpython.tool.udir import udir from rpython.translator.tool.cbuild import ExternalCompilationInfo from rpython.translator.platform import platform BaseFfiTest.setup_class() # prepare C code as an example, so we can load it and call # it via rlib.libffi c_file = udir.ensure("test_libffi", dir=1).join("foolib.c") # automatically collect the C source from the docstrings of the tests snippets = [] for name in dir(cls): if name.startswith('test_'): meth = getattr(cls, name) # the heuristic to determine it it's really C code could be # improved: so far we just check that there is a '{' :-) if meth.__doc__ is not None and '{' in meth.__doc__: snippets.append(meth.__doc__) # INCLUDE = '#include "src/precommondefs.h"\n' c_file.write(INCLUDE + str(py.code.Source('\n'.join(snippets)))) eci = ExternalCompilationInfo(include_dirs=[cdir]) cls.libfoo_name = str( platform.compile([c_file], eci, 'x', standalone=False)) cls.dll = cls.CDLL(cls.libfoo_name)
def setup_class(cls): from rpython.tool.udir import udir from rpython.translator.tool.cbuild import ExternalCompilationInfo from rpython.translator.platform import platform BaseFfiTest.setup_class() # prepare C code as an example, so we can load it and call # it via rlib.libffi c_file = udir.ensure("test_libffi", dir=1).join("foolib.c") # automatically collect the C source from the docstrings of the tests snippets = [] for name in dir(cls): if name.startswith('test_'): meth = getattr(cls, name) # the heuristic to determine it it's really C code could be # improved: so far we just check that there is a '{' :-) if meth.__doc__ is not None and '{' in meth.__doc__: snippets.append(meth.__doc__) # INCLUDE = '#include "src/precommondefs.h"\n' c_file.write(INCLUDE + str(py.code.Source('\n'.join(snippets)))) eci = ExternalCompilationInfo(include_dirs=[cdir]) cls.libfoo_name = str(platform.compile([c_file], eci, 'x', standalone=False)) cls.dll = cls.CDLL(cls.libfoo_name)
def prepare_c_example(cls): from rpython.tool.udir import udir from rpython.translator.tool.cbuild import ExternalCompilationInfo from rpython.translator.platform import platform c_file = udir.ensure("test__ffi", dir=1).join("foolib.c") # automatically collect the C source from the docstrings of the tests snippets = [ """ #include "src/precommondefs.h" #define DLLEXPORT RPY_EXPORTED """ ] for name in dir(cls): if name.startswith('test_'): meth = getattr(cls, name) # the heuristic to determine it it's really C code could be # improved: so far we just check that there is a '{' :-) if meth.__doc__ is not None and '{' in meth.__doc__: snippets.append(meth.__doc__) # c_file.write(py.code.Source('\n'.join(snippets))) eci = ExternalCompilationInfo(include_dirs=[cdir]) # Windows note: can't reuse the same file name 'x.dll', because # the previous one is likely still opened return str( platform.compile([c_file], eci, 'x' + cls.__name__, standalone=False))
def build_executable_cache(c_files, eci, ignore_errors=False): "Builds and run a program; caches the result" # Import 'platform' every time, the compiler may have been changed from rpython.translator.platform import platform path = cache_file_path(c_files, eci, "build_executable_cache") try: return path.read() except py.error.Error: _previous = platform.log_errors try: if ignore_errors: platform.log_errors = False result = platform.execute(platform.compile(c_files, eci)) if result.err: sys.stderr.write(result.err) finally: if ignore_errors: del platform.log_errors # ^^^remove from the instance --- needed so that it can # compare equal to another instance without it if platform.log_errors != _previous: platform.log_errors = _previous if not result.err: try_atomic_write(path, result.out) return result.out
def prepare_c_example(cls): from rpython.tool.udir import udir from rpython.translator.tool.cbuild import ExternalCompilationInfo from rpython.translator.platform import platform c_file = udir.ensure("test__ffi", dir=1).join("foolib.c") # automatically collect the C source from the docstrings of the tests snippets = [""" #ifdef _WIN32 #define DLLEXPORT __declspec(dllexport) #else #define DLLEXPORT #endif """] for name in dir(cls): if name.startswith('test_'): meth = getattr(cls, name) # the heuristic to determine it it's really C code could be # improved: so far we just check that there is a '{' :-) if meth.__doc__ is not None and '{' in meth.__doc__: snippets.append(meth.__doc__) # c_file.write(py.code.Source('\n'.join(snippets))) eci = ExternalCompilationInfo(export_symbols=[]) return str(platform.compile([c_file], eci, 'x', standalone=False))
def test_cdll_life_time(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" RPY_EXPORTED long fun(long i) { return i + 42; } """ ) ) eci = ExternalCompilationInfo(include_dirs=[cdir]) lib_name = str(platform.compile([c_file], eci, "x", standalone=False)) lib = CDLL(lib_name) slong = cast_type_to_ffitype(rffi.LONG) fun = lib.getrawpointer("fun", [slong], slong) del lib # already delete here buffer = lltype.malloc(rffi.LONGP.TO, 2, flavor="raw") buffer[0] = 200 buffer[1] = -1 fun.call([rffi.cast(rffi.VOIDP, buffer)], rffi.cast(rffi.VOIDP, rffi.ptradd(buffer, 1))) assert buffer[1] == 242 lltype.free(buffer, flavor="raw") del fun assert not ALLOCATED
def test_struct_by_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 x_y { long x; long y; }; RPY_EXPORTED long sum_x_y(struct x_y s) { return s.x + s.y; } long sum_x_y_p(struct x_y *p) { return p->x + p->y; } """ ) ) eci = ExternalCompilationInfo(include_dirs=[cdir]) lib_name = str(platform.compile([c_file], eci, "x", standalone=False)) lib = CDLL(lib_name) slong = cast_type_to_ffitype(rffi.LONG) size = slong.c_size * 2 alignment = slong.c_alignment tpe = make_struct_ffitype_e(size, alignment, [slong, slong]) sum_x_y = lib.getrawpointer("sum_x_y", [tpe.ffistruct], slong) buffer = lltype.malloc(rffi.LONGP.TO, 3, flavor="raw") buffer[0] = 200 buffer[1] = 220 buffer[2] = 666 sum_x_y.call([rffi.cast(rffi.VOIDP, buffer)], rffi.cast(rffi.VOIDP, rffi.ptradd(buffer, 2))) assert buffer[2] == 420 lltype.free(buffer, flavor="raw") del sum_x_y lltype.free(tpe, flavor="raw") del lib assert not ALLOCATED
def test_struct_by_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 x_y { long x; long y; }; RPY_EXPORTED long sum_x_y(struct x_y s) { return s.x + s.y; } long sum_x_y_p(struct x_y *p) { return p->x + p->y; } ''')) eci = ExternalCompilationInfo(include_dirs=[cdir]) lib_name = str(platform.compile([c_file], eci, 'x', standalone=False)) lib = CDLL(lib_name) slong = cast_type_to_ffitype(rffi.LONG) size = slong.c_size * 2 alignment = slong.c_alignment tpe = make_struct_ffitype_e(size, alignment, [slong, slong]) sum_x_y = lib.getrawpointer('sum_x_y', [tpe.ffistruct], slong) buffer = lltype.malloc(rffi.LONGP.TO, 3, flavor='raw') buffer[0] = 200 buffer[1] = 220 buffer[2] = 666 sum_x_y.call([rffi.cast(rffi.VOIDP, buffer)], rffi.cast(rffi.VOIDP, rffi.ptradd(buffer, 2))) assert buffer[2] == 420 lltype.free(buffer, flavor='raw') del sum_x_y lltype.free(tpe, flavor='raw') del lib gc.collect() assert not ALLOCATED
def pytest_configure(config): global disabled if disabled or config.getoption('runappdirect') or config.getoption( 'direct_apptest'): if py.path.local.sysfind('genreflex') is None: disabled = True # can't run dummy tests in -A return if py.path.local.sysfind('genreflex') is None: import pypy.module._cppyy.capi.loadable_capi as lcapi try: import ctypes ctypes.CDLL(lcapi.backend_library) except Exception as e: # build dummy backend (which has reflex info and calls hard-wired) import os from rpython.translator.tool.cbuild import ExternalCompilationInfo from rpython.translator.platform import platform, CompilationError from rpython.translator import cdir from rpython.rtyper.lltypesystem import rffi pkgpath = py.path.local(__file__).dirpath().join(os.pardir) srcpath = pkgpath.join('src') incpath = pkgpath.join('include') tstpath = pkgpath.join('test') compile_extra = [ '-DRPY_EXTERN=RPY_EXPORTED', '-DCPPYY_DUMMY_BACKEND' ] if platform.name == 'msvc': compile_extra += ['-std:c++14'] else: compile_extra += ['-fno-strict-aliasing', '-std=c++14'] eci = ExternalCompilationInfo( separate_module_files=[srcpath.join('dummy_backend.cxx')], include_dirs=[incpath, tstpath, cdir], compile_extra=compile_extra, use_cpp_linker=True, ) try: soname = platform.compile( [], eci, outputfilename='libcppyy_dummy_backend', standalone=False) except CompilationError as e: if '-std=c++14' in str(e): disabled = str(e) return raise lcapi.backend_library = str(soname)
def compile_so_file(): from rpython.translator.platform import platform from rpython.translator.tool.cbuild import ExternalCompilationInfo udir = pytest.ensuretemp('_ctypes_test') cfile = py.path.local(__file__).dirpath().join("_ctypes_test.c") if sys.platform == 'win32': libraries = ['oleaut32'] else: libraries = [] eci = ExternalCompilationInfo(libraries=libraries) return platform.compile([cfile], eci, str(udir.join('_ctypes_test')), standalone=False)
def compile_so_file(): from rpython.translator.platform import platform from rpython.translator.tool.cbuild import ExternalCompilationInfo from rpython.translator import cdir udir = pytest.ensuretemp('_ctypes_test') cfile = py.path.local(__file__).dirpath().join("_ctypes_test.c") if sys.platform == 'win32': libraries = ['oleaut32'] else: libraries = [] eci = ExternalCompilationInfo(libraries=libraries, include_dirs=[cdir]) return platform.compile([cfile], eci, str(udir.join('_ctypes_test')), standalone=False)
def test_variadic_args(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 <stdarg.h> #include <stdio.h> RPY_EXPORTED Signed fun(Signed n, ...) { va_list ptr; int sum = 0; printf("n: %ld\\n", n); va_start(ptr, n); for (int i = 0; i < n; i++) { Signed foo = va_arg(ptr, Signed); sum += foo; printf("Arg %d: %ld\\n", i, foo); } va_end(ptr); return sum; } ''')) eci = ExternalCompilationInfo(include_dirs=[cdir]) lib_name = str(platform.compile([c_file], eci, 'x4', standalone=False)) lib = CDLL(lib_name) signed = cast_type_to_ffitype(rffi.SIGNED) fun = lib.getrawpointer('fun', [signed, signed, signed], signed, variadic_args=2) buffer = lltype.malloc(rffi.SIGNEDP.TO, 4, flavor='raw') buffer[0] = 2 buffer[1] = 3 buffer[2] = 15 buffer[3] = 100 fun.call([rffi.cast(rffi.VOIDP, buffer), rffi.cast(rffi.VOIDP, rffi.ptradd(buffer, 1)), rffi.cast(rffi.VOIDP, rffi.ptradd(buffer, 2))], rffi.cast(rffi.VOIDP, rffi.ptradd(buffer, 3))) assert buffer[3] == 3 + 15 lltype.free(buffer, flavor='raw')
def setup_class(cls): import ctypes from rpython.tool.udir import udir from rpython.translator.platform import platform from rpython.translator.tool.cbuild import ExternalCompilationInfo c_source = """ #include "src/precommondefs.h" RPY_EXPORTED void *int_to_void_p(int arg) {} RPY_EXPORTED struct random_structure* int_int_to_struct_p(int one, int two) {} """ c_file = udir.join('rffilib.c') c_file.write(c_source) eci = ExternalCompilationInfo(include_dirs=[cdir]) libname = platform.compile([c_file], eci, standalone=False) cls.lib = ctypes.CDLL(str(libname))
def test_external_lib(): eci = ExternalCompilationInfo(include_dirs=[cdir]) c_source = """ #include "src/precommondefs.h" RPY_EXPORTED int f(int a, int b) { return (a + b); } """ if platform.name == 'msvc': libname = 'libc_lib' else: libname = 'c_lib' tmpdir = udir.join('external_lib').ensure(dir=1) c_file = tmpdir.join('libc_lib.c') c_file.write(c_source) l = platform.compile([c_file], eci, standalone=False) eci = ExternalCompilationInfo(libraries=[libname], library_dirs=[str(tmpdir)]) rffi_platform.verify_eci(eci)
def test_external_lib(): eci = ExternalCompilationInfo() c_source = """ int f(int a, int b) { return (a + b); } """ if platform.name == 'msvc': c_source = '__declspec(dllexport) ' + c_source libname = 'libc_lib' else: libname = 'c_lib' tmpdir = udir.join('external_lib').ensure(dir=1) c_file = tmpdir.join('libc_lib.c') c_file.write(c_source) l = platform.compile([c_file], eci, standalone=False) eci = ExternalCompilationInfo( libraries = [libname], library_dirs = [str(tmpdir)] ) rffi_platform.verify_eci(eci)
def setup_class(cls): import ctypes from rpython.tool.udir import udir from rpython.translator.platform import platform from rpython.translator.tool.cbuild import ExternalCompilationInfo c_source = """ void *int_to_void_p(int arg) {} struct random_strucutre { int one; int *two; }; struct random_structure* int_int_to_struct_p(int one, int two) {} """ c_file = udir.join('rffilib.c') c_file.write(c_source) libname = platform.compile([c_file], ExternalCompilationInfo(), standalone=False) cls.lib = ctypes.CDLL(str(libname))
def pytest_configure(config): if py.path.local.sysfind('genreflex') is None: import pypy.module.cppyy.capi.loadable_capi as lcapi try: import ctypes ctypes.CDLL(lcapi.reflection_library) except Exception, e: if config.option.runappdirect: return # "can't run dummy tests in -A" # build dummy backend (which has reflex info and calls hard-wired) import os from rpython.translator.tool.cbuild import ExternalCompilationInfo from rpython.translator.platform import platform from rpython.translator import cdir from rpython.rtyper.lltypesystem import rffi pkgpath = py.path.local(__file__).dirpath().join(os.pardir) srcpath = pkgpath.join('src') incpath = pkgpath.join('include') tstpath = pkgpath.join('test') eci = ExternalCompilationInfo( separate_module_files=[srcpath.join('dummy_backend.cxx')], include_dirs=[incpath, tstpath, cdir], compile_extra=['-DRPY_EXTERN=RPY_EXPORTED'], use_cpp_linker=True, ) soname = platform.compile([], eci, outputfilename='libcppyy_dummy_backend', standalone=False) lcapi.reflection_library = str(soname)
def test_external_lib(): eci = ExternalCompilationInfo(include_dirs = [cdir]) c_source = """ #include "src/precommondefs.h" RPY_EXPORTED int f(int a, int b) { return (a + b); } """ if platform.name == 'msvc': libname = 'libc_lib' else: libname = 'c_lib' tmpdir = udir.join('external_lib').ensure(dir=1) c_file = tmpdir.join('libc_lib.c') c_file.write(c_source) l = platform.compile([c_file], eci, standalone=False) eci = ExternalCompilationInfo( libraries = [libname], library_dirs = [str(tmpdir)] ) rffi_platform.verify_eci(eci)
def prepare_c_example(): from rpython.tool.udir import udir c_file = udir.ensure("test__rawffi", dir=1).join("xlib.c") c_file.write(py.code.Source(''' #include "src/precommondefs.h" #include <stdlib.h> #include <stdio.h> #include <errno.h> struct x { int x1; short x2; char x3; struct x* next; }; RPY_EXPORTED void nothing() { } RPY_EXPORTED char inner_struct_elem(struct x *x1) { return x1->next->x3; } RPY_EXPORTED struct x* create_double_struct() { struct x* x1, *x2; x1 = (struct x*)malloc(sizeof(struct x)); x2 = (struct x*)malloc(sizeof(struct x)); x1->next = x2; x2->x2 = 3; return x1; } RPY_EXPORTED void free_double_struct(struct x* x1) { free(x1->next); free(x1); } const char *static_str = "xxxxxx"; RPY_EXPORTED long static_int = 42; RPY_EXPORTED double static_double = 42.42; RPY_EXPORTED long double static_longdouble = 42.42; RPY_EXPORTED unsigned short add_shorts(short one, short two) { return one + two; } RPY_EXPORTED void* get_raw_pointer() { return (void*)add_shorts; } RPY_EXPORTED char get_char(char* s, unsigned short num) { return s[num]; } RPY_EXPORTED const char *char_check(char x, char y) { if (y == static_str[0]) return static_str; return NULL; } RPY_EXPORTED int get_array_elem(int* stuff, int num) { return stuff[num]; } RPY_EXPORTED struct x* get_array_elem_s(struct x** array, int num) { return array[num]; } RPY_EXPORTED long long some_huge_value() { return 1LL<<42; } RPY_EXPORTED unsigned long long some_huge_uvalue() { return 1LL<<42; } RPY_EXPORTED long long pass_ll(long long x) { return x; } static int prebuilt_array1[] = {3}; RPY_EXPORTED int* allocate_array() { return prebuilt_array1; } RPY_EXPORTED long long runcallback(long long(*callback)()) { return callback(); } struct x_y { long x; long y; }; RPY_EXPORTED long sum_x_y(struct x_y s) { return s.x + s.y; } RPY_EXPORTED long op_x_y(struct x_y s, long(*callback)(struct x_y)) { return callback(s); } 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; } struct s2a { int bah[2]; }; RPY_EXPORTED struct s2a get_s2a(void) { struct s2a outp; outp.bah[0] = 4; outp.bah[1] = 5; return outp; } RPY_EXPORTED int check_s2a(struct s2a inp) { return (inp.bah[0] == 4 && inp.bah[1] == 5); } RPY_EXPORTED int AAA_first_ordinal_function() { return 42; } typedef union { short x; long y; } UN; RPY_EXPORTED UN ret_un_func(UN inp) { inp.y = inp.x * 100; return inp; } RPY_EXPORTED int check_errno(int incoming) { int old_errno = errno; errno = incoming; return old_errno; } #ifdef _WIN32 #include <Windows.h> RPY_EXPORTED int check_last_error(int incoming) { int old_errno = GetLastError(); SetLastError(incoming); return old_errno; } #endif ''')) eci = ExternalCompilationInfo(include_dirs=[cdir]) return str(platform.compile([c_file], eci, 'x', standalone=False))
def prepare_c_example(): from rpython.tool.udir import udir c_file = udir.ensure("test__rawffi", dir=1).join("xlib.c") c_file.write(py.code.Source(''' #include <stdlib.h> #include <stdio.h> struct x { int x1; short x2; char x3; struct x* next; }; void nothing() { } char inner_struct_elem(struct x *x1) { return x1->next->x3; } struct x* create_double_struct() { struct x* x1, *x2; x1 = (struct x*)malloc(sizeof(struct x)); x2 = (struct x*)malloc(sizeof(struct x)); x1->next = x2; x2->x2 = 3; return x1; } void free_double_struct(struct x* x1) { free(x1->next); free(x1); } const char *static_str = "xxxxxx"; long static_int = 42; double static_double = 42.42; long double static_longdouble = 42.42; unsigned short add_shorts(short one, short two) { return one + two; } void* get_raw_pointer() { return (void*)add_shorts; } char get_char(char* s, unsigned short num) { return s[num]; } const char *char_check(char x, char y) { if (y == static_str[0]) return static_str; return NULL; } int get_array_elem(int* stuff, int num) { return stuff[num]; } struct x* get_array_elem_s(struct x** array, int num) { return array[num]; } long long some_huge_value() { return 1LL<<42; } unsigned long long some_huge_uvalue() { return 1LL<<42; } long long pass_ll(long long x) { return x; } static int prebuilt_array1[] = {3}; int* allocate_array() { return prebuilt_array1; } long long runcallback(long long(*callback)()) { return callback(); } struct x_y { long x; long y; }; long sum_x_y(struct x_y s) { return s.x + s.y; } long op_x_y(struct x_y s, long(*callback)(struct x_y)) { return callback(s); } struct s2h { short x; short y; }; struct s2h give(short x, short y) { struct s2h out; out.x = x; out.y = y; return out; } struct s2h perturb(struct s2h inp) { inp.x *= 2; inp.y *= 3; return inp; } struct s2a { int bah[2]; }; struct s2a get_s2a(void) { struct s2a outp; outp.bah[0] = 4; outp.bah[1] = 5; return outp; } int check_s2a(struct s2a inp) { return (inp.bah[0] == 4 && inp.bah[1] == 5); } int AAA_first_ordinal_function() { return 42; } typedef union { short x; long y; } UN; UN ret_un_func(UN inp) { inp.y = inp.x * 100; return inp; } ''')) symbols = """get_char char_check get_raw_pointer add_shorts inner_struct_elem create_double_struct free_double_struct get_array_elem get_array_elem_s nothing some_huge_value some_huge_uvalue pass_ll runcallback allocate_array static_int static_double static_longdouble sum_x_y op_x_y give perturb get_s2a check_s2a AAA_first_ordinal_function ret_un_func """.split() eci = ExternalCompilationInfo(export_symbols=symbols) return str(platform.compile([c_file], eci, 'x', standalone=False))
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 <stdlib.h> #include <stdio.h> struct s2h { short x; short y; }; struct s2h give(short x, short y) { struct s2h out; out.x = x; out.y = y; return out; } struct s2h perturb(struct s2h inp) { inp.x *= 2; inp.y *= 3; return inp; } ''')) eci = ExternalCompilationInfo(export_symbols=['give', 'perturb']) 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') del lib assert not ALLOCATED
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
# This is how the files, which are checked into the repo, were created from rpython.translator.tool.cbuild import ExternalCompilationInfo from rpython.translator.platform import platform from rpython.translator import cdir if not os.path.exists(loadtest_dir): os.mkdir(loadtest_dir) c_file = udir.ensure("test_rwin32", dir=1).join("test0.c") c_file.write(py.code.Source(''' #include "src/precommondefs.h" RPY_EXPORTED int internal_sum(int a, int b) { return a + b; } ''')) eci = ExternalCompilationInfo(include_dirs=[cdir]) lib_name = str(platform.compile([c_file], eci, test0[:-4], standalone=False)) assert os.path.abspath(lib_name) == os.path.abspath(test0) c_file = udir.ensure("test_rwin32", dir=1).join("test1.c") c_file.write(py.code.Source(''' #include "src/precommondefs.h" int internal_sum(int a, int b); RPY_EXPORTED int sum(int a, int b) { return internal_sum(a, b); } ''')) eci = ExternalCompilationInfo(include_dirs=[cdir], libraries=[loadtest_dir + '/loadtest0']) lib_name = str(platform.compile([c_file], eci, test1[:-4], standalone=False, ))
def prepare_c_example(): from rpython.tool.udir import udir c_file = udir.ensure("test__rawffi", dir=1).join("xlib.c") c_file.write( py.code.Source(''' #include "src/precommondefs.h" #include <stdlib.h> #include <stdio.h> #include <errno.h> struct x { int x1; short x2; char x3; struct x* next; }; RPY_EXPORTED void nothing() { } RPY_EXPORTED char inner_struct_elem(struct x *x1) { return x1->next->x3; } RPY_EXPORTED struct x* create_double_struct() { struct x* x1, *x2; x1 = (struct x*)malloc(sizeof(struct x)); x2 = (struct x*)malloc(sizeof(struct x)); x1->next = x2; x2->x2 = 3; return x1; } RPY_EXPORTED void free_double_struct(struct x* x1) { free(x1->next); free(x1); } const char *static_str = "xxxxxx"; RPY_EXPORTED long static_int = 42; RPY_EXPORTED double static_double = 42.42; RPY_EXPORTED long double static_longdouble = 42.42; RPY_EXPORTED unsigned short add_shorts(short one, short two) { return one + two; } RPY_EXPORTED void* get_raw_pointer() { return (void*)add_shorts; } RPY_EXPORTED char get_char(char* s, unsigned short num) { return s[num]; } RPY_EXPORTED const char *char_check(char x, char y) { if (y == static_str[0]) return static_str; return NULL; } RPY_EXPORTED int get_array_elem(int* stuff, int num) { return stuff[num]; } RPY_EXPORTED struct x* get_array_elem_s(struct x** array, int num) { return array[num]; } RPY_EXPORTED long long some_huge_value() { return 1LL<<42; } RPY_EXPORTED unsigned long long some_huge_uvalue() { return 1LL<<42; } RPY_EXPORTED long long pass_ll(long long x) { return x; } static int prebuilt_array1[] = {3}; RPY_EXPORTED int* allocate_array() { return prebuilt_array1; } RPY_EXPORTED long long runcallback(long long(*callback)()) { return callback(); } struct x_y { long x; long y; }; RPY_EXPORTED long sum_x_y(struct x_y s) { return s.x + s.y; } RPY_EXPORTED long op_x_y(struct x_y s, long(*callback)(struct x_y)) { return callback(s); } 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; } struct s2a { int bah[2]; }; RPY_EXPORTED struct s2a get_s2a(void) { struct s2a outp; outp.bah[0] = 4; outp.bah[1] = 5; return outp; } RPY_EXPORTED int check_s2a(struct s2a inp) { return (inp.bah[0] == 4 && inp.bah[1] == 5); } RPY_EXPORTED int AAA_first_ordinal_function() { return 42; } typedef union { short x; long y; } UN; RPY_EXPORTED UN ret_un_func(UN inp) { inp.y = inp.x * 100; return inp; } RPY_EXPORTED int check_errno(int incoming) { int old_errno = errno; errno = incoming; return old_errno; } #ifdef _WIN32 #include <Windows.h> RPY_EXPORTED int check_last_error(int incoming) { int old_errno = GetLastError(); SetLastError(incoming); return old_errno; } #endif ''')) eci = ExternalCompilationInfo(include_dirs=[cdir]) return str(platform.compile([c_file], eci, 'x', standalone=False))
from rpython.translator.platform import platform from rpython.translator import cdir if not os.path.exists(loadtest_dir): os.mkdir(loadtest_dir) c_file = udir.ensure("test_rwin32", dir=1).join("test0.c") c_file.write( py.code.Source(''' #include "src/precommondefs.h" RPY_EXPORTED int internal_sum(int a, int b) { return a + b; } ''')) eci = ExternalCompilationInfo(include_dirs=[cdir]) lib_name = str( platform.compile([c_file], eci, test0[:-4], standalone=False)) assert os.path.abspath(lib_name) == os.path.abspath(test0) c_file = udir.ensure("test_rwin32", dir=1).join("test1.c") c_file.write( py.code.Source(''' #include "src/precommondefs.h" int internal_sum(int a, int b); RPY_EXPORTED int sum(int a, int b) { return internal_sum(a, b); } ''')) eci = ExternalCompilationInfo( include_dirs=[cdir], libraries=[loadtest_dir + '/loadtest0' + arch]) lib_name = str(