Diese Präsentation wurde erfolgreich gemeldet.
Wir verwenden Ihre LinkedIn Profilangaben und Informationen zu Ihren Aktivitäten, um Anzeigen zu personalisieren und Ihnen relevantere Inhalte anzuzeigen. Sie können Ihre Anzeigeneinstellungen jederzeit ändern.

Call a C API from Python becomes more enjoyable with CFFI, Jean-Sébastien Bevilacqua

646 Aufrufe

Veröffentlicht am

PyParis 2017
http://pyparis.org

Veröffentlicht in: Technologie
  • Als Erste(r) kommentieren

  • Gehören Sie zu den Ersten, denen das gefällt!

Call a C API from Python becomes more enjoyable with CFFI, Jean-Sébastien Bevilacqua

  1. 1. CALL A C API FROM PYTHON BECOMES MORE ENJOYABLE WITH CFFI JEAN-SÉBASTIEN BEVILACQUA
  2. 2. WHY PYTHON EXTENSION ?
  3. 3. WHY PYTHON EXTENSION ? ACCESSING LOW-LEVEL API OPENGL / VULKAN 
  4. 4. WHY PYTHON EXTENSION ? LINKING TO EXISTING C LIBRARY 
  5. 5. WHY PYTHON EXTENSION ? IMPROVING PERFORMANCE 
  6. 6. OUR GOOD FRIEND IS ALWAYS HERE !
  7. 7. I'M TOTALLY LOST WITH CPYTHON API
  8. 8. APPLICATION PROGRAMMING INTERFACE APPLICATION BINARY INTERFACE 
  9. 9. WHY ABI ?
  10. 10. CYTHON
  11. 11. CYTHON INCREMENTAL OPTIMIZATION PY++
  12. 12. CYTHON def fib(int n): cdef int a = 0 cdef int b = 1 while b < n: print(b) a, b = b, a + b
  13. 13. CYTHON ABI / API
  14. 14. CTYPES BUILT-IN / ABI ONLY
  15. 15. CTYPES from ctypes import cdll, Structure, c_int, c_double lib = cdll.LoadLibrary('./vector.so') # ctypes Point structure class Point(Structure): _fields_ = [('x', c_int), ('y', c_int)] # Initialize Point[2] argument points_array = (Point * 2)((1, 2), (3, 4)) # Get vector_size from library vector_size_fn = lib.vector_size vector_size_fn.restype = c_double # Call vector_size with ctypes size = vector_size_fn(points_array) print('out = {}'.format(size))
  16. 16. CFFI ENLIGHTENED IN-LINE : IMPORT TIME OUT-OF-LINE : INSTALL TIME
  17. 17. ABI / IN-LINE from cffi import FFI ffi = FFI() ffi.cdef("int printf(const char *format, ...);") C = ffi.dlopen(None) arg = ffi.new("char[]", "world") C.printf("hello %sn", arg)
  18. 18. ABI / IN-LINE DEMO
  19. 19. API / OUT-OF-LINE from cffi import FFI ffibuilder = FFI() ffibuilder.set_source("_example", r"""#include <sys/types.h> #include <pwd.h> """) ffibuilder.cdef(""" struct passwd { char *pw_name; ...; }; struct passwd *getpwuid(int uid); """) if __name__ == "__main__": ffibuilder.compile(verbose=True)
  20. 20. API / OUT-OF-LINE RUNNING
  21. 21. REBUILD
  22. 22. STATISTICS VULKAN API C HEADER : 5088 LOC XML DESCRIPTION : 6461 LOC
  23. 23. STATISTICS C WRAPPER GENERATED C FILE : 62705 LOC GENERATOR : 1057 PY-LOC / 1141 C-LOC
  24. 24. STATISTICS CFFI WRAPPER GENERATED PYTHON FILE : 4859 LOC GENERATOR : 692 PY-LOC
  25. 25. HOW IT WORKS ?
  26. 26. JINJA2 TEMPLATE
  27. 27. JINJA2 TEMPLATEC EXTENSION ├── converters.c -> 423 ├── custom_functions.c -> 103 ├── custom_structs.c -> 59 ├── extension_functions.c -> 32 ├── functions.c -> 8 ├── header.c -> 11 ├── init.c -> 68 ├── init_unions │ ├── vkclearcolorvalue.c -> 69 │ └── vkclearvalue.c -> 36 ├── macros.c -> 111 ├── main.c -> 122 ├── objects.c -> 99 └── jfilter.py -> 542 Total: 1683
  28. 28. JINJA2 TEMPLATE CFFI EXTENSION ONLY ONE SMALL FILE vulkan.template.py -> 340
  29. 29. SHOW ME THE CODE !
  30. 30. CONSTANTS C EXTENSION CFFI EXTENSION PyModule_AddIntConstant(module, {{name}}, {{value}}); {{name}} = {{value}}
  31. 31. OBJECTS
  32. 32. OBJECTS C EXTENSION NEW (MALLOC) DEL (FREE) INIT GET (FOR EACH MEMBER)
  33. 33. OBJECTS CFFI EXTENSION def _new(ctype, **kwargs): _type = ffi.typeof(ctype) ptrs = {} for k, v in kwargs.items(): # convert tuple pair to dict ktype = dict(_type.fields)[k].type if ktype.kind == 'pointer': ptrs[k] = _cast_ptr(v, ktype) init = dict(kwargs, **{k: v for k, (v, _) in ptrs.items()}) return ffi.new(_type.cname + '*', init)[0]
  34. 34. FAST API MODE
  35. 35. SHADERC WRAPPER
  36. 36. FOLDER DESIGN ├── _cffi_build │ ├── pyshaderc_build.py │ └── shaderc.h ├── pyshaderc │ └── __init__.py └── setup.py
  37. 37. DEFINITION ffi = FFI() with open('shaderc.h') as f: ffi.cdef(f.read())
  38. 38. BUILDING ffi = FFI() with open('shaderc.h') as f: source = f.read() ffi.set_source('_pyshaderc', source, libraries=['shaderc_combined']) if __name__ == '__main__': ffi.compile()
  39. 39. USE
  40. 40. USE from pyshaderc._pyshaderc import ffi, lib
  41. 41. USE def compile_into_spirv(raw, stage, suppress_warnings=False): # initialize compiler compiler = lib.shaderc_compiler_initialize() # compile result = lib.shaderc_compile_into_spv(compiler, raw, len(raw), stage, b"main")
  42. 42. USE length = lib.shaderc_result_get_length(result) output_pointer = lib.shaderc_result_get_bytes(result) tmp = bytearray(length) ffi.memmove(tmp, output_pointer, length) spirv = bytes(tmp) return spirv
  43. 43. SETUPTOOLS INTEGRATION setup( ... cffi_modules=["_cffi_build/pyshaderc_build.py:ffi"] )
  44. 44. DEMO TIME !
  45. 45. GIVE A TRY TO CFFI ! @REALITIX LINAGORA.COM

×