Skip to content

Instantly share code, notes, and snippets.

@pmp-p
Created October 22, 2020 18:34
Show Gist options
  • Save pmp-p/d5902fb79f6ad4415cc24ac9b612948f to your computer and use it in GitHub Desktop.
Save pmp-p/d5902fb79f6ad4415cc24ac9b612948f to your computer and use it in GitHub Desktop.
use dragon ffi to call inlined C from python
import sys
import pydffi
rt = {
int : ('int',0),
float : ('float',.0),
None : ('void', '*0'),
}
class Exports:
table = {}
def __init__(self):
global FFI, this
FFI = pydffi.FFI(includeDirs=["/usr/local/include/python3.8/"])
this = FFI.cdef("#include <Python.h>").funcs
def __call__(self, func, stack ):
if not id(func) in self.table:
ann = func.__annotations__
r_type, r_value = rt[ ann.get('return',None) ]
print(f"compiling: {r_type} {func.__name__}({', '.join(stack.keys())})")
print("-"*40)
args = []
for key, value in func.__annotations__.items():
if key == 'return':
continue
args.append(f'{rt[value][0]} {key}')
if r_type == 'void':
retblock_begin = ''
retblock_end = ''
else:
retblock_begin = f"""\
rtype __ret__ = {r_value};"""
retblock_end = f"""\
return (rtype)(__ret__);"""
dyncode = f"""
#define rtype {r_type}
rtype
{func.__name__}({', '.join(args)}) {{
{retblock_begin}
//user code
{func.__doc__}
//user code
end:;
{retblock_end} // or pytype there
}}
#undef rtype
"""
func.__doc__ = ""
print(dyncode)
self.table[func.__name__] = getattr( FFI.compile(dyncode).funcs, func.__name__ )
print("-"*40)
return self.table[func.__name__](*stack.values())
def __getattr__(self, attr):
global this
return getattr(this, attr)
exports = Exports()
exports.PyRun_SimpleString("print('hello #python-fr')")
def c_test(a:int=0, b:int=0) -> int :
"""
__ret__ = (rtype)(a+b); goto end;
"""
return exports(c_test, locals())
rdyn = c_test(4,5)
print("DYN:", rdyn, int(rdyn) )
# <3 inplace op. , merci dragonffi !
rdyn += 1
print("DYN:", rdyn, int(rdyn) )
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment