-
Notifications
You must be signed in to change notification settings - Fork 51
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #245 from bzz/initial-cffi-python-bindings
Initial cffi bindings for python
- Loading branch information
Showing
6 changed files
with
161 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
# Python bindings for enry | ||
|
||
Python bingings thoug cFFI (API, out-of-line) for calling enr Go functions though CGo wrapper. | ||
|
||
## Build | ||
|
||
``` | ||
$ make static | ||
$ python enry_build.py | ||
``` | ||
|
||
Will build static library for Cgo wrapper `libenry`, then generate and build `enry.c` | ||
- a CPython extension that | ||
|
||
## Run | ||
|
||
Example for single exposed API function is provided. | ||
|
||
``` | ||
$ python enry.py | ||
``` | ||
|
||
## TODOs | ||
- [ ] try ABI mode, to aviod dependency on C compiler on install (+perf test?) | ||
- [ ] ready `libenry.h` and generate `ffibuilder.cdef` content | ||
- [ ] helpers for sending/recieving Go slices to C | ||
- [ ] cover the rest of enry API | ||
- [ ] add `setup.py` | ||
- [ ] build/release automation on CI (publish on pypi) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
""" | ||
Python library calling enry Go implementation trough cFFI (API, out-of-line) and Cgo. | ||
""" | ||
|
||
from _c_enry import ffi, lib | ||
|
||
## Helpers | ||
|
||
|
||
def go_str_to_py(go_str): | ||
str_len = go_str.n | ||
if str_len > 0: | ||
return ffi.unpack(go_str.p, go_str.n).decode() | ||
return "" | ||
|
||
|
||
def py_str_to_go(py_str): | ||
str_bytes = py_str.encode() | ||
c_str = ffi.new("char[]", str_bytes) | ||
go_str = ffi.new("_GoString_ *", [c_str, len(str_bytes)]) | ||
return go_str[0] | ||
|
||
|
||
def go_bool_to_py(go_bool): | ||
return go_bool == 1 | ||
|
||
|
||
## API | ||
|
||
|
||
def language_by_extension(filename: str) -> str: | ||
fName = py_str_to_go(filename) | ||
guess = lib.GetLanguageByExtension(fName) | ||
lang = go_str_to_py(guess.r0) | ||
return lang | ||
|
||
|
||
def language_by_filename(filename: str) -> str: | ||
fName = py_str_to_go(filename) | ||
guess = lib.GetLanguageByFilename(fName) | ||
lang = go_str_to_py(guess.r0) | ||
return lang | ||
|
||
|
||
def is_vendor(filename: str) -> bool: | ||
fName = py_str_to_go(filename) | ||
guess = lib.IsVendor(fName) | ||
return go_bool_to_py(guess) | ||
|
||
|
||
## Tests | ||
|
||
|
||
def main(): | ||
files = [ | ||
"Parse.hs", "some.cpp", "and.go", "type.h", ".bashrc", ".gitignore" | ||
] | ||
|
||
print("strategy: extension") | ||
for filename in files: | ||
lang = language_by_extension(filename) | ||
print("file: {:10s} language: '{}'".format(filename, lang)) | ||
|
||
print("\nstrategy: filename") | ||
for filename in files: | ||
lang = language_by_filename(filename) | ||
print("file: {:10s} language: '{}'".format(filename, lang)) | ||
|
||
print("\ncheck: is vendor?") | ||
for filename in files: | ||
vendor = is_vendor(filename) | ||
print("file: {:10s} vendor: '{}'".format(filename, vendor)) | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
from cffi import FFI | ||
ffibuilder = FFI() | ||
|
||
# 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(""" | ||
typedef struct { const char *p; ptrdiff_t n; } _GoString_; | ||
typedef _GoString_ GoString; | ||
typedef unsigned char GoUint8; | ||
/* Return type for GetLanguageByExtension */ | ||
struct GetLanguageByExtension_return { | ||
GoString r0; /* language */ | ||
GoUint8 r1; /* safe */ | ||
}; | ||
extern struct GetLanguageByExtension_return GetLanguageByExtension(GoString p0); | ||
/* Return type for GetLanguageByFilename */ | ||
struct GetLanguageByFilename_return { | ||
GoString r0; /* language */ | ||
GoUint8 r1; /* safe */ | ||
}; | ||
extern struct GetLanguageByFilename_return GetLanguageByFilename(GoString p0); | ||
extern GoUint8 IsVendor(GoString p0); | ||
""") | ||
|
||
# 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". | ||
ffibuilder.set_source("_c_enry", | ||
""" | ||
#include "../.shared/libenry.h" // the C header of the library | ||
""", | ||
libraries=['enry'], | ||
library_dirs=['../.shared' | ||
]) # library name, for the linker | ||
|
||
if __name__ == "__main__": | ||
ffibuilder.compile(verbose=True) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
cffi==1.12.3 | ||
Click==7.0 | ||
pycparser==2.19 | ||
yapf==0.27.0 |