PKHMy cffi_magic/__init__.py""" A module that define a cffi magic for IPython import to get `%%cffi` cell magic in current namespace See `%%cffi?` for usage. Mostly playing with CFFI, feel free to contact me if you want to take over. """ from __future__ import print_function import re from cffi import FFI from hashlib import md5 import string import logging import subprocess from IPython.core.magic import Magics, magics_class, cell_magic hash_code = lambda s:md5(s.encode()).hexdigest() import io import os __version__ ='0.0.9' log = logging.getLogger(__name__) cargotoml=""" [package] name = "{name}" version = "0.0.1" authors = ["No-one InParticular "] [lib] name = "{name}" crate-type = ["dylib"] [dependencies] libc = "0.1" """ lib_pre = 'lib' from sys import platform if platform == 'darwin': ext = 'dylib' elif platform == 'win32': lib_pre = '' ext = 'dll' else: ext = 'so' @magics_class class CFFI(Magics): @cell_magic def cffi(self, line, cell): """ Put declaration on the fisrt line, implementation in second example: %%cffis int quad(int); int quad(int n){ return 4*n; } inject `quad`, and `quad_ffi` in user namespace to be usable directly """ ffi = FFI() rname = '_cffi_%s' % hash_code(line+cell) ffi.cdef(line) ffi.set_source(rname, cell) ffi.compile() mod = __import__(rname) for attr in dir(mod.lib): self.shell.user_ns[attr] = getattr(mod.lib, attr) self.shell.user_ns['%s_ffi' % attr] = mod.ffi @cell_magic def rust(self, line, cell): """ Rust cffi magic, declaration on first line, rust on the rest. Example: ``` %%rust int calculate(const char *script); #![allow(dead_code)] extern crate libc; use libc::c_char; use std::ffi::CStr; use std::str; // {{{ fn calculate(c_buf: *const c_char) -> i32 {...} #[no_mangle] pub extern fn calculate(c_buf: *const c_char) -> i32 { let buf = unsafe { CStr::from_ptr(c_buf).to_bytes() }; let slice = str::from_utf8(buf).unwrap(); calc(slice) } // }}} fn calc(script: &str) -> i32 { let mut accumulator = 0; for c in script.chars() { match c { '+' => accumulator += 1, '-' => accumulator -= 1, '*' => accumulator *= 2, '/' => accumulator /= 2, _ => { /* ignore other characters */ } } } accumulator } ``` you can now ``` calculate('+ + + * - /') # 2 ``` Exmaple 2: ``` %%rust int double(int); #[no_mangle] pub extern fn double(x: i32) -> i32 { x*2 } ``` now ``` double(3) # return 6 ``` """ ffi = FFI() rname = '_cffi_%s' % hash_code(line+cell) with io.open('Cargo.toml','wb') as f: f.write(cargotoml.format(name=rname).encode('utf-8')) try: os.mkdir('src') except OSError: pass with io.open('src/lib.rs', 'wb') as f: f.write(cell.encode()) subprocess.call(["cargo", "build",'--release']) ffi.cdef(line) mod = ffi.dlopen("target/release/{pre}{name}.{ext}".format(name=rname, pre=lib_pre, ext=ext)) exports = re.findall('([a-zA-Z_]+)\(', line) for attr in exports: self.shell.user_ns[attr] = getattr(mod, attr) print("injecting `%s` in user ns" % (attr,)) #self.shell.user_ns['%s_ffi'%attr] = mod.ffi try: ip = get_ipython() ip.register_magics(CFFI) except NameError: log.debug('Not in IPython, cffi_magic will have no effect') example = """ %%cffi int quint(int); int quint(int n) { return 5*n; } # quint(9) # 45 """ PKiJX >>"cffi_magic-0.0.9.dist-info/LICENSEThe MIT License (MIT) Copyright (c) 2015 Matthias Bussonnier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. PK!Hf$Wd cffi_magic-0.0.9.dist-info/WHEEL HM K-*ϳR03rOK-J,/RH,Q0343 /, (-JLR()*M ILR(4KM̫#DPK!HCyՕ#cffi_magic-0.0.9.dist-info/METADATAuQmk1>b@ ^a ('EZ/D$;IdR{YAy}3̚X֒eW<VM~h٪ I~uZ%j[;XS 밸qg A1v?om.n`b 'p-;%=[c HK ,ڄ$)X{DPँBuapt_aH?r7E^TLNrt mwD4y) {&*c48f~% Gc3rMY<>=p?-ـ%)x}Oo/6݆)Q{DF3 6枾,fL:NjOgPK!H!cffi_magic-0.0.9.dist-info/RECORD}Kr0нg 1,2n2iWOnw'(JlʁsYH((F0-tW{t'|pN1 \/ hA-]- Q3^67VޑxN]W8 "CJ#P|JkufW\_;<~ǿ<{}°~YmR r b?_eChޓQ/PKHMy cffi_magic/__init__.pyPKiJX >>"cffi_magic-0.0.9.dist-info/LICENSEPK!Hf$Wd 3cffi_magic-0.0.9.dist-info/WHEELPK!HCyՕ#cffi_magic-0.0.9.dist-info/METADATAPK!H!cffi_magic-0.0.9.dist-info/RECORDPK