def main(filename): ffi = FFI() ffi.set_source( "pylibsize", """ # include "libsize.h" """, extra_objects=["libsize.so"], include_dirs=["."], ) ffi.cdef( """\ struct Size_return { int r0; /* w */ int r1; /* h */ }; extern struct Size_return Size(char* p0); """ ) ffi.compile(verbose=True, debug=True) from pylibsize import lib, ffi sizeinfo = lib.Size(filename.encode("utf-8")) print(sizeinfo, sizeinfo.r0, sizeinfo.r1)
def setup_class(cls): stack_ffi = FFI() stack_ffi.cdef(""" typedef intptr_t ptr_t; int vmp_binary_search_ranges(ptr_t ip, ptr_t * l, int count); int vmp_ignore_ip(ptr_t ip); int vmp_ignore_symbol_count(void); ptr_t * vmp_ignore_symbols(void); void vmp_set_ignore_symbols(ptr_t * symbols, int count); int vmp_read_vmaps(const char * fname); void vmp_native_disable(); """) with open("src/vmp_stack.c", "rb") as fd: source = fd.read().decode() libs = [] #['unwind', 'unwind-x86_64'] if sys.platform.startswith('linux'): libs = ['unwind', 'unwind-x86_64'] # trick: compile with _CFFI_USE_EMBEDDING=1 which will not define Py_LIMITED_API stack_ffi.set_source("vmprof.test._test_stack", source, include_dirs=['src'], define_macros=[('_CFFI_USE_EMBEDDING',1), ('PY_TEST',1), ('VMP_SUPPORTS_NATIVE_PROFILING',1)], libraries=libs, extra_compile_args=['-Werror', '-g']) stack_ffi.compile(verbose=True) from vmprof.test import _test_stack as clib cls.lib = clib.lib cls.ffi = clib.ffi
def main(defs_file, parser_file, verbose): ffi = FFI() with open(defs_file) as f: ffi.embedding_api(f.read()) ffi.set_source('parser_interface', '#include "%s"' % defs_file) with open(parser_file) as f: ffi.embedding_init_code(f.read()) interpreter, _, _ = os.path.basename(sys.executable).partition('.') ffi.compile(target='libplease_parser_%s.*' % interpreter, verbose=verbose)
def _buildlib(): cdef, src = _getcode() libname = _getlibname() from cffi import FFI ffibuilder = FFI() ffibuilder.cdef(cdef) ffibuilder.set_source(libname, src) dir = os.path.abspath(os.path.dirname(__file__)) ffibuilder.compile(tmpdir=dir,verbose=True)
def find_curses_library(): for curses_library in ['ncursesw', 'ncurses']: ffi = FFI() ffi.set_source("_curses_cffi_check", "", libraries=[curses_library]) try: ffi.compile() except VerificationError as e: e_last = e continue else: return curses_library # If none of the libraries is available, present the user a meaningful # error message raise e_last
def load_ool_module(): """ Compile an out-of-line module, return the corresponding ffi and module objects. """ from cffi import FFI defs = """ double sin(double x); double cos(double x); void vsSin(int n, float* x, float* y); void vdSin(int n, double* x, double* y); int foo(int a, int b, int c); """ source = """ static int foo(int a, int b, int c) { return a + b * c; } void vsSin(int n, float* x, float* y) { int i; for (i=0; i<n; i++) y[i] = sin(x[i]); } void vdSin(int n, double* x, double* y) { int i; for (i=0; i<n; i++) y[i] = sin(x[i]); } """ ffi = FFI() ffi.set_source('cffi_usecases_ool', source) ffi.cdef(defs, override=True) tmpdir = static_temp_directory('test_cffi') ffi.compile(tmpdir=tmpdir) sys.path.append(tmpdir) try: import cffi_usecases_ool as mod cffi_support.register_module(mod) return mod.ffi, mod finally: sys.path.remove(tmpdir)
def build(**kwargs): """Build the C slitfunc library""" CWD = os.path.dirname(__file__) ffibuilder = FFI() with open(os.path.join(CWD, "slit_func_bd.h")) as f: ffibuilder.cdef(f.read(), override=True) with open(os.path.join(CWD, "slit_func_bd.c"), "r") as f: ffibuilder.set_source("clib._slitfunc_bd", f.read()) ffibuilder.compile(**kwargs) ffibuilder = FFI() with open(os.path.join(CWD, "slit_func_2d_xi_zeta_bd.h")) as f: ffibuilder.cdef(f.read(), override=True) with open(os.path.join(CWD, "slit_func_2d_xi_zeta_bd.c"), "r") as f: ffibuilder.set_source("clib._slitfunc_2d", f.read()) ffibuilder.compile(**kwargs)
def build(**kwargs): """Build the cluster C library""" ffibuilder = FFI() CWD = os.path.dirname(__file__) with open(os.path.join(CWD, "cluster.h")) as f: ffibuilder.cdef(f.read(), override=True) with open(os.path.join(CWD, "cluster.c"), "r") as f: ffibuilder.set_source( "clib._cluster", f.read(), # libraries=["c"], # sources=[os.path.join(CWD, "cluster.c")], # library_dirs=["."] # include_dirs=[os.path.join()] ) ffibuilder.compile(**kwargs)
def setup_class(cls): ffi = FFI() ffi.cdef(""" void native_gzipgzipgzip(void); """) source = """ #include "zlib.h" unsigned char input[100]; unsigned char output[100]; void native_gzipgzipgzip(void) { z_stream defstream; defstream.zalloc = Z_NULL; defstream.zfree = Z_NULL; defstream.opaque = Z_NULL; defstream.next_in = input; // input char array defstream.next_out = output; // output char array deflateInit(&defstream, Z_DEFAULT_COMPRESSION); int i = 0; while (i < 10000) { defstream.avail_in = 100; defstream.avail_out = 100; deflate(&defstream, Z_FINISH); i++; } deflateEnd(&defstream); } """ libs = [] if sys.platform.startswith('linux'): libs.append('z') # trick: compile with _CFFI_USE_EMBEDDING=1 which will not define Py_LIMITED_API ffi.set_source("vmprof.test._test_native_gzip", source, include_dirs=['src'], define_macros=[('_CFFI_USE_EMBEDDING',1),('_PY_TEST',1)], libraries=libs, extra_compile_args=['-Werror', '-g', '-O0']) ffi.compile(verbose=True) from vmprof.test import _test_native_gzip as clib cls.lib = clib.lib cls.ffi = clib.ffi
def _build_c_extension(): ffi = FFI() ffi.cdef(""" typedef int... off_t; #define PROT_READ ... #define PROT_WRITE ... #define PROT_EXEC ... #define PROT_NONE ... #define MAP_PRIVATE ... #define MAP_FIXED ... #define MAP_SHARED ... void mmap_init(off_t offset); uint16_t mmap_peek16(off_t offset); void mmap_poke16(off_t offset, uint16_t value); """) ffi.set_source("_cmmapwrapper", """ #include<sys/mman.h> #include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> volatile uint16_t *map = 0; void mmap_init(off_t offset){ int fd; fd = open("/dev/mem", O_RDWR|O_SYNC); map = mmap(0, getpagesize(), PROT_READ|PROT_WRITE, MAP_SHARED, fd, offset); } uint16_t mmap_peek16(off_t offset){ uint16_t n; n = map[offset/2]; return n; } void mmap_poke16(off_t offset, uint16_t value){ map[offset/2] = value; } """) ffi.compile(tmpdir='build')
def test_cffi_assembly(): mesh = create_unit_square(MPI.COMM_WORLD, 13, 13) V = FunctionSpace(mesh, ("Lagrange", 1)) if mesh.comm.rank == 0: from cffi import FFI ffibuilder = FFI() ffibuilder.set_source( "_cffi_kernelA", r""" #include <math.h> #include <stdalign.h> void tabulate_tensor_poissonA(double* restrict A, const double* w, const double* c, const double* restrict coordinate_dofs, const int* entity_local_index, const int* cell_orientation) { // Precomputed values of basis functions and precomputations // FE* dimensions: [entities][points][dofs] // PI* dimensions: [entities][dofs][dofs] or [entities][dofs] // PM* dimensions: [entities][dofs][dofs] alignas(32) static const double FE3_C0_D01_Q1[1][1][2] = { { { -1.0, 1.0 } } }; // Unstructured piecewise computations const double J_c0 = coordinate_dofs[0] * FE3_C0_D01_Q1[0][0][0] + coordinate_dofs[3] * FE3_C0_D01_Q1[0][0][1]; const double J_c3 = coordinate_dofs[1] * FE3_C0_D01_Q1[0][0][0] + coordinate_dofs[7] * FE3_C0_D01_Q1[0][0][1]; const double J_c1 = coordinate_dofs[0] * FE3_C0_D01_Q1[0][0][0] + coordinate_dofs[6] * FE3_C0_D01_Q1[0][0][1]; const double J_c2 = coordinate_dofs[1] * FE3_C0_D01_Q1[0][0][0] + coordinate_dofs[4] * FE3_C0_D01_Q1[0][0][1]; alignas(32) double sp[20]; sp[0] = J_c0 * J_c3; sp[1] = J_c1 * J_c2; sp[2] = sp[0] + -1 * sp[1]; sp[3] = J_c0 / sp[2]; sp[4] = -1 * J_c1 / sp[2]; sp[5] = sp[3] * sp[3]; sp[6] = sp[3] * sp[4]; sp[7] = sp[4] * sp[4]; sp[8] = J_c3 / sp[2]; sp[9] = -1 * J_c2 / sp[2]; sp[10] = sp[9] * sp[9]; sp[11] = sp[8] * sp[9]; sp[12] = sp[8] * sp[8]; sp[13] = sp[5] + sp[10]; sp[14] = sp[6] + sp[11]; sp[15] = sp[12] + sp[7]; sp[16] = fabs(sp[2]); sp[17] = sp[13] * sp[16]; sp[18] = sp[14] * sp[16]; sp[19] = sp[15] * sp[16]; // UFLACS block mode: preintegrated A[0] = 0.5 * sp[19] + 0.5 * sp[18] + 0.5 * sp[18] + 0.5 * sp[17]; A[1] = -0.5 * sp[19] + -0.5 * sp[18]; A[2] = -0.5 * sp[18] + -0.5 * sp[17]; A[3] = -0.5 * sp[19] + -0.5 * sp[18]; A[4] = 0.5 * sp[19]; A[5] = 0.5 * sp[18]; A[6] = -0.5 * sp[18] + -0.5 * sp[17]; A[7] = 0.5 * sp[18]; A[8] = 0.5 * sp[17]; } void tabulate_tensor_poissonL(double* restrict A, const double* w, const double* c, const double* restrict coordinate_dofs, const int* entity_local_index, const int* cell_orientation) { // Precomputed values of basis functions and precomputations // FE* dimensions: [entities][points][dofs] // PI* dimensions: [entities][dofs][dofs] or [entities][dofs] // PM* dimensions: [entities][dofs][dofs] alignas(32) static const double FE4_C0_D01_Q1[1][1][2] = { { { -1.0, 1.0 } } }; // Unstructured piecewise computations const double J_c0 = coordinate_dofs[0] * FE4_C0_D01_Q1[0][0][0] + coordinate_dofs[3] * FE4_C0_D01_Q1[0][0][1]; const double J_c3 = coordinate_dofs[1] * FE4_C0_D01_Q1[0][0][0] + coordinate_dofs[7] * FE4_C0_D01_Q1[0][0][1]; const double J_c1 = coordinate_dofs[0] * FE4_C0_D01_Q1[0][0][0] + coordinate_dofs[6] * FE4_C0_D01_Q1[0][0][1]; const double J_c2 = coordinate_dofs[1] * FE4_C0_D01_Q1[0][0][0] + coordinate_dofs[4] * FE4_C0_D01_Q1[0][0][1]; alignas(32) double sp[4]; sp[0] = J_c0 * J_c3; sp[1] = J_c1 * J_c2; sp[2] = sp[0] + -1 * sp[1]; sp[3] = fabs(sp[2]); // UFLACS block mode: preintegrated A[0] = 0.1666666666666667 * sp[3]; A[1] = 0.1666666666666667 * sp[3]; A[2] = 0.1666666666666667 * sp[3]; } """) ffibuilder.cdef(""" void tabulate_tensor_poissonA(double* restrict A, const double* w, const double* c, const double* restrict coordinate_dofs, const int* entity_local_index, const int* cell_orientation); void tabulate_tensor_poissonL(double* restrict A, const double* w, const double* c, const double* restrict coordinate_dofs, const int* entity_local_index, const int* cell_orientation); """) ffibuilder.compile(verbose=True) mesh.comm.Barrier() from _cffi_kernelA import ffi, lib ptrA = ffi.cast("intptr_t", ffi.addressof(lib, "tabulate_tensor_poissonA")) integrals = {IntegralType.cell: ([(-1, ptrA)], None)} a = _cpp.fem.Form_float64([V._cpp_object, V._cpp_object], integrals, [], [], False) ptrL = ffi.cast("intptr_t", ffi.addressof(lib, "tabulate_tensor_poissonL")) integrals = {IntegralType.cell: ([(-1, ptrL)], None)} L = _cpp.fem.Form_float64([V._cpp_object], integrals, [], [], False) A = fem.assemble_matrix(a) A.finalize() assert np.isclose(np.sqrt(A.norm_squared()), 56.124860801609124) b = fem.assemble_vector(L) b.scatter_reverse(_cpp.common.ScatterMode.add) assert np.isclose(b.norm(), 0.0739710713711999)
gchar * gdk_pixbuf_format_get_name (GdkPixbufFormat *format); GdkColorspace gdk_pixbuf_get_colorspace (const GdkPixbuf *pixbuf); int gdk_pixbuf_get_n_channels (const GdkPixbuf *pixbuf); gboolean gdk_pixbuf_get_has_alpha (const GdkPixbuf *pixbuf); int gdk_pixbuf_get_bits_per_sample (const GdkPixbuf *pixbuf); int gdk_pixbuf_get_width (const GdkPixbuf *pixbuf); int gdk_pixbuf_get_height (const GdkPixbuf *pixbuf); int gdk_pixbuf_get_rowstride (const GdkPixbuf *pixbuf); guchar * gdk_pixbuf_get_pixels (const GdkPixbuf *pixbuf); gsize gdk_pixbuf_get_byte_length (const GdkPixbuf *pixbuf); gboolean gdk_pixbuf_save_to_buffer ( GdkPixbuf *pixbuf, gchar **buffer, gsize *buffer_size, const char *type, GError **error, ...); void gdk_cairo_set_source_pixbuf ( cairo_t *cr, const GdkPixbuf *pixbuf, double pixbuf_x, double pixbuf_y); void g_object_ref (gpointer object); void g_object_unref (gpointer object); void g_error_free (GError *error); void g_type_init (void); ''') if __name__ == '__main__': ffi.compile() ffi_pixbuf.compile()
def build(name, openvx_install, default): pwd = os.getcwd() os.chdir(os.path.dirname(mydir)) assert name != 'default' hdr = os.path.join(openvx_install, 'include', 'VX', 'vx.h') if not os.path.exists(hdr): print("ERROR: Can't find header", hdr) exit(-1) lib = os.path.join(openvx_install, 'bin', 'libopenvx.so') if not os.path.exists(lib): print("ERROR: Can't find lib", lib) exit(-1) defs= dict(VX_API_ENTRY='', VX_API_CALL='', VX_CALLBACK='', VX_MAX_KERNEL_NAME='256') if os.name == 'nt': defs['VX_API_CALL'] = '__stdcall' defs['VX_CALLBACK'] = '__stdcall' ffi = FFI() # vx.h vx = open(os.path.join(mydir, "cdefs", "vx.h")).read() vx = re.subn(r'(#define\s+[^\s]+)\s.*', r'\1 ...', vx)[0] # Remove specifics from #defines ffi.cdef(vx) # vx_vendors.h ffi.cdef(open(os.path.join(mydir, "cdefs", "vx_vendors.h")).read()) # vx_types.h types = open(os.path.join(mydir, "cdefs", "vx_types.h")).read() for k,v in defs.items(): types = types.replace(k, v) types = re.subn(r'(#define\s+[^\s]+)\s.*', r'\1 ...', types)[0] # Remove specifics from #defines types = re.subn(r'(/\*.*?\*/)', r'', types)[0] # Remove some one line comments types = re.subn(r'=.*,', r'= ...,', types)[0] # Remove specifics from enums types = re.subn(r'\[\s*[^\s]+?.*?\]', r'[...]', types)[0] # Remove specific array sizes ffi.cdef(types) ffi.cdef(''' char *_get_FMT_REF(void); char *_get_FMT_SIZE(void); int _get_KERNEL_BASE(int vendor, int lib); char *_get_backend_version(); char *_get_backend_name(); char *_get_backend_install_path(); ''') # vx_kernels.h kernels = open(os.path.join(mydir, "cdefs", "vx_kernels.h")).read() kernels = re.subn(r'=.*,', r'= ...,', kernels)[0] # Remove specifics from enums ffi.cdef(kernels) # vx_api.h api = open(os.path.join(mydir, "cdefs", "vx_api.h")).read() for k, v in defs.items(): api = api.replace(k, v) ffi.cdef(api) # vx_nodes.h nodes = open(os.path.join(mydir, "cdefs", "vx_nodes.h")).read() for k, v in defs.items(): nodes = nodes.replace(k, v) ffi.cdef(nodes) # vxu.h vxu = open(os.path.join(mydir, "cdefs", "vxu.h")).read() for k, v in defs.items(): vxu = vxu.replace(k, v) ffi.cdef(vxu) ffi.set_source("pyvx.backend.%s" % name, """ #include <VX/vx.h> #include <VX/vxu.h> char *_get_FMT_REF(void) {return VX_FMT_REF;} char *_get_FMT_SIZE(void) {return VX_FMT_SIZE;} int _get_KERNEL_BASE(int vendor, int lib) {return VX_KERNEL_BASE(vendor, lib);} char *_get_backend_version() {return "%s";} char *_get_backend_name() {return "%s";} char *_get_backend_install_path() {return "%s";} """ % (__backend_version__.decode("utf8"), name, openvx_install), include_dirs=[os.path.join(openvx_install, 'include')], library_dirs=[os.path.join(openvx_install, 'bin')], extra_link_args=['-Wl,-rpath=' + os.path.abspath(os.path.join(openvx_install, 'bin'))], libraries=['openvx', 'vxu']) ffi.compile() default_file_name = os.path.join('pyvx', 'backend', '_default.py') if default or not os.path.exists(default_file_name): fd = open(default_file_name, 'w') fd.write("from pyvx.backend.%s import ffi, lib\n" % name) fd.close() import pyvx.backend as backend assert backend.ffi.string(backend.lib._get_backend_version()) == __backend_version__ assert backend.ffi.string(backend.lib._get_backend_name()).decode("utf8") == name assert backend.ffi.string(backend.lib._get_backend_install_path()).decode("utf8") == openvx_install names = {} exec("import pyvx.backend.%s as backend" % name, names) backend = names['backend'] assert backend.ffi.string(backend.lib._get_backend_version()) == __backend_version__ assert backend.ffi.string(backend.lib._get_backend_name()).decode("utf8") == name assert backend.ffi.string(backend.lib._get_backend_install_path()).decode("utf8") == openvx_install print('') print("Succesfully built backend pyvx.backend.%s in %s" % (name, mydir)) print('')
# Copied from the Go-generated gohttplib.h ffi.cdef(""" typedef struct Request_ { const char *Method; const char *Host; const char *URL; const char *Body; const char *Headers; } Request; typedef unsigned int ResponseWriterPtr; typedef void FuncPtr(ResponseWriterPtr w, Request *r); void Call_HandleFunc(ResponseWriterPtr w, Request *r, FuncPtr *fn); void ListenAndServe(char* p0); void Shutdown(); void HandleFunc(char* p0, FuncPtr* p1); int ResponseWriter_Write(unsigned int p0, char* p1, int p2); void ResponseWriter_WriteHeader(unsigned int p0, int p1); """) if __name__ == "__main__": ffi.compile()
assert(pNtHeaders32->OptionalHeader.DataDirectory[0].VirtualAddress != 0); assert(pNtHeaders32->OptionalHeader.DataDirectory[0].Size != 0); pExportDirectory = (IMAGE_EXPORT_DIRECTORY*) (pNtHeaders32->OptionalHeader.DataDirectory[0].VirtualAddress + pRVABase); _cffi_initialize_python(); return TRUE; } """) ffi.embedding_init_code(open("scratch-init.py", "r").read()) ffi.compile(target="scratch.dll", verbose=True) def test_it(): ffi = FFI() ffi.cdef(""" int _0(int, int); """) api = ffi.dlopen('scratch.dll') # why no api call here? print(api._0(1, 10)) # assert 3 == api._0(1, 2)
word32 pubKeySz); int wc_ed25519_size(ed25519_key* key); int wc_ed25519_sig_size(ed25519_key* key); int wc_ed25519_sign_msg(const byte* in, word32 inlen, byte* out, word32 *outlen, ed25519_key* key); int wc_ed25519_verify_msg(const byte* sig, word32 siglen, const byte* msg, word32 msglen, int* stat, ed25519_key* key); int wc_Ed25519PrivateKeyDecode(const byte*, word32*, ed25519_key*, word32); int wc_Ed25519KeyToDer(ed25519_key*, byte* output, word32 inLen); int wc_Ed25519PublicKeyDecode(const byte*, word32*, ed25519_key*, word32); int wc_Ed25519PublicKeyToDer(ed25519_key*, byte* output, word32 inLen, int with_AlgCurve); int wc_ed25519_import_public(const byte* in, word32 inLen, ed25519_key* key); int wc_ed25519_import_private_only(const byte* priv, word32 privSz, ed25519_key* key); int wc_ed25519_import_private_key(const byte* priv, word32 privSz, const byte* pub, word32 pubSz, ed25519_key* key); int wc_ed25519_export_public(ed25519_key*, byte* out, word32* outLen); int wc_ed25519_export_private_only(ed25519_key* key, byte* out, word32* outLen); int wc_ed25519_export_private(ed25519_key* key, byte* out, word32* outLen); int wc_ed25519_export_key(ed25519_key* key, byte* priv, word32 *privSz, byte* pub, word32 *pubSz); int wc_ed25519_check_key(ed25519_key* key); int wc_ed25519_pub_size(ed25519_key* key); int wc_ed25519_priv_size(ed25519_key* key); """ ) if __name__ == "__main__": ffi.compile(verbose=1)
""", include_dirs=['src'], extra_link_args=['/DEF:_xll.def'], #extra_compile_args=['/FAc'], sources=['src/DllMain.cpp'], ) ffi.embedding_api(''' extern "Python" int __stdcall xlAutoOpen(void); extern "Python" int __stdcall xlAutoClose(void); extern "Python" void __stdcall xlAutoFree12(LPXLOPER12); extern "Python" int __stdcall xlAutoAdd(void); extern "Python" int __stdcall xlAutoRemove(void); extern "Python" double __stdcall TheNumberOneInPy(); extern "Python" LPXLOPER12 __stdcall test_c_string(wchar_t*); extern "Python" LPXLOPER12 __stdcall os_environ(LPXLOPER12); ''') ffi.embedding_init_code(''' import sys try: import xll.addin except: sys.excepthook(*sys.exc_info()) raise ''') if __name__ == '__main__': ffi.compile(target='python.xll')
def load_ool_module(): """ Compile an out-of-line module, return the corresponding ffi and module objects. """ from cffi import FFI numba_complex = """ typedef struct _numba_complex { double real; double imag; } numba_complex; """ defs = numba_complex + """ double sin(double x); double cos(double x); int foo(int a, int b, int c); void vsSin(int n, float* x, float* y); void vdSin(int n, double* x, double* y); void vector_real(numba_complex *c, double *real, int n); void vector_imag(numba_complex *c, double *imag, int n); """ source = numba_complex + """ static int foo(int a, int b, int c) { return a + b * c; } void vsSin(int n, float* x, float* y) { int i; for (i=0; i<n; i++) y[i] = sin(x[i]); } void vdSin(int n, double* x, double* y) { int i; for (i=0; i<n; i++) y[i] = sin(x[i]); } static void vector_real(numba_complex *c, double *real, int n) { int i; for (i = 0; i < n; i++) real[i] = c[i].real; } static void vector_imag(numba_complex *c, double *imag, int n) { int i; for (i = 0; i < n; i++) imag[i] = c[i].imag; } """ ffi = FFI() ffi.set_source('cffi_usecases_ool', source) ffi.cdef(defs, override=True) tmpdir = temp_directory('test_cffi') ffi.compile(tmpdir=tmpdir) sys.path.append(tmpdir) try: mod = import_dynamic('cffi_usecases_ool') cffi_support.register_module(mod) cffi_support.register_type(mod.ffi.typeof('struct _numba_complex'), complex128) return mod.ffi, mod finally: sys.path.remove(tmpdir)
for (i=0; i<n; i++) y[i] = sin(x[i]); } void vdSin(int n, double* x, double* y) { int i; for (i=0; i<n; i++) y[i] = sin(x[i]); } """ ffi_ool = FFI() ffi.set_source('cffi_usecases_ool', source) ffi.cdef(defs, override=True) tmpdir = static_temp_directory('test_cffi') ffi.compile(tmpdir=tmpdir) sys.path.append(tmpdir) try: import cffi_usecases_ool cffi_support.register_module(cffi_usecases_ool) cffi_sin_ool = cffi_usecases_ool.lib.sin cffi_cos_ool = cffi_usecases_ool.lib.cos cffi_foo = cffi_usecases_ool.lib.foo vsSin = cffi_usecases_ool.lib.vsSin vdSin = cffi_usecases_ool.lib.vdSin finally: sys.path.remove(tmpdir) def use_cffi_sin(x): return cffi_sin(x) * 2
struct Point *points; unsigned int centroid_count; struct Centroid *centroids; unsigned int compression_count; }; extern struct TDigest *tdigest_new(unsigned int compression); extern void tdigest_add(struct TDigest *digest, double value, long long weight); extern void tdigest_merge(struct TDigest *digest1, struct TDigest *digest2); extern double tdigest_cdf(struct TDigest *digest, double value); extern double tdigest_quantile(struct TDigest *digest, double quantile); extern void tdigest_compress(struct TDigest *digest); extern void tdigest_free(struct TDigest *digest); """ source_directory = os.path.join(os.path.dirname(os.path.abspath(__file__)), "sources") tdigest_ffi = FFI() tdigest_ffi.cdef(CFFI_CDEF) with open(os.path.join(source_directory, "tdigest.c")) as tdigest_source_file: tdigest_ffi.set_source("tdigest._tdigest", tdigest_source_file.read(), include_dirs=[source_directory]) if __name__ == "__main__": tdigest_ffi.compile(verbose=True)
ffi = FFI() ffi.set_source('_rmath_ffi', '#include <Rmath.h>', include_dirs=include_dirs, sources=rmath_src, libraries=[], extra_compile_args=extra_compile_args) # This is an incomplete list of the available functions in Rmath # but these are sufficient for our example purposes and gives a sense of # the types of functions we can get ffi.cdef('''\ // Normal Distribution double dnorm(double, double, double, int); double pnorm(double, double, double, int, int); // Uniform Distribution double dunif(double, double, double, int); double punif(double, double, double, int, int); // Gamma Distribution double dgamma(double, double, double, int); double pgamma(double, double, double, int, int); ''') if __name__ == '__main__': # Normally set verbose to `True`, but silence output # for reduced notebook noise ffi.compile(verbose=False)
def compile(arch, bits, pypanda_headers, install, static_inc): #from ..ffi_importer import ffi from cffi import FFI ffi = FFI() ffi.set_source(f"panda_{arch}_{bits}", None) if install: import os include_dir = os.path.abspath( os.path.join(*[os.path.dirname(__file__), "pandare", "include"])) else: include_dir = static_inc def define_clean_header(ffi, fname): '''Convenience function to pull in headers from file in C''' #print("Pulling cdefs from ", fname) # CFFI can't handle externs, but sometimes we have to extern C (as opposed to r = open(fname).read() for line in r.split("\n"): assert ( "extern \"C\" {" not in line ), "Externs unsupported by CFFI. Change {} to a single line without braces".format( r) r = r.replace( "extern \"C\" ", "") # This allows inline externs like 'extern "C" void foo(...)' try: ffi.cdef(r) except Exception as e: # it's a cffi.CDefError, but cffi isn't imported print(f"\nError parsing header from {fname}\n") raise # For OSI ffi.cdef("typedef void GArray;") ffi.cdef("typedef int target_pid_t;") ffi.cdef("typedef uint" + str(bits) + "_t target_ulong;") ffi.cdef("typedef int" + str(bits) + "_t target_long;") # PPP Headers # Syscalls - load architecture-specific headers if arch == "i386": define_clean_header(ffi, include_dir + "/panda_datatypes_X86_32.h") define_clean_header(ffi, include_dir + "/syscalls_ext_typedefs_x86.h") elif arch == "x86_64": define_clean_header(ffi, include_dir + "/panda_datatypes_X86_64.h") define_clean_header(ffi, include_dir + "/syscalls_ext_typedefs_x64.h") elif arch == "arm": define_clean_header(ffi, include_dir + "/panda_datatypes_ARM_32.h") define_clean_header(ffi, include_dir + "/syscalls_ext_typedefs_arm.h") elif arch == "aarch64": # Could also do arch and bits==64 define_clean_header(ffi, include_dir + "/panda_datatypes_ARM_64.h") define_clean_header(ffi, include_dir + "/syscalls_ext_typedefs_arm64.h") elif arch == "ppc" and int(bits) == 32: define_clean_header(ffi, include_dir + "/panda_datatypes_PPC_32.h") print('WARNING: no syscalls support for PPC 32') elif arch == "ppc" and int(bits) == 64: define_clean_header(ffi, include_dir + "/panda_datatypes_PPC_64.h") print('WARNING: no syscalls support for PPC 64') elif arch == "mips" and int(bits) == 32: define_clean_header(ffi, include_dir + "/panda_datatypes_MIPS_32.h") define_clean_header(ffi, include_dir + "/syscalls_ext_typedefs_mips.h") elif arch == "mipsel" and int(bits) == 32: define_clean_header(ffi, include_dir + "/panda_datatypes_MIPS_32.h") # XXX? define_clean_header(ffi, include_dir + "/syscalls_ext_typedefs_mips.h") else: print("PANDA_DATATYPES: Architecture not supported") # Define some common panda datatypes define_clean_header(ffi, include_dir + "/panda_datatypes.h") # get some libc functionality define_clean_header(ffi, include_dir + "/libc_includes.h") # Now syscalls2 common: define_clean_header(ffi, include_dir + "/syscalls2_info.h") # A few more CFFI types now that we have common datatypes # Manually define syscall_ctx_t - taken from syscalls2/generated/syscalls_ext_typedefs.h # It uses a #DEFINES as part of the array size so CFFI can't hanle that : ffi.cdef(''' typedef struct syscall_ctx { ''' + f''' int no; /**< number */ target_ptr_t asid; /**< calling process asid */ target_ptr_t retaddr; /**< return address */ uint8_t args[{GLOBAL_MAX_SYSCALL_ARG_SIZE}] [{GLOBAL_MAX_SYSCALL_ARG_SIZE}]; /**< arguments */ ''' + ''' } syscall_ctx_t; ''') ffi.cdef("void panda_setup_signal_handling(void (*f) (int,void*,void*));", override=True) # MANUAL curated list of PPP headers define_clean_header(ffi, include_dir + "/syscalls_ext_typedefs.h") define_clean_header(ffi, include_dir + "/callstack_instr.h") define_clean_header(ffi, include_dir + "/hooks2_ppp.h") define_clean_header(ffi, include_dir + "/proc_start_linux_ppp.h") define_clean_header(ffi, include_dir + "/forcedexec_ppp.h") define_clean_header(ffi, include_dir + "/stringsearch_ppp.h") # END PPP headers define_clean_header(ffi, include_dir + "/breakpoints.h") for header in pypanda_headers: define_clean_header(ffi, header) # has to be at the end because it depends on something in list define_clean_header(ffi, include_dir + "/taint2.h") ffi.compile(verbose=True, debug=True, tmpdir='./pandare/autogen')
PangoFontDescription * pango_font_description_from_string (const char *str); void pango_font_description_set_family (PangoFontDescription *desc, const char *family); const char * pango_font_description_get_family (const PangoFontDescription *desc); void pango_font_description_set_absolute_size (PangoFontDescription *desc, double size); void pango_font_description_set_size (PangoFontDescription *desc, gint size); gint pango_font_description_get_size (const PangoFontDescription *desc); // https://developer.gnome.org/glib/stable/glib-Simple-XML-Subset-Parser.html gchar * g_markup_escape_text(const gchar *text, gssize length); """ ) if __name__ == "__main__": pango_ffi.compile()
ffiwrapper.cdef(''' void zyre_destroy_py (void *self); void zyre_event_destroy_py (void *self); ''') ffiwrapper.set_source("zyre.zyre_py_destructors", libraries=['zyre'], source=''' #include <zyre.h> void zyre_destroy_py (void *self) { zyre_destroy ((zyre_t **) &self); } void zyre_event_destroy_py (void *self) { zyre_event_destroy ((zyre_event_t **) &self); } ''') if __name__ == "__main__": ffi.compile() ffiwrapper.compile()
void registerPyReductionExtCallback(int (*cb)(char**, int*, int, char**)); void CkExtContributeToChare(struct ContributeInfo* contribute_params, int onPE, void* objPtr); void CkExtContributeToGroup(struct ContributeInfo* contribute_params, int gid, int pe); void CkExtContributeToArray(struct ContributeInfo* contribute_params, int aid, int* idx, int ndims); // callbacks to python extern "Python" void registerMainModule(void); extern "Python" void recvReadOnly_py2(int, char*); extern "Python" void recvReadOnly_py3(int, char*); extern "Python" void buildMainchare(int, void*, int, int, char **); extern "Python" void recvChareMsg_py2(int, void*, int, int, char*, int); extern "Python" void recvChareMsg_py3(int, void*, int, int, char*, int); extern "Python" void recvGroupMsg_py2(int, int, int, char *, int); extern "Python" void recvGroupMsg_py3(int, int, int, char *, int); extern "Python" void recvArrayMsg_py2(int, int, int *, int, int, char *, int); extern "Python" void recvArrayMsg_py3(int, int, int *, int, int, char *, int); extern "Python" int arrayElemLeave(int, int, int *, char**, int); extern "Python" void arrayElemJoin_py2(int, int, int *, int, char*, int); extern "Python" void arrayElemJoin_py3(int, int, int *, int, char*, int); extern "Python" void resumeFromSync(int, int, int *); extern "Python" void cpickleData_py2(void*, int, int, char**, int*); extern "Python" void cpickleData_py3(void*, int, int, char**, int*); extern "Python" int pyReduction_py2(char**, int*, int, char**); extern "Python" int pyReduction_py3(char**, int*, int, char**); """) if __name__ == "__main__": ffibuilder.compile(tmpdir='__cffi_objs__', verbose=True)
vbz_size_t vbz_max_compressed_size( vbz_size_t source_size, CompressionOptions const* options ); vbz_size_t vbz_decompressed_size( void const* source, vbz_size_t source_size, CompressionOptions const* options ); vbz_size_t vbz_compress_sized( void const* source, vbz_size_t source_size, void* destination, vbz_size_t destination_capacity, CompressionOptions const* options ); vbz_size_t vbz_decompress_sized( void const* source, vbz_size_t source_size, void* destination, vbz_size_t destination_capacity, CompressionOptions const* options ); """) if __name__ == "__main__": ffibuilder.compile()
g_markup_escape_text(const gchar *text, gssize length); """) xcursors_ffi = FFI() xcursors_ffi.set_source("libqtile._ffi_xcursors", None) xcursors_ffi.include(xcffib_ffi) xcursors_ffi.cdef(""" typedef uint32_t xcb_cursor_t; typedef struct xcb_cursor_context_t xcb_cursor_context_t; int xcb_cursor_context_new( xcb_connection_t *conn, xcb_screen_t *screen, xcb_cursor_context_t **ctx ); xcb_cursor_t xcb_cursor_load_cursor( xcb_cursor_context_t *ctx, const char *name ); void xcb_cursor_context_free(xcb_cursor_context_t *ctx); """) if __name__ == "__main__": pango_ffi.compile() xcursors_ffi.compile()
def test_cffi_assembly(): mesh = UnitSquareMesh(MPI.COMM_WORLD, 13, 13) V = FunctionSpace(mesh, ("Lagrange", 1)) if mesh.mpi_comm().rank == 0: from cffi import FFI ffibuilder = FFI() ffibuilder.set_source( "_cffi_kernelA", r""" #include <math.h> #include <stdalign.h> void tabulate_tensor_poissonA(double* restrict A, const double* w, const double* c, const double* restrict coordinate_dofs, const int* entity_local_index, const int* cell_orientation) { // Precomputed values of basis functions and precomputations // FE* dimensions: [entities][points][dofs] // PI* dimensions: [entities][dofs][dofs] or [entities][dofs] // PM* dimensions: [entities][dofs][dofs] alignas(32) static const double FE3_C0_D01_Q1[1][1][2] = { { { -1.0, 1.0 } } }; // Unstructured piecewise computations const double J_c0 = coordinate_dofs[0] * FE3_C0_D01_Q1[0][0][0] + coordinate_dofs[2] * FE3_C0_D01_Q1[0][0][1]; const double J_c3 = coordinate_dofs[1] * FE3_C0_D01_Q1[0][0][0] + coordinate_dofs[5] * FE3_C0_D01_Q1[0][0][1]; const double J_c1 = coordinate_dofs[0] * FE3_C0_D01_Q1[0][0][0] + coordinate_dofs[4] * FE3_C0_D01_Q1[0][0][1]; const double J_c2 = coordinate_dofs[1] * FE3_C0_D01_Q1[0][0][0] + coordinate_dofs[3] * FE3_C0_D01_Q1[0][0][1]; alignas(32) double sp[20]; sp[0] = J_c0 * J_c3; sp[1] = J_c1 * J_c2; sp[2] = sp[0] + -1 * sp[1]; sp[3] = J_c0 / sp[2]; sp[4] = -1 * J_c1 / sp[2]; sp[5] = sp[3] * sp[3]; sp[6] = sp[3] * sp[4]; sp[7] = sp[4] * sp[4]; sp[8] = J_c3 / sp[2]; sp[9] = -1 * J_c2 / sp[2]; sp[10] = sp[9] * sp[9]; sp[11] = sp[8] * sp[9]; sp[12] = sp[8] * sp[8]; sp[13] = sp[5] + sp[10]; sp[14] = sp[6] + sp[11]; sp[15] = sp[12] + sp[7]; sp[16] = fabs(sp[2]); sp[17] = sp[13] * sp[16]; sp[18] = sp[14] * sp[16]; sp[19] = sp[15] * sp[16]; // UFLACS block mode: preintegrated A[0] = 0.5 * sp[19] + 0.5 * sp[18] + 0.5 * sp[18] + 0.5 * sp[17]; A[1] = -0.5 * sp[19] + -0.5 * sp[18]; A[2] = -0.5 * sp[18] + -0.5 * sp[17]; A[3] = -0.5 * sp[19] + -0.5 * sp[18]; A[4] = 0.5 * sp[19]; A[5] = 0.5 * sp[18]; A[6] = -0.5 * sp[18] + -0.5 * sp[17]; A[7] = 0.5 * sp[18]; A[8] = 0.5 * sp[17]; } void tabulate_tensor_poissonL(double* restrict A, const double* w, const double* c, const double* restrict coordinate_dofs, const int* entity_local_index, const int* cell_orientation) { // Precomputed values of basis functions and precomputations // FE* dimensions: [entities][points][dofs] // PI* dimensions: [entities][dofs][dofs] or [entities][dofs] // PM* dimensions: [entities][dofs][dofs] alignas(32) static const double FE4_C0_D01_Q1[1][1][2] = { { { -1.0, 1.0 } } }; // Unstructured piecewise computations const double J_c0 = coordinate_dofs[0] * FE4_C0_D01_Q1[0][0][0] + coordinate_dofs[2] * FE4_C0_D01_Q1[0][0][1]; const double J_c3 = coordinate_dofs[1] * FE4_C0_D01_Q1[0][0][0] + coordinate_dofs[5] * FE4_C0_D01_Q1[0][0][1]; const double J_c1 = coordinate_dofs[0] * FE4_C0_D01_Q1[0][0][0] + coordinate_dofs[4] * FE4_C0_D01_Q1[0][0][1]; const double J_c2 = coordinate_dofs[1] * FE4_C0_D01_Q1[0][0][0] + coordinate_dofs[3] * FE4_C0_D01_Q1[0][0][1]; alignas(32) double sp[4]; sp[0] = J_c0 * J_c3; sp[1] = J_c1 * J_c2; sp[2] = sp[0] + -1 * sp[1]; sp[3] = fabs(sp[2]); // UFLACS block mode: preintegrated A[0] = 0.1666666666666667 * sp[3]; A[1] = 0.1666666666666667 * sp[3]; A[2] = 0.1666666666666667 * sp[3]; } """) ffibuilder.cdef(""" void tabulate_tensor_poissonA(double* restrict A, const double* w, const double* c, const double* restrict coordinate_dofs, const int* entity_local_index, const int* cell_orientation); void tabulate_tensor_poissonL(double* restrict A, const double* w, const double* c, const double* restrict coordinate_dofs, const int* entity_local_index, const int* cell_orientation); """) ffibuilder.compile(verbose=True) mesh.mpi_comm().Barrier() from _cffi_kernelA import ffi, lib a = cpp.fem.Form([V._cpp_object, V._cpp_object]) ptrA = ffi.cast("intptr_t", ffi.addressof(lib, "tabulate_tensor_poissonA")) a.set_tabulate_tensor(IntegralType.cell, -1, ptrA) L = cpp.fem.Form([V._cpp_object]) ptrL = ffi.cast("intptr_t", ffi.addressof(lib, "tabulate_tensor_poissonL")) L.set_tabulate_tensor(IntegralType.cell, -1, ptrL) A = dolfinx.fem.assemble_matrix(a) A.assemble() b = dolfinx.fem.assemble_vector(L) b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE) Anorm = A.norm(PETSc.NormType.FROBENIUS) bnorm = b.norm(PETSc.NormType.N2) assert (np.isclose(Anorm, 56.124860801609124)) assert (np.isclose(bnorm, 0.0739710713711999)) list_timings(MPI.COMM_WORLD, [TimingType.wall])
taco_tensor_t create_tensor(); taco_tensor_t* create_pointer_to_tensor(); """) ffi.set_source( 'taco_kernel', taco_define_header + taco_type_header + source, extra_compile_args=['-Wno-unused-variable', '-Wno-unknown-pragmas']) expected_tensor = Tensor.from_lol([[6, 0, 9, 8], [0, 0, 0, 0], [5, 0, 0, 7]], format='ds') with tempfile.TemporaryDirectory() as temp_dir: # Lock because FFI.compile is not thread safe: https://foss.heptapod.net/pypy/cffi/-/issues/490 with lock: # Create shared object in temporary directory lib_path = ffi.compile(tmpdir=temp_dir) # Load the shared object lib = ffi.dlopen(lib_path) def test_take_ownership_of_tensor_on_returned_struct(): cffi_tensor = lib.create_tensor() take_ownership_of_tensor_members(cffi_tensor) tensor = Tensor(cffi_tensor) assert tensor == expected_tensor def test_take_ownership_of_tensor_on_returned_pointer_to_struct(): cffi_tensor = lib.create_pointer_to_tensor() take_ownership_of_tensor(cffi_tensor)
ioinc = "-I." sotarget = './_libmar345.{}.{}.so'.format(platform.system(), platform.machine()) else: pre = "C/" ioinc = "-IC" sotarget = 'lib/_libmar345.{}.{}.so'.format(platform.system(), platform.machine()) with open(pre + "marpck.h") as f: ffibuilder.cdef(f.read()) ffibuilder.set_source("_libmar345", """ #include "marpck.h" """, sources=[pre + 'marpck.c'], extra_compile_args=['-g', '-fPIC']) ffibuilder.compile(verbose=True, target=sotarget) if __name__ == "__main__": if platform.system() == "Darwin": sotarget = "../mario/_libmar345.cpython-{}{}-darwin.so".format( V[0], V[1]) elif platform.system() == "Windows": sotarget = "../mario/_libmar345.pyd" else: sotarget = "../mario/_libmar345.so" print("Shared library: {}".format(sotarget)) ffibuilder.compile(verbose=True, target=sotarget)
void* wolfSSLv23_server_method(void); void* wolfSSLv23_client_method(void); void* wolfTLSv1_2_server_method(void); void* wolfTLSv1_2_client_method(void); void* wolfSSL_CTX_new(void*); void wolfSSL_CTX_free(void*); void wolfSSL_CTX_set_verify(void*, int, void*); int wolfSSL_CTX_set_cipher_list(void*, const char*); int wolfSSL_CTX_use_PrivateKey_file(void*, const char*, int); int wolfSSL_CTX_load_verify_locations(void*, const char*, const char*); int wolfSSL_CTX_load_verify_buffer(void*, const unsigned char*, long, int); int wolfSSL_CTX_use_certificate_chain_file(void*, const char *); int wolfSSL_CTX_UseSupportedCurve(void*, short); void* wolfSSL_new(void*); void wolfSSL_free(void*); int wolfSSL_set_fd(void*, int); int wolfSSL_get_error(void*, int); int wolfSSL_negotiate(void*); int wolfSSL_write(void*, const void*, int); int wolfSSL_read(void*, void*, int); int wolfSSL_shutdown(void*); """) if __name__ == "__main__": ffi.compile(verbose=1)
blake2b_ffi = FFI() blake2b_ffi.cdef(blake_cdef) blake2b_ffi.set_source( '_blake2b_cffi', blake2b_source, sources=sourcesB, include_dirs=[_libdir], extra_compile_args=extra_compile_args, define_macros=define_macros, ) def _replace_b2s(src): for b, s in (('blake2b', 'blake2s'), ('BLAKE2B', 'BLAKE2S')): src = src.replace(b, s) return src blake2s_ffi = FFI() blake2s_ffi.cdef(blake_cdef) blake2s_ffi.set_source( '_blake2s_cffi', _replace_b2s(blake2b_source), sources=sourcesS, include_dirs=[_libdir], extra_compile_args=extra_compile_args, define_macros=define_macros, ) if __name__ == '__main__': os.chdir(os.path.dirname(__file__)) blake2b_ffi.compile() blake2s_ffi.compile()
void pango_font_description_free (PangoFontDescription *desc); PangoFontDescription * pango_font_description_from_string (const char *str); void pango_font_description_set_family (PangoFontDescription *desc, const char *family); const char * pango_font_description_get_family (const PangoFontDescription *desc); void pango_font_description_set_absolute_size (PangoFontDescription *desc, double size); void pango_font_description_set_size (PangoFontDescription *desc, gint size); gint pango_font_description_get_size (const PangoFontDescription *desc); // https://developer.gnome.org/glib/stable/glib-Simple-XML-Subset-Parser.html gchar * g_markup_escape_text(const gchar *text, gssize length); """) if __name__ == "__main__": pango_ffi.compile()
class SGXInterface: def __init__(self): self.ffi = FFI() dir_path = os.path.dirname(os.path.realpath(__file__)) with open(os.path.join(dir_path, "sgx.h")) as stream: self.ffi.cdef(stream.read()) self.ffi.set_source( "_sgx_interface", """ #include "sgx_eid.h" #include "sgx_key_exchange.h" #include "common.h" #include "network_ra.h" #include "barbie_server.h" #include "barbie_client.h" #include "ra_client.h" #include "ra_server.h" #include <stdbool.h> #include "service_provider.h" """, include_dirs=['/usr/include', '/opt/intel/sgxsdk/include'], library_dirs=['/usr/local/lib', '/opt/intel/sgxsdk/lib64/'], libraries=["sample_libcrypto", "BarbiE_Client", "BarbiE_Server"]) self.ffi.compile(tmpdir=dir_path) libuae = self.ffi.dlopen("sgx_uae_service", self.ffi.RTLD_GLOBAL) liburts = self.ffi.dlopen("sgx_urts", self.ffi.RTLD_GLOBAL) libcrypto = self.ffi.dlopen("sample_libcrypto", self.ffi.RTLD_GLOBAL) self.barbie_s = self.ffi.dlopen("BarbiE_Server", self.ffi.RTLD_LAZY) self.barbie_c = self.ffi.dlopen("BarbiE_Client", self.ffi.RTLD_LAZY) self.iv = 12 self.mac = 16 def init_env_variables(self): separator = "=" with open("/opt/BarbiE/env.properties") as f: for line in f: if separator in line: name, value = line.split(separator) os.environ[name.strip()] = value.strip() def init_enclave(self, target_lib): try: p_enclave_id = self.ffi.new("sgx_enclave_id_t *") status = target_lib.initialize_enclave(p_enclave_id) return p_enclave_id[0] except Exception as e: raise Exception("Error in initializing enclave!", e) def generate_key_pair(self, key_dir): pub_key_path = os.path.join(key_dir, "public_key.pem") priv_key_path = os.path.join(key_dir, "private_key.pem") if not os.path.exists(pub_key_path) and not os.path.exists( priv_key_path): priv_key = SigningKey.generate(curve=NIST256p) pub_key = priv_key.get_verifying_key() open(priv_key_path, "w").write(priv_key.to_pem()) open(pub_key_path, "w").write(pub_key.to_pem()) else: priv_key = SigningKey.from_pem(open(priv_key_path).read()) pub_key = VerifyingKey.from_pem(open(pub_key_path).read()) pk64 = pub_key.to_string() pk_x, pk_y = pk64[:len(pk64) / 2], pk64[len(pk64) / 2:] hex_priv_key = priv_key.to_string() hex_sk = hex_priv_key.encode('hex') pk_x = pk_x.encode('hex') pk_y = pk_y.encode('hex') hex_priv_key_out = [hex_sk[i:i + 2] for i in range(0, len(hex_sk), 2)] pk_x_out = [pk_x[i:i + 2] for i in range(0, len(pk_x), 2)] pk_y_out = [pk_y[i:i + 2] for i in range(0, len(pk_y), 2)] pk_x_out.reverse() pk_y_out.reverse() pub_key = "" for i in range(len(pk_x_out)): pub_key = pub_key + pk_x_out[i] for i in range(len(pk_y_out)): pub_key = pub_key + pk_y_out[i] hex_priv_key_out.reverse() priv_key = "" for i in range(len(hex_priv_key_out)): priv_key = priv_key + hex_priv_key_out[i] pub_key = base64.b64encode(pub_key + '\0') priv_key = base64.b64encode(priv_key + '\0') return pub_key, priv_key def get_crt(self, resp_crt=None): pattern = '-----END CERTIFICATE-----\n' crt = resp_crt.split(pattern) return crt[0] + pattern, crt[1] + pattern def verify_certificate(self, crt=None, cacrt=None): try: cert = load_certificate(FILETYPE_PEM, crt) intermediate_cert = load_certificate(FILETYPE_PEM, cacrt) validation_cert = load_certificate(FILETYPE_PEM, cacrt) store = X509Store() store.add_cert(intermediate_cert) store.add_cert(cert) store_ctx = X509StoreContext(store, validation_cert) if (store_ctx.verify_certificate() == None): print "Certificate verification Passed on Client side" return True else: raise Exception( "Certificate Verification Failed on Client side") except Exception as e: raise Exception("Certificate Validation Failed on Client side", e) def verify_signature(self, crt=None, sign=None, resp_body=None): try: x509 = load_certificate(FILETYPE_PEM, crt) pub_key = x509.get_pubkey() ias_public_key = dump_publickey(FILETYPE_PEM, pub_key) public_key = load_publickey(FILETYPE_PEM, ias_public_key) x509 = X509() x509.set_pubkey(public_key) if verify(x509, base64.b64decode(sign), resp_body, 'sha256') == None: print "Signature verification Passed on Client side" return True except Exception as e: raise Exception("Signature verification Failed on Client side", e) def gen_msg0(self, target_lib, spid=None): try: p_ctxt = self.ffi.new("sgx_ra_context_t *") p_req0 = self.ffi.new("ra_samp_msg0_request_header_t **") ret = target_lib.gen_msg0(p_req0, spid) msg0 = base64.b64encode(self.ffi.buffer(p_req0[0])) return ret, msg0 except Exception as e: raise Exception("Error in generating msg0", e) def proc_msg0(self, target_lib, msg0, spid=None, client_verify_ias=False): try: if spid is None: spid = self.ffi.NULL msg0 = self.ffi.from_buffer(base64.b64decode(msg0)) p_net_ctxt = self.ffi.new("void **") ret = target_lib.proc_msg0(msg0, p_net_ctxt, spid, client_verify_ias) return ret, p_net_ctxt except Exception as e: raise Exception("Error in processing msg0", e) def gen_msg1(self, target_lib, enclave_id, pub_key): try: if pub_key != None: pub_key = base64.b64decode(pub_key) key = self.ffi.new("char[]", pub_key) else: key = self.ffi.NULL p_ctxt = self.ffi.new("sgx_ra_context_t *") p_req1 = self.ffi.new("ra_samp_msg1_request_header_t **") target_lib.gen_msg1(enclave_id, p_ctxt, p_req1, key) msg1 = base64.b64encode(self.ffi.buffer(p_req1[0])) return p_ctxt[0], msg1 except Exception as e: raise Exception("Error in generating msg1", e) def proc_msg1_gen_msg2(self, target_lib, msg1, p_net_ctxt, priv_key): try: if priv_key != None: priv_key = base64.b64decode(priv_key) key = self.ffi.new("char[]", priv_key) else: key = self.ffi.NULL msg1 = self.ffi.from_buffer(base64.b64decode(msg1)) pp_resp1 = self.ffi.new("ra_samp_msg1_response_header_t **") target_lib.proc_msg1(msg1, p_net_ctxt, pp_resp1, key) msg2 = base64.b64encode(self.ffi.buffer(pp_resp1[0])) return msg2 except Exception as e: raise Exception("Error in generating msg2", e) def proc_msg2_gen_msg3(self, target_lib, enclave_id, msg2, p_ctxt, ias_crt=None, client_verify_ias=False, server_verify_ias=False): try: if ias_crt is None: ias_crt = self.ffi.NULL msg2 = self.ffi.from_buffer(base64.b64decode(msg2)) pp_req2 = self.ffi.new("ra_samp_msg3_request_header_t **") resp_crt = self.ffi.new("uint8_t[]", 4000) resp_sign = self.ffi.new("uint8_t[]", 500) resp_body = self.ffi.new("uint8_t[]", 1200) if not server_verify_ias and not client_verify_ias: server_verify_ias = True status = target_lib.gen_msg3(enclave_id, p_ctxt, msg2, pp_req2, ias_crt, client_verify_ias, server_verify_ias, resp_crt, resp_sign, resp_body) if status != 3: msg3 = base64.b64encode(self.ffi.buffer(pp_req2[0])) else: raise Exception("IAS verification failed") return (msg3, self.ffi.string(resp_crt), self.ffi.string(resp_sign), self.ffi.string(resp_body)) except Exception as e: raise Exception("Error in generating msg3", e) def proc_msg3_gen_msg4(self, target_lib, enclave_id, s_msg3, p_net_ctxt, sealed_sk, c_msg3, project_id=None, owner_mr_e=None, ias_crt=None, client_verify_ias=False): try: if ias_crt is None: ias_crt = self.ffi.NULL if owner_mr_e is None: owner_mr_e = self.ffi.NULL else: owner_mr_e = self.ffi.from_buffer(base64.b64decode(owner_mr_e)) s_msg3 = self.ffi.from_buffer(base64.b64decode(s_msg3)) c_msg3 = self.ffi.from_buffer(base64.b64decode(c_msg3)) if sealed_sk is None: sealed_len = 0 sealed_sk = self.ffi.NULL else: sealed_len = sealed_sk.length sealed_sk = self.ffi.from_buffer( base64.b64decode(sealed_sk.value)) if project_id is None: project_id_len = 0 project_id = self.ffi.NULL else: project_id_len = len(project_id) pp_resp2 = self.ffi.new("ra_samp_msg3_response_header_t **") target_lib.set_enclave(p_net_ctxt, enclave_id) target_lib.set_secret(p_net_ctxt, sealed_sk, sealed_len, self.ffi.NULL, 0) status = target_lib.proc_msg3(s_msg3, p_net_ctxt, pp_resp2, c_msg3, project_id, owner_mr_e, ias_crt, client_verify_ias) #Initially using 177 length of msg4 but #after adding project id to msg4 using (209 + project id length) for msg4 if status != 3: msg4 = base64.b64encode( self.ffi.buffer(pp_resp2[0], (417 + project_id_len))) else: raise Exception("IAS call failed") return msg4 except Exception as e: raise Exception("Error in generating msg4", e) def legacy_proc_msg3_gen_msg4(self, target_lib, msg3, p_net_ctxt, project_id=None, owner_mr_e=None, ias_crt=None, client_verify_ias=False): try: if ias_crt is None: ias_crt = self.ffi.NULL if owner_mr_e is None: owner_mr_e = self.ffi.NULL else: owner_mr_e = self.ffi.from_buffer(base64.b64decode(owner_mr_e)) if project_id is None: project_id_len = 0 project_id = self.ffi.NULL else: project_id_len = len(project_id) msg3 = self.ffi.from_buffer(base64.b64decode(msg3)) pp_resp2 = self.ffi.new("ra_samp_msg3_response_header_t **") target_lib.set_secret(p_net_ctxt, self.ffi.NULL, 0, self.ffi.NULL, 0) status = target_lib.proc_msg3(msg3, p_net_ctxt, pp_resp2, self.ffi.NULL, project_id, owner_mr_e, ias_crt, client_verify_ias) #Initially using 177 length of msg4 but #after adding project id to msg4 using (209 + project id length) for msg4 if status != 3: msg4 = base64.b64encode( self.ffi.buffer(pp_resp2[0], (417 + project_id_len))) else: raise Exception("IAS call failed") return msg4 except Exception as e: raise Exception("Error in generating msg4", e) def proc_msg4(self, target_lib, enclave_id, msg4, p_ctxt, sealed_nonse): try: plain_sk_len = 16 sealed_len = target_lib.get_sealed_data_len( enclave_id, 0, plain_sk_len) sealed_nonse = self.ffi.from_buffer( base64.b64decode(sealed_nonse.value)) #Length is 0 as this will not be output variable sealed_nonse_len = 0 msg4 = self.ffi.from_buffer(base64.b64decode(msg4)) sealed_secret2 = self.ffi.new("uint8_t[]", sealed_len) status = target_lib.proc_ra(enclave_id, p_ctxt, msg4, sealed_nonse, sealed_nonse_len, sealed_secret2, sealed_len) secret2_buf = base64.b64encode(self.ffi.buffer(sealed_secret2)) target_lib.close_ra(enclave_id, p_ctxt) return status, secret2_buf except Exception as e: raise Exception( "Error in prcessing msg4 and retrieving sealed session key", e) def get_dh_key(self, target_lib, enclave_id, msg4, p_ctxt): try: msg4 = self.ffi.from_buffer(base64.b64decode(msg4)) plain_sk_len = 16 sealed_len = target_lib.get_sealed_data_len( enclave_id, 0, plain_sk_len) sealed_dh = self.ffi.new("uint8_t[]", sealed_len) status = target_lib.get_dh_key( enclave_id, p_ctxt, msg4, sealed_dh, self.ffi.cast("uint32_t", sealed_len)) dh_buf = base64.b64encode(self.ffi.buffer(sealed_dh)) #target_lib.close_ra(enclave_id, p_ctxt) return status, dh_buf except Exception as e: raise Exception("Error in get_dh_key", e) def get_project_id(self, target_lib, enclave_id, msg4, p_ctxt): try: msg4 = self.ffi.from_buffer(base64.b64decode(msg4)) proj_id_len = self.ffi.cast("uint32_t", 0) proj_id_len = target_lib.get_project_id_len( enclave_id, p_ctxt, msg4) proj_id = self.ffi.new("uint8_t[]", proj_id_len) status = target_lib.get_project_id(enclave_id, p_ctxt, msg4, proj_id) return proj_id, proj_id_len except Exception as e: raise Exception("Error in geting project id", e) def get_sk(self, target_lib, p_net_ctx, enc_sk): #todo extract iv and mac, call target_lib.get_sk and return plain sk try: b64_iv = 16 b64_mac = 24 iv = self.ffi.from_buffer(base64.b64decode(enc_sk[:b64_iv])) mac = self.ffi.from_buffer( base64.b64decode(enc_sk[b64_iv:(b64_iv + b64_mac)])) dh_sk = self.ffi.from_buffer( base64.b64decode(enc_sk[(b64_iv + b64_mac):])) plain_sk = self.ffi.new("uint8_t[]", 16) status = target_lib.get_sk(p_net_ctx, plain_sk, 16, dh_sk, iv, mac) return Secret(self.ffi.string(plain_sk, 16), 16) except Exception as e: raise Exception("Error in get_sk", e) def generate_key(self, target_lib, enclave_id, key_len): try: sealed_len = target_lib.get_sealed_data_len(enclave_id, 0, key_len) sealed_key = self.ffi.new("uint8_t[]", sealed_len) target_lib.crypto_generate_key(enclave_id, key_len, sealed_key, sealed_len) #use these api's to determine required plain text buffer given a sealed buffer #add mac always 0 for now #add_mac_len = target_lib.get_add_mac_len(enclave_id, sealed_key, sealed_len) #plain_len = target_lib.get_encrypted_len(enclave_id, sealed_key, sealed_len) return Secret(base64.b64encode(self.ffi.buffer(sealed_key)), sealed_len) except Exception as e: raise Exception("Error in generating key", e) def provision_kek(self, target_lib, enclave_id, sealed_sk, sk_kek, project_id=None): try: if project_id is None: project_id = self.ffi.NULL proj_id_len = 0 else: proj_id_len = len(project_id) b64_iv = 16 b64_mac = 24 sealed_len = sealed_sk.length sealed_sk = self.ffi.from_buffer(base64.b64decode(sealed_sk.value)) iv = self.ffi.from_buffer(base64.b64decode(sk_kek[:b64_iv])) mac = self.ffi.from_buffer( base64.b64decode(sk_kek[b64_iv:(b64_iv + b64_mac)])) sk_kek = self.ffi.from_buffer( base64.b64decode(sk_kek[(b64_iv + b64_mac):])) plain_kek_len = len(sk_kek) sealed_kek_len = target_lib.get_sealed_data_len( enclave_id, 0, plain_kek_len) sealed_kek = self.ffi.new("uint8_t[]", sealed_kek_len) target_lib.crypto_provision_kek(enclave_id, sealed_sk, sealed_len, sk_kek, plain_kek_len, iv, mac, sealed_kek, sealed_kek_len, project_id, proj_id_len) return base64.b64encode(self.ffi.buffer(sealed_kek)) except Exception as e: raise Exception("Error in provisioning of kek", e) def legacy_encrypt(self, target_lib, plain_sk, secret): try: iv = self.ffi.new("uint8_t[]", self.iv) mac = self.ffi.new("uint8_t[]", self.mac) enc_secret = self.ffi.new("uint8_t[]", secret.length) target_lib.crypto_legacy_encrypt(plain_sk.value, plain_sk.length, secret.value, secret.length, enc_secret, iv, mac) return base64.b64encode(self.ffi.buffer(iv)) + base64.b64encode( self.ffi.buffer(mac)) + base64.b64encode( self.ffi.buffer(enc_secret)) except Exception as e: raise Exception("ERROR: Encryption of the secret failed!", e) def legacy_decrypt(self, plain_sk, enc_secret): try: b64_iv = 16 b64_mac = 24 iv = base64.b64decode(enc_secret[:b64_iv]) mac = base64.b64decode(enc_secret[b64_iv:(b64_iv + b64_mac)]) enc_secret = base64.b64decode(enc_secret[(b64_iv + b64_mac):]) cipher = AES.new(plain_sk, AES.MODE_GCM, iv) dec_secret = cipher.decrypt(enc_secret) #cipher.verify(mac) return base64.b64encode(dec_secret) except Exception as e: raise Exception("ERROR: Legacy Decryption of the secret failed!", e) def encrypt(self, target_lib, enclave_id, sealed_sk, secret): try: iv = self.ffi.new("uint8_t[]", self.iv) mac = self.ffi.new("uint8_t[]", self.mac) sealed_len = sealed_sk.length sealed_sk = self.ffi.from_buffer(base64.b64decode(sealed_sk.value)) enc_secret = self.ffi.new("uint8_t[]", secret.length) target_lib.crypto_encrypt(enclave_id, sealed_sk, sealed_len, secret.value, secret.length, enc_secret, iv, mac) return base64.b64encode(self.ffi.buffer(iv)) + base64.b64encode( self.ffi.buffer(mac)) + base64.b64encode( self.ffi.buffer(enc_secret)) except Exception as e: raise Exception("ERROR: Encryption of the secret failed!", e) def decrypt(self, target_lib, enclave_id, sealed_sk, enc_secret): try: b64_iv = 16 b64_mac = 24 iv = self.ffi.from_buffer(base64.b64decode(enc_secret[:b64_iv])) mac = self.ffi.from_buffer( base64.b64decode(enc_secret[b64_iv:(b64_iv + b64_mac)])) enc_secret = self.ffi.from_buffer( base64.b64decode(enc_secret[(b64_iv + b64_mac):])) length = len(enc_secret) sealed_len = sealed_sk.length sealed_sk = self.ffi.from_buffer(base64.b64decode(sealed_sk.value)) secret = self.ffi.new("uint8_t[]", length) target_lib.crypto_decrypt(enclave_id, sealed_sk, sealed_len, secret, length, enc_secret, iv, mac, self.ffi.NULL, 0) return base64.b64encode(self.ffi.buffer(secret)) except Exception as e: raise Exception("ERROR: Decryption of the secret failed!", e) def transport(self, target_lib, enclave_id, sealed_kek, sealed_sk, project_id=None): try: if project_id is None: project_id = self.ffi.NULL proj_id_len = 0 else: proj_id_len = len(project_id) iv = self.ffi.new("uint8_t[]", self.iv) mac = self.ffi.new("uint8_t[]", self.mac) sealed_kek_len = sealed_kek.length sealed_kek = self.ffi.from_buffer( base64.b64decode(sealed_kek.value)) sealed_sk_len = sealed_sk.length sealed_sk = self.ffi.from_buffer(base64.b64decode(sealed_sk.value)) sk_len = target_lib.get_encrypted_len(enclave_id, sealed_sk, sealed_sk_len) kek_sk = self.ffi.new("uint8_t[]", sk_len) target_lib.crypto_transport_secret(enclave_id, sealed_kek, sealed_kek_len, sealed_sk, sealed_sk_len, kek_sk, sk_len, iv, mac, project_id, proj_id_len) return base64.b64encode(self.ffi.buffer(iv)) + base64.b64encode( self.ffi.buffer(mac)) + base64.b64encode( self.ffi.buffer(kek_sk)) except Exception as e: raise Exception("Error in transporting the secret", e) #no need for target lib, server action only def kek_encrypt(self, enclave_id, kek_sk, sealed_kek, sk_secret, project_id=None): try: if project_id is None: project_id = self.ffi.NULL proj_id_len = 0 else: proj_id_len = len(project_id) b64_iv = 16 b64_mac = 24 iv1 = self.ffi.from_buffer(base64.b64decode(kek_sk[:b64_iv])) mac1 = self.ffi.from_buffer( base64.b64decode(kek_sk[b64_iv:(b64_iv + b64_mac)])) kek_sk = self.ffi.from_buffer( base64.b64decode(kek_sk[(b64_iv + b64_mac):])) sealed_kek_len = sealed_kek.length sealed_kek = self.ffi.from_buffer( base64.b64decode(sealed_kek.value)) iv = self.ffi.from_buffer(base64.b64decode(sk_secret[:b64_iv])) mac = self.ffi.from_buffer( base64.b64decode(sk_secret[b64_iv:(b64_iv + b64_mac)])) sk_secret = self.ffi.from_buffer( base64.b64decode(sk_secret[(b64_iv + b64_mac):])) length = len(sk_secret) kek_secret = self.ffi.new("uint8_t[]", length) self.barbie_s.crypto_store_secret(enclave_id, kek_sk, len(kek_sk), iv1, mac1, sealed_kek, sealed_kek_len, sk_secret, length, kek_secret, length, iv, mac, str(project_id), proj_id_len) return base64.b64encode(self.ffi.buffer(iv)) + base64.b64encode( self.ffi.buffer(mac)) + base64.b64encode( self.ffi.buffer(kek_secret)) except Exception as e: raise Exception("Error in encrypting the secret with kek", e) #no need for target lib, server action only def kek_decrypt(self, enclave_id, kek_sk, sealed_kek, kek_secret, project_id=None): try: if project_id is None: project_id = self.ffi.NULL proj_id_len = 0 else: proj_id_len = len(project_id) b64_iv = 16 b64_mac = 24 iv1 = self.ffi.from_buffer(base64.b64decode(kek_sk[:b64_iv])) mac1 = self.ffi.from_buffer( base64.b64decode(kek_sk[b64_iv:(b64_iv + b64_mac)])) kek_sk = self.ffi.from_buffer( base64.b64decode(kek_sk[(b64_iv + b64_mac):])) sealed_kek_len = sealed_kek.length sealed_kek = self.ffi.from_buffer( base64.b64decode(sealed_kek.value)) iv = self.ffi.from_buffer(base64.b64decode(kek_secret[:b64_iv])) mac = self.ffi.from_buffer( base64.b64decode(kek_secret[b64_iv:(b64_iv + b64_mac)])) kek_secret = self.ffi.from_buffer( base64.b64decode(kek_secret[(b64_iv + b64_mac):])) length = len(kek_secret) sk_secret = self.ffi.new("uint8_t[]", length) self.barbie_s.crypto_get_secret(enclave_id, kek_sk, len(kek_sk), iv1, mac1, sealed_kek, sealed_kek_len, kek_secret, length, sk_secret, length, iv, mac, str(project_id), proj_id_len) return base64.b64encode(self.ffi.buffer(iv)) + base64.b64encode( self.ffi.buffer(mac)) + base64.b64encode( self.ffi.buffer(sk_secret)) except Exception as e: raise Exception("Error in decrypting the secret with kek", e) def compare_secret(self, target_lib, secret1, secret2, secret_len): try: secret1 = self.ffi.from_buffer(base64.b64decode(secret1)) secret2 = self.ffi.from_buffer(base64.b64decode(secret2)) if target_lib.crypto_cmp(secret1, secret2, secret_len) == 0: return True return False except Exception as e: raise Exception("Error in comparing the secrets", e) def compare_sealed_secret(self, target_lib, encalve_id, secret1, secret2): try: secret1 = self.ffi.from_buffer(base64.b64decode(secret1)) secret2 = self.ffi.from_buffer(base64.b64decode(secret2)) if target_lib.crypto_sealed_cmp(encalve_id, secret1, len(secret1), secret2, len(secret2)) == 0: return True return False except Exception as e: raise Exception("Error in comparing the sealed secrets", e) def compare_sealed_secret(self, target_lib, enclave_id, secret1, secret2): try: secret1 = self.ffi.from_buffer(base64.b64decode(secret1)) secret2 = self.ffi.from_buffer(base64.b64decode(secret2)) if target_lib.crypto_sealed_cmp(enclave_id, secret1, len(secret1), secret2, len(secret2)) == 0: return True return False except Exception as e: raise Exception("Error in comparing the sealed secrets", e) def destroy_enclave(self, target_lib, enclave_id): try: target_lib.destroy_enclave(enclave_id) except Exception as e: raise Exception("Error in destroying enclave!", e) def write_buffer_to_file(self, filename, buff): try: dir_path = os.path.dirname(os.path.realpath(__file__)) write_file = os.path.join(dir_path, filename) with open(write_file, 'w') as f: f.write(buff) except Exception as e: raise Exception("Error writing buffer to file!", e) def read_buffer_from_file(self, filename): try: dir_path = os.path.dirname(os.path.realpath(__file__)) read_file = os.path.join(dir_path, filename) if os.path.exists(os.path.join(dir_path, read_file)): with open(read_file, 'r') as f: read_buffer = f.read() return read_buffer except Exception as e: raise Exception("Error reading buffer from file!", e) def get_mr_enclave(self, msg3): try: msg3 = self.ffi.from_buffer(base64.b64decode(msg3)) mr_e = self.barbie_s.get_mr_e(msg3) #return self.ffi.string(mr_e) #return self.ffi.buffer(mr_e) return base64.b64encode(self.ffi.buffer(mr_e, 32)) except Exception as e: raise Exception("Error in retrieveing mr enclave", e) def get_mr_signer(self, msg3): try: msg3 = self.ffi.from_buffer(base64.b64decode(msg3)) mr_s = self.barbie_s.get_mr_s(msg3) #return self.ffi.string(mr_s) #return self.ffi.buffer(mr_s) return base64.b64encode(self.ffi.buffer(mr_s, 32)) except Exception as e: raise Exception("Error in retrieveing mr signer", e) def get_report_sha256(self, target_lib, msg3): try: msg3 = self.ffi.from_buffer(base64.b64decode(msg3)) sha256 = self.ffi.new("uint8_t []", 32) target_lib.get_report_sha256(msg3, sha256) return base64.b64encode(self.ffi.buffer(sha256)) except Exception as e: raise Exception("Error getting SHA256", e) def test_legacy_client(self): try: #plain_secret = "my-private-secre" secret = "This-Is-My-Private-Secret" plain_secret = Secret(secret, len(secret)) enclave_id = self.init_enclave(self.barbie_s) #To simulate KEK of server side sealed_kek = self.generate_key(self.barbie_s, enclave_id, 16) enc_secret = self.encrypt(self.barbie_s, enclave_id, sealed_kek, plain_secret) r_secret = self.decrypt(self.barbie_s, enclave_id, sealed_kek, enc_secret) r_secret = base64.b64decode(r_secret) if r_secret == secret: print "Legacy Client : Secret Management done!" else: print "Legacy Client : Secret Management failed!" finally: self.destroy_enclave(self.barbie_s, enclave_id) def test_sgx_client_wo_sgx_hw(self, spid=None, crt_path=None, kdir=None): try: pub_key, priv_key = self.generate_key_pair(kdir) s_eid = self.init_enclave(self.barbie_s) plain_sk = Secret("", len("")) #Perform attestation ret, msg0 = self.gen_msg0(self.barbie_s, spid) p_ctxt, msg1 = self.gen_msg1(self.barbie_s, s_eid, pub_key) print "gen_msg1 returned: " + msg1 ret, p_net_ctxt = self.proc_msg0(self.barbie_c, msg0, spid, False) msg2 = self.proc_msg1_gen_msg2(self.barbie_c, msg1, p_net_ctxt, priv_key) print "send_msg1_recv_msg2 returned: " + msg2 msg3, crt, sig, resp_body = self.proc_msg2_gen_msg3( self.barbie_s, s_eid, msg2, p_ctxt, crt_path, False) print "proc_msg2_gen_msg3 returned: " + msg3 msg4 = self.legacy_proc_msg3_gen_msg4(self.barbie_c, msg3, p_net_ctxt, "sgx_wo_hw", None, crt_path, False) print "send_msg3_recv_msg4 returned: " + str(msg4) status, s_dh = self.get_dh_key(self.barbie_s, s_eid, msg4, p_ctxt) print "get_dh_key returned: " + str(status) proj_id, proj_id_size = self.get_project_id( self.barbie_s, s_eid, msg4, p_ctxt) s_sk = self.generate_key(self.barbie_s, s_eid, 16) plain_kek_len = 16 sealed_len = self.barbie_s.get_sealed_data_len( s_eid, 0, plain_kek_len) dh_sk = self.transport(self.barbie_s, s_eid, Secret(s_dh, sealed_len), s_sk, None) plain_sk = self.get_sk(self.barbie_c, p_net_ctxt, dh_sk) #status, plain_sk = self.get_sk(self.barbie_c, p_net_ctxt, 16, dh_sk) #status, sk = self.proc_msg4(self.barbie_s, s_eid, msg4, p_ctxt) #sealed_sk = Secret(sk, sealed_len) #Perform kek provisioning kek = "yek etyb neetxis" plain_kek = Secret(kek, len(kek)) sk_kek = self.legacy_encrypt(self.barbie_c, plain_sk, plain_kek) kek = self.provision_kek(self.barbie_s, s_eid, s_sk, sk_kek, None) plain_kek_len = 16 sealed_len = self.barbie_s.get_sealed_data_len( s_eid, 0, plain_kek_len) sealed_kek = Secret(kek, sealed_len) kek_sk = self.transport(self.barbie_c, s_eid, sealed_kek, s_sk, proj_id) #Perform secret management secret = "my-private-secret" plain_secret = Secret(secret, len(secret)) sk_secret = self.legacy_encrypt(self.barbie_c, plain_sk, plain_secret) kek_secret = self.kek_encrypt(s_eid, kek_sk, sealed_kek, sk_secret, "sgx_wo_hw") rec = self.kek_decrypt(s_eid, kek_sk, sealed_kek, kek_secret, "sgx_wo_hw") if self.compare_secret(self.barbie_c, rec[40:], sk_secret[40:], plain_secret.length): print "SGX Aware Client Without SGX hardware : Secret Management done!" else: print "SGX Aware Cliwnt Without SGX hardware : Secret Management failed!" finally: self.destroy_enclave(self.barbie_s, s_eid)
ffi.embedding_init_code(''' from test_xll import ffi from xlcall._xlcall import ffi as xlcall xlcall = xlcall.dlopen('XLCALL32') # we should look for the module we want to expose, and def_extern all of them here? # then the xlAutoOpen implementation needs to loop over all the def_externs.. @ffi.def_extern(error=0) def xlAutoOpen(): import os for key, value in os.environ.items(): print('{key:<32s} {value}'.format(key=key, value=value)) import sys print(sys.path) print(sys.prefix) print(sys.executable) print('XlCallVer: {:d}'.format(xlcall.XLCallVer())) return 1 @ffi.def_extern(error=0) def xlAutoClose(): return 1 ''') if __name__ == '__main__': ffi.compile(target='test_xll.xll')
########## # FFI Build ########## _groove_source = r""" #include <groove/groove.h> #include <groove/queue.h> #include <groove/encoder.h> #include <groovefingerprinter/fingerprinter.h> #include <grooveloudness/loudness.h> #include <grooveplayer/player.h> """ # TODO: set these differently depending on platform/compiler libs = [ ':libgroove.so.4', ':libgroovefingerprinter.so.4', ':libgrooveloudness.so.4', ':libgrooveplayer.so.4', ] ffi_groove = FFI() ffi_groove.set_source('groove._groove', _groove_source, libraries=libs) ffi_groove.cdef(_groove_header) ffi_groove.cdef(_queue_header) ffi_groove.cdef(_encoder_header) ffi_groove.cdef(_fingerprinter_header) ffi_groove.cdef(_loudness_header) ffi_groove.cdef(_player_header) if __name__ == '__main__': ffi_groove.compile()
# SOFTWARE. from cffi import FFI from xcffib.ffi_build import ffi as xcffib_ffi xcursors_ffi = FFI() xcursors_ffi.set_source("libqtile.core._ffi_xcursors", None) xcursors_ffi.include(xcffib_ffi) xcursors_ffi.cdef(""" typedef uint32_t xcb_cursor_t; typedef struct xcb_cursor_context_t xcb_cursor_context_t; int xcb_cursor_context_new( xcb_connection_t *conn, xcb_screen_t *screen, xcb_cursor_context_t **ctx ); xcb_cursor_t xcb_cursor_load_cursor( xcb_cursor_context_t *ctx, const char *name ); void xcb_cursor_context_free(xcb_cursor_context_t *ctx); """) if __name__ == "__main__": xcursors_ffi.compile()
int Tcl_GetBignumFromObj(Tcl_Interp *interp, Tcl_Obj *obj, mp_int *value); Tcl_Obj *Tcl_NewBignumObj(mp_int *value); int mp_unsigned_bin_size(mp_int *a); int mp_to_unsigned_bin_n(mp_int * a, unsigned char *b, unsigned long *outlen); int mp_read_radix(mp_int *a, const char *str, int radix); int mp_init(mp_int *a); void mp_clear(mp_int *a); """) tkffi.set_source("_tkinter.tklib_cffi", """ #define HAVE_LIBTOMMATH %(HAVE_LIBTOMMATH)s #define HAVE_WIDE_INT_TYPE %(HAVE_WIDE_INT_TYPE)s #include <tcl.h> #include <tk.h> #if HAVE_LIBTOMMATH #include <tclTomMath.h> #endif char *get_tk_version(void) { return TK_VERSION; } char *get_tcl_version(void) { return TCL_VERSION; } """ % globals(), include_dirs=incdirs, libraries=linklibs, library_dirs = libdirs ) if __name__ == "__main__": tkffi.compile(os.path.join(os.path.dirname(sys.argv[0]), '..'))
int16_t nvp_reserve; /* not used */ int32_t nvp_value_elem; /* number of elements for array types */ data_type_t nvp_type; /* type of value */ } nvpair_t; typedef enum { _B_FALSE = 0, _B_TRUE = 1 } boolean_t; typedef unsigned int uint_t; /* Functions */ const char *attr_to_name(f_attr_t); const char *attr_to_option(f_attr_t); f_attr_t name_to_attr(const char *name); f_attr_t option_to_attr(const char *option); int fgetattr(int, xattr_view_t, nvlist_t **); int fsetattr(int, xattr_view_t, nvlist_t *); int nvlist_alloc(nvlist_t **, uint_t, int); void nvlist_free(nvlist_t *); int nvlist_add_boolean_value(nvlist_t *, const char *, boolean_t); nvpair_t *nvlist_next_nvpair(nvlist_t *, nvpair_t *); char *nvpair_name(nvpair_t *); data_type_t nvpair_type(nvpair_t *); int nvpair_value_boolean_value(nvpair_t *, boolean_t *); """) if __name__ == "__main__": ffi.compile(tmpdir="./cffi_src") # Vim hints # vim:ts=8:sw=8:et:fdm=marker
def load_ool_module(): """ Compile an out-of-line module, return the corresponding ffi and module objects. """ from cffi import FFI numba_complex = """ typedef struct _numba_complex { double real; double imag; } numba_complex; """ bool_define = """ #ifdef _MSC_VER #define false 0 #define true 1 #define bool int #else #include <stdbool.h> #endif """ defs = (numba_complex + """ bool boolean(void); double sin(double x); double cos(double x); int foo(int a, int b, int c); void vsSin(int n, float* x, float* y); void vdSin(int n, double* x, double* y); void vector_real(numba_complex *c, double *real, int n); void vector_imag(numba_complex *c, double *imag, int n); """) source = (numba_complex + bool_define + """ static bool boolean(void) { return true; } static int foo(int a, int b, int c) { return a + b * c; } void vsSin(int n, float* x, float* y) { int i; for (i=0; i<n; i++) y[i] = sin(x[i]); } void vdSin(int n, double* x, double* y) { int i; for (i=0; i<n; i++) y[i] = sin(x[i]); } static void vector_real(numba_complex *c, double *real, int n) { int i; for (i = 0; i < n; i++) real[i] = c[i].real; } static void vector_imag(numba_complex *c, double *imag, int n) { int i; for (i = 0; i < n; i++) imag[i] = c[i].imag; } """) ffi = FFI() ffi.set_source("cffi_usecases_ool", source) ffi.cdef(defs, override=True) tmpdir = temp_directory("test_cffi") ffi.compile(tmpdir=tmpdir) sys.path.append(tmpdir) try: mod = import_dynamic("cffi_usecases_ool") cffi_support.register_module(mod) cffi_support.register_type(mod.ffi.typeof("struct _numba_complex"), complex128) return mod.ffi, mod finally: sys.path.remove(tmpdir)
def build_callback_fn(function_string, userdata_names=[]): ''' Builds a C callback function and returns a function pointer int. function_string : str This is a string of the C function to be compiled userdata_names : list or tuple This is an optional list to defince convenience names We compile and link and load the function, and return a function pointer. See `MjSim.set_substep_callback()` for an example use of these callbacks. The callback function should match the signature: void fun(const mjModel *m, mjData *d); Here's an example function_string: ``` """ #include <stdio.h> void fun(const mjModel* m, mjData* d) { printf("hello"); } """ ``` Input and output for the function pass through userdata in the data struct: ``` """ void fun(const mjModel* m, mjData* d) { d->userdata[0] += 1; } """ ``` `userdata_names` is expected to match the model where the callback is used. These can bet set on a model with: `model.set_userdata_names([...])` If `userdata_names` is supplied, convenience `#define`s are added for each. For example: `userdata_names = ['my_sum']` Will get gerenerated into the extra line: `#define my_sum d->userdata[0]` And prepended to the top of the function before compilation. Here's an example that takes advantage of this: ``` """ void fun(const mjModel* m, mjData* d) { for (int i = 0; i < m->nu; i++) { my_sum += d->ctrl[i]; } } """ ``` Note these are just C `#define`s and are limited in how they can be used. After compilation, the built library containing the function is loaded into memory and all of the files (including the library) are deleted. To retain these for debugging set the `MUJOCO_PY_DEBUG_FN_BUILDER` envvar. To save time compiling, these function pointers may be re-used by many different consumers. They are thread-safe and don't acquire the GIL. See the file `tests/test_substep.py` for additional examples, including an example which iterates over contacts to compute penetrations. ''' assert isinstance(userdata_names, (list, tuple)), \ 'invalid userdata_names: {}'.format(userdata_names) ffibuilder = FFI() ffibuilder.cdef('extern uintptr_t __fun;') name = '_fn_' + ''.join(choice(ascii_lowercase) for _ in range(15)) source_string = '#include <mujoco.h>\n' # Add defines for each userdata to make setting them easier for i, data_name in enumerate(userdata_names): source_string += '#define {} d->userdata[{}]\n'.format(data_name, i) source_string += function_string source_string += '\nuintptr_t __fun = (uintptr_t) fun;' # Link against mujoco so we can call mujoco functions from within callback ffibuilder.set_source(name, source_string, include_dirs=[join(mujoco_path, 'include')], library_dirs=[join(mujoco_path, 'bin')], libraries=['mujoco200']) # Catch compilation exceptions so we can cleanup partial files in that case try: library_path = ffibuilder.compile(verbose=True) except Exception as e: build_fn_cleanup(name) raise e # On Mac the MuJoCo library is linked strangely, so we have to fix it here if sys.platform == 'darwin': fixed_library_path = manually_link_libraries(mujoco_path, library_path) move(fixed_library_path, library_path) # Overwrite with fixed library module = load_dynamic_ext(name, library_path) # Now that the module is loaded into memory, we can actually delete it build_fn_cleanup(name) return module.lib.__fun
int Tcl_GetBignumFromObj(Tcl_Interp *interp, Tcl_Obj *obj, mp_int *value); Tcl_Obj *Tcl_NewBignumObj(mp_int *value); int mp_unsigned_bin_size(mp_int *a); int mp_to_unsigned_bin_n(mp_int * a, unsigned char *b, unsigned long *outlen); int mp_read_radix(mp_int *a, const char *str, int radix); int mp_init(mp_int *a); void mp_clear(mp_int *a); """) tkffi.set_source("_tkinter.tklib_cffi", """ #define HAVE_LIBTOMMATH %(HAVE_LIBTOMMATH)s #define HAVE_WIDE_INT_TYPE %(HAVE_WIDE_INT_TYPE)s #include <tcl.h> #include <tk.h> #if HAVE_LIBTOMMATH #include <tclTomMath.h> #endif char *get_tk_version(void) { return TK_VERSION; } char *get_tcl_version(void) { return TCL_VERSION; } """ % globals(), include_dirs=incdirs, libraries=linklibs, library_dirs = libdirs ) if __name__ == "__main__": tkffi.compile(os.path.join(os.path.dirname(sys.argv[0]), '..'))
from cffi import FFI ffibuilder = FFI() # specify functions, etc made available to Python ffibuilder.cdef(""" void batch_fcn(double ans[], double x[], int n, int dim); """) # specify code needed to build the module ffibuilder.set_source( "ffcn_cffi", # Python extension module (output) """ // code for module double fcn_(double* x, int* dim); // Fortran function in ffcn.o void batch_fcn(double ans[], double x[], int n, int dim) { int i; for(i=0; i<n; i++) ans[i] = fcn_(&x[i * dim], &dim); } """, extra_objects=['ffcn.o'], # compiled Fortran libraries=['m'], # may need to specify the math library (-lm) ) if __name__ == "__main__": # create C code for module and compile it ffibuilder.compile(verbose=False)
#include "orte/orted/orted_submit.h" """, libraries=["open-rte"], include_dirs=include_dirs, library_dirs=library_dirs ) ffi.cdef(""" /* Types */ typedef ... orte_job_t; typedef ... opal_cmd_line_init_t; typedef void (*orte_submit_cbfunc_t)(int index, orte_job_t *jdata, int ret, void *cbdata); /* Functions */ int orte_submit_init(int argc, char *argv[], opal_cmd_line_init_t *opts); int orte_submit_job(char *cmd[], int *index, orte_submit_cbfunc_t launch_cb, void *launch_cbdata, orte_submit_cbfunc_t complete_cb, void *complete_cbdata); void orte_submit_finalize(void); int orte_submit_cancel(int index); int orte_submit_halt(void); /* Callbacks */ extern "Python" void launch_cb(int, orte_job_t *, int, void *); extern "Python" void finish_cb(int, orte_job_t *, int, void *); """) if __name__ == "__main__": ffi.compile(verbose=True)
} void wrapped_log_init(enum wlr_log_importance verbosity, wrapped_log_func_t callback) { if (callback == NULL) { wlr_log_init(verbosity, NULL); } else { py_callback = callback; wlr_log_init(verbosity, wrapped_log_callback); } } """ ffi_builder = FFI() ffi_builder.set_source( "wlroots._ffi", SOURCE, libraries=["wlroots"], define_macros=[("WLR_USE_UNSTABLE", None)], include_dirs=["/usr/include/pixman-1", "include"], ) ffi_builder.include(pywayland_ffi) ffi_builder.include(xkb_ffi) ffi_builder.cdef(CDEF) if __name__ == "__main__": ffi_builder.compile()
* The data associated with the event, or NULL if there isn't any. */ const uint8_t* data; }; typedef struct jsua_event jsua_event; typedef void (jsua_parser_evt_func)(jsua_event* event, void* user_data); extern "Python" void on_parser_event(jsua_event*, void*); typedef struct jsua_parser jsua_parser; jsua_parser* jsua_parser_new(void); void jsua_parser_free(jsua_parser* parser); bool jsua_parser_init(jsua_parser* parser, jsua_parser_evt_func* cb, void* user_data); void jsua_parser_fini(jsua_parser* parser); bool jsua_parser_feed(jsua_parser* parser, jsua_blob* blob); const jsua_error* jsua_parser_error(jsua_parser* parser); const char* jsua_error_to_string(const jsua_error* err); ''') if __name__ == '__main__': ffibuilder.compile()
ffiwrapper = FFI() ffiwrapper.cdef(''' void zyre_destroy_py (void *self); void zyre_event_destroy_py (void *self); ''') ffiwrapper.set_source("zyre.zyre_py_destructors", libraries=['zyre'], source=''' #include <zyre.h> void zyre_destroy_py (void *self) { zyre_destroy ((zyre_t **) &self); } void zyre_event_destroy_py (void *self) { zyre_event_destroy ((zyre_event_t **) &self); } ''') if __name__ == "__main__": ffi.compile() ffiwrapper.compile()
from cffi import FFI ffibuilder = FFI() source = """ typedef unsigned char MP_U8; typedef unsigned int MP_U32; int lzmat_encode(MP_U8 *pbOut, MP_U32 *pcbOut, MP_U8 *pbIn, MP_U32 cbIn); int lzmat_decode(MP_U8 *pbOut, MP_U32 *pcbOut, MP_U8 *pbIn, MP_U32 cbIn); """ ffibuilder.set_source( "_pylzmat", # name of the output C extension """#include "lzmat.h" """, sources=['src/lzmat/lzmat_enc.c', 'src/lzmat/lzmat_dec.c'], # includes pi.c as additional sources include_dirs=['src/lzmat'] ) # ffibuilder.cdef("int lzmat_encode(char *pbOut, int *pcbOut, char *pbIn, int cbIn);") # ffibuilder.cdef("int lzmat_decode(char *pbOut, int *pcbOut, char *pbIn, int cbIn);") ffibuilder.cdef(source) if __name__ == "__main__": ffibuilder.compile(verbose=True)
output = StringIO() p.write(output) return output.getvalue() ffibuilder = FFI() ffibuilder.cdef(get_preprocessed_headers()) # set_source() gives the name of the python extension module to # produce, and some C source code as a string. This C code needs # to make the declarated functions, types and globals available, # so it is often just the "#include". if sys.platform.startswith('linux'): linker_args = "-Wl,-rpath=$ORIGIN/pahmm,--enable-new-dtags" elif sys.platform.startswith('darwin'): linker_args = "-Wl,-rpath,@loader_path/pahmm" else: linker_args = "" ffibuilder.set_source("_pahmm_cffi", """ #include "cpahmm.h" // the C header of the library """, extra_link_args=[linker_args], library_dirs=["./python/pahmm"], include_dirs=["./include"], libraries=["pahmm"]) if __name__ == "__main__": ffibuilder.compile(verbose=True, tmpdir="./build/python")
""" #include <libxml/xmlversion.h> #include <xmlstar.h> #include <config.h> #include <libexslt/exslt.h> """, sources=sources, include_dirs=include_dirs, libraries=libraries, library_dirs=library_dirs, ) # cdef() expects a single string declaring the C types, functions and # globals needed to use the shared object. It must be in valid C syntax. FFIBUILDER.cdef(""" int c14nMain(int argc, char **argv); int depyxMain(int argc, char **argv); int edMain(int argc, char **argv); int elMain(int argc, char **argv); int escMain(int argc, char **argv, int escape); int foMain(int argc, char **argv); int lsMain(int argc, char **argv); int pyxMain(int argc, char **argv); int selMain(int argc, char **argv); int trMain(int argc, char **argv); int valMain(int argc, char **argv); """) if __name__ == "__main__": FFIBUILDER.compile(verbose=True)
def load_ool_module(): """ Compile an out-of-line module, return the corresponding ffi and module objects. """ from cffi import FFI numba_complex = """ typedef struct _numba_complex { double real; double imag; } numba_complex; """ defs = numba_complex + """ double sin(double x); double cos(double x); int foo(int a, int b, int c); void vsSin(int n, float* x, float* y); void vdSin(int n, double* x, double* y); void vector_real(numba_complex *c, double *real, int n); void vector_imag(numba_complex *c, double *imag, int n); """ source = numba_complex + """ static int foo(int a, int b, int c) { return a + b * c; } void vsSin(int n, float* x, float* y) { int i; for (i=0; i<n; i++) y[i] = sin(x[i]); } void vdSin(int n, double* x, double* y) { int i; for (i=0; i<n; i++) y[i] = sin(x[i]); } static void vector_real(numba_complex *c, double *real, int n) { int i; for (i = 0; i < n; i++) real[i] = c[i].real; } static void vector_imag(numba_complex *c, double *imag, int n) { int i; for (i = 0; i < n; i++) imag[i] = c[i].imag; } """ ffi = FFI() ffi.set_source('cffi_usecases_ool', source) ffi.cdef(defs, override=True) tmpdir = temp_directory('test_cffi') ffi.compile(tmpdir=tmpdir) sys.path.append(tmpdir) try: mod = import_dynamic('cffi_usecases_ool') cffi_support.register_module(mod) cffi_support.register_type(mod.ffi.typeof('struct _numba_complex'), complex128) return mod.ffi, mod finally: sys.path.remove(tmpdir)
void SSOS_query_exec(char *sql, char *target_host, int target_port); // void SSOS_request_pub_manifest( SSOS_query_results *manifest_var, int *max_frame_overall_var, char *pub_title_filter, char *target_host, int target_port); // void SSOS_cache_grab( char *pub_filter, char *val_filter, int frame_head, int frame_depth_limit, char *target_host, int target_port); // void SSOS_result_pool_size(int *addr_of_counter_int); void SSOS_result_claim(SSOS_query_results *results); void SSOS_result_destroy(SSOS_query_results *results); void SSOS_sense_trigger(char *sense_handle, int payload_size, void *payload_data); // -------------------- """) #ffibuilder.compile(verbose=True) ffibuilder.compile(verbose=False)
extra_compile_args.append('-std=c99') ffi = FFI() ffi.set_source('_rmath_ffi', '#include <Rmath.h>', include_dirs=include_dirs, sources=rmath_src, libraries=[], extra_compile_args=extra_compile_args) # This is an incomplete list of the available functions in Rmath # but these are sufficient for our example purposes and gives a sense of # the types of functions we can get ffi.cdef('''\ // Normal Distribution double dnorm(double, double, double, int); double pnorm(double, double, double, int, int); // Uniform Distribution double dunif(double, double, double, int); double punif(double, double, double, int, int); // Gamma Distribution double dgamma(double, double, double, int); double pgamma(double, double, double, int, int); ''') if __name__ == '__main__': # Normally set verbose to `True`, but silence output # for reduced notebook noise ffi.compile(verbose=False)
from cffi import FFI from unittest import TestCase source = open('libsec.h', 'r').read() ffi = FFI() ffi.cdef(source) ffi.set_source('_libsec', '#include <secp256k1.h>', libraries=['secp256k1']) ffi.compile(verbose=True)
# Check which resample lib to use if pkgconfig.exists("libswresample"): resample = (dname + "/../src/decode.c", "swresample") elif pkgconfig.exists("libavresample"): resample = (dname + "/../src/decode_av.c", "avresample") else: sys.exit("No libswresample/libavresample available.") # Build ffi.set_source("bliss._bliss", "#include \"bliss.h\"", sources=[os.path.normpath(dname + "/../src/amplitude_sort.c"), os.path.normpath(dname + "/../src/analyze.c"), os.path.normpath(resample[0]), os.path.normpath(dname + "/../src/tempo_atk_sort.c"), os.path.normpath(dname + "/../src/frequency_sort.c"), os.path.normpath(dname + "/../src/helpers.c")], libraries=["avformat", "avutil", "avcodec", "fftw3", resample[1]], include_dirs=["/usr/include/ffmpeg/", "/usr/include/", dname + "/../include"], extra_compile_args=["-std=c99"]) header = ''.join([i for i in open(dname + "/../include/bliss.h", 'r').readlines() if not i.strip().startswith("#")]) ffi.cdef(header) if __name__ == "__main__": ffi.compile(tmpdir="/tmp/bliss/")
def compile_c_function(code_c, nbout, dtype=numpy.float32, add_header=True, suffix="", additional_paths=None, tmpdir='.', fLOG=None): """ Compiles a C function with :epkg:`cffi`. It takes one features vector. @param nbout number of expected outputs @param code_c code C @param dtype numeric type to use @param add_header add common function before compiling @param suffix avoid avoid the same compiled module name @param additional_paths additional paths to add to the module @param tmpdir see below @param fLOG logging function @return compiled function The function assumes the first line is the signature. If you are using Windows with Visual Studio 2017, make sure you are using :epkg:`Python` 3.6.3+ (see `Issue 30389 <https://bugs.python.org/issue30389>`_). Parameter *tmpdir* is used by function `compile <http://cffi.readthedocs.io/en/latest/cdef.html? highlight=compile#ffibuilder-compile-etc-compiling-out-of-line-modules>`_. """ if sys.platform.startswith("win"): if "VS140COMNTOOLS" not in os.environ: # pragma: no cover raise CompilationError( "Visual Studio is not installed.\n{0}".format( "\n".join("{0}={1}".format(k, v) for k, v in sorted(os.environ.items())))) sig = code_c.split("\n")[0].strip() + ";" name = sig.split()[1] include_paths = [] lib_paths = [] if additional_paths is None: additional_paths = [] # ~ if len(additional_paths) == 0 and sys.platform.startswith("win") and \ # ~ 'VSSDK140Install' not in os.environ: # last condition is for the installed VisualStudio. # ~ if fLOG: #~ fLOG("[compile_c_function] fix PATH for VS2017 on Windows") # ~ # Update environment variables. # ~ adds = [r"C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64", # ~ r"C:\Program Files (x86)\Windows Kits\10\bin\10.0.15063.0\x64"] # ~ vcvars64 = os.path.join(adds[0], 'vcvars64.bat') #~ subprocess.run(vcvars64) # ~ # Add paths for VS2017. # ~ includes = [r'C:\Program Files (x86)\Windows Kits\10\Include\10.0.15063.0\shared', #~ r'C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include', # ~ r'C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\SDK\ScopeCppSDK\SDK\include\ucrt'] # ~ libs = [r'C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\lib\amd64', #~ r'C:\Program Files (x86)\Windows Kits\10\Lib\10.0.15063.0\um\x64', # ~ r'C:\Program Files (x86)\Windows Kits\10\Lib\10.0.15063.0\ucrt\x64'] # ~ opaths = os.environ['PATH'].split(';') # ~ for add in adds: # ~ if os.path.exists(add) and add not in opaths: #~ additional_paths.append(add) # ~ oinc = os.environ.get('INCLUDE', '').split(';') # ~ for inc in includes: # ~ if os.path.exists(inc) and inc not in oinc: #~ include_paths.append(inc) # ~ for lib in libs: # ~ if os.path.exists(lib): #~ lib_paths.append(lib) if additional_paths: if fLOG: # pragma: no cover for p in additional_paths: fLOG("[compile_c_function] PATH += '{0}'".format(p)) os.environ["PATH"] += ";" + ";".join(additional_paths) if lib_paths and sys.platform.startswith("win"): # pragma: no cover libs = ['msvcrt.lib', 'oldnames.lib', 'kernel32.lib', 'vcruntime.lib', 'ucrt.lib'] libs = {k: False for k in libs} for lib in lib_paths: for name in list(libs): if libs[name]: continue msv = os.path.join(lib, name) if os.path.exists(msv): dst = os.getcwd() msvd = os.path.join(dst, name) if not os.path.exists(msvd): shutil.copy(msv, dst) if fLOG: fLOG("[compile_c_function] copy '{0}'".format(msv)) libs[name] = True copied = len([k for k, v in libs.items() if v]) if copied < len(libs): raise CompilationError('Unable to find those libraries ({0}<{1}) {2} in\n{3}'.format( copied, len(libs), ','.join(sorted(libs)), '\n'.join(lib_paths))) if include_paths: if fLOG: # pragma: no cover for p in include_paths: fLOG("[compile_c_function] INCLUDE += '{0}'".format(p)) if 'INCLUDE' in os.environ: # pragma: no cover os.environ["INCLUDE"] += ";" + ";".join(include_paths) else: # pragma: no cover os.environ["INCLUDE"] = ";".join(include_paths) is_float = dtype == numpy.float32 header = _header_c_float if is_float else _header_c_double code = code_c if not add_header else (header + code_c) from cffi import FFI ffibuilder = FFI() try: ffibuilder.cdef(sig) except Exception as e: # pragma: no cover raise CompilationError( "Signature is wrong\n{0}\ndue to\n{1}".format(sig, e)) from e ffibuilder.set_source("_" + name + suffix, code) try: ffibuilder.compile(verbose=False, tmpdir=tmpdir) except Exception as e: # pragma: no cover raise CompilationError( "Compilation failed \n{0}\ndue to\n{1}".format(sig, e)) from e mod = __import__("_{0}{1}".format(name, suffix)) fct = getattr(mod.lib, name) def wrapper(features, output, cast_type, dtype): "wrapper for a vector of features" if len(features.shape) != 1: raise TypeError( # pragma: no cover "Only one dimension for the features not {0}.".format( features.shape)) if output is None: output = numpy.zeros((nbout,), dtype=dtype) else: if len(output.shape) != 1: raise TypeError( # pragma: no cover "Only one dimension for the output not {0}.".format( output.shape)) if output.shape[0] != nbout: raise TypeError( # pragma: no cover "Dimension mismatch {0} != {1} (expected).".format( output.shape, nbout)) if output.dtype != dtype: raise TypeError( # pragma: no cover "Type mismatch {0} != {1} (expected).".format( output.dtype, dtype)) ptr = features.__array_interface__['data'][0] cptr = mod.ffi.cast(cast_type, ptr) optr = output.__array_interface__['data'][0] cout = mod.ffi.cast(cast_type, optr) fct(cout, cptr) return output def wrapper_double(features, output=None): "wrapper for double" return wrapper(features, output, "double*", numpy.float64) def wrapper_float(features, output=None): "wrapper for float" return wrapper( # pragma: no cover features, output, "float*", numpy.float32) return wrapper_float if is_float else wrapper_double
def build_callback_fn(function_string, userdata_names=[]): ''' Builds a C callback function and returns a function pointer int. function_string : str This is a string of the C function to be compiled userdata_names : list or tuple This is an optional list to defince convenience names We compile and link and load the function, and return a function pointer. See `MjSim.set_substep_callback()` for an example use of these callbacks. The callback function should match the signature: void fun(const mjModel *m, mjData *d); Here's an example function_string: ``` """ #include <stdio.h> void fun(const mjModel* m, mjData* d) { printf("hello"); } """ ``` Input and output for the function pass through userdata in the data struct: ``` """ void fun(const mjModel* m, mjData* d) { d->userdata[0] += 1; } """ ``` `userdata_names` is expected to match the model where the callback is used. These can bet set on a model with: `model.set_userdata_names([...])` If `userdata_names` is supplied, convenience `#define`s are added for each. For example: `userdata_names = ['my_sum']` Will get gerenerated into the extra line: `#define my_sum d->userdata[0]` And prepended to the top of the function before compilation. Here's an example that takes advantage of this: ``` """ void fun(const mjModel* m, mjData* d) { for (int i = 0; i < m->nu; i++) { my_sum += d->ctrl[i]; } } """ ``` Note these are just C `#define`s and are limited in how they can be used. After compilation, the built library containing the function is loaded into memory and all of the files (including the library) are deleted. To retain these for debugging set the `MUJOCO_PY_DEBUG_FN_BUILDER` envvar. To save time compiling, these function pointers may be re-used by many different consumers. They are thread-safe and don't acquire the GIL. See the file `tests/test_substep.py` for additional examples, including an example which iterates over contacts to compute penetrations. ''' assert isinstance(userdata_names, (list, tuple)), \ 'invalid userdata_names: {}'.format(userdata_names) ffibuilder = FFI() ffibuilder.cdef('extern uintptr_t __fun;') name = '_fn_' + ''.join(choice(ascii_lowercase) for _ in range(15)) source_string = '#include <mujoco.h>\n' # Add defines for each userdata to make setting them easier for i, data_name in enumerate(userdata_names): source_string += '#define {} d->userdata[{}]\n'.format(data_name, i) source_string += function_string source_string += '\nuintptr_t __fun = (uintptr_t) fun;' # Link against mujoco so we can call mujoco functions from within callback ffibuilder.set_source(name, source_string, include_dirs=[join(mujoco_path, 'include')], library_dirs=[join(mujoco_path, 'bin')], libraries=['mujoco200']) # Catch compilation exceptions so we can cleanup partial files in that case try: library_path = ffibuilder.compile(verbose=True) except Exception as e: build_fn_cleanup(name) raise e # On Mac the MuJoCo library is linked strangely, so we have to fix it here if sys.platform == 'darwin': fixed_library_path = manually_link_libraries(mujoco_path, library_path) move(fixed_library_path, library_path) # Overwrite with fixed library module = load_dynamic_ext(name, library_path) # Now that the module is loaded into memory, we can actually delete it build_fn_cleanup(name) return module.lib.__fun
eAudioCategoryGameChat = 8, eAudioCategorySpeech = 9, eAudioCategoryMovie = 10, eAudioCategoryMedia = 11 } PaWasapiStreamCategory; typedef enum PaWasapiStreamOption { eStreamOptionNone = 0, eStreamOptionRaw = 1, eStreamOptionMatchFormat = 2 } PaWasapiStreamOption; typedef struct PaWasapiStreamInfo { unsigned long size; PaHostApiTypeId hostApiType; unsigned long version; unsigned long flags; PaWinWaveFormatChannelMask channelMask; PaWasapiHostProcessorCallback hostProcessorOutput; PaWasapiHostProcessorCallback hostProcessorInput; PaWasapiThreadPriority threadPriority; PaWasapiStreamCategory streamCategory; PaWasapiStreamOption streamOption; } PaWasapiStreamInfo; """) if __name__ == "__main__": ffibuilder.compile(verbose=True)
# file "testCFFI_build.py" # Note: this particular example fails before version 1.0.2 # because it combines variadic function and ABI level. from cffi import FFI ffi = FFI() ffi.set_source("_testCFFI", None) ffi.cdef(""" void printHello(); void printMessage(char *myMessage); double sumVector(int size, double* vec); """) if __name__ == "__main__": ffi.compile()
gchar * gdk_pixbuf_format_get_name (GdkPixbufFormat *format); GdkColorspace gdk_pixbuf_get_colorspace (const GdkPixbuf *pixbuf); int gdk_pixbuf_get_n_channels (const GdkPixbuf *pixbuf); gboolean gdk_pixbuf_get_has_alpha (const GdkPixbuf *pixbuf); int gdk_pixbuf_get_bits_per_sample (const GdkPixbuf *pixbuf); int gdk_pixbuf_get_width (const GdkPixbuf *pixbuf); int gdk_pixbuf_get_height (const GdkPixbuf *pixbuf); int gdk_pixbuf_get_rowstride (const GdkPixbuf *pixbuf); guchar * gdk_pixbuf_get_pixels (const GdkPixbuf *pixbuf); gsize gdk_pixbuf_get_byte_length (const GdkPixbuf *pixbuf); gboolean gdk_pixbuf_save_to_buffer ( GdkPixbuf *pixbuf, gchar **buffer, gsize *buffer_size, const char *type, GError **error, ...); void gdk_cairo_set_source_pixbuf ( cairo_t *cr, const GdkPixbuf *pixbuf, double pixbuf_x, double pixbuf_y); void g_object_ref (gpointer object); void g_object_unref (gpointer object); void g_error_free (GError *error); void g_type_init (void); ''') if __name__ == '__main__': ffi.compile() ffi_pixbuf.compile()