| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Name | Name | Last commit date | ||
|---|---|---|---|---|
A complete project which demonstrates how to use CFFI 1.0 during development of a modern Python package:
This repository is the result of a weeks worth of frustrated googling. I don't think anything is too misleading, but I would deeply appreciate feedback from anyone who actually knows what's going on.
cffi_example/person.py and cffi_example/build_person.py is an example of a Python class which wraps a C class, including proper memory management and passing around string buffers:
>>> p = Person(u"Alex", u"Smith", 72) # --> calls person_create(...) >>> p.get_full_name() # --> calls person_get_full_name(p, buf, len(buf)) u"Alex Smith"
cffi_example/fnmatch.py and cffi_example/build_fnmatch.py is an example of wrapping a shared library (in this case libc's fnmatch):
>>> fnmatch("f*", "foo") # --> calls libc's fnmatch
True
Clone the repository:
$ git clone git@github.com:wolever/python-cffi-example.git
Make sure that cffi, py.test, and tox are installed:
$ pip install -r requirements-testing.txt
Run python setup.py develop to build development versions of the modules:
$ python setup.py develop ... Finished processing dependencies for cffi-example==0.1
Test locally with py.test:
$ py.test test/ =========================== test session starts =========================== platform darwin -- Python 2.7.2 -- py-1.4.28 -- pytest-2.7.1 rootdir: /Users/wolever/code/python-cffi-example, inifile: collected 7 items test/test_fnmatch.py .... test/test_person.py ... ======================== 7 passed in 0.03 seconds =========================
Test against multiple Python environments using tox:
$ tox ... _________________________________ summary _________________________________ py26: commands succeeded py27: commands succeeded py33: commands succeeded pypy: commands succeeded congratulations :)
I prefer to use make to clean and rebuild libraries during development (since it's faster than setup.py develop):
$ make clean ... $ make python cffi_example/build_person.py python cffi_example/build_fnmatch.py
This example uses CFFI's recommended combination of setuptools and cffi_modules:
$ cat setup.py
from setuptools import setup
setup(
...
install_requires=["cffi>=1.0.0"],
setup_requires=["cffi>=1.0.0"],
cffi_modules=[
"./cffi_example/build_person.py:ffi",
"./cffi_example/build_fnmatch.py:ffi",
],
)
This will cause the modules to be built with setup.py develop or setup.py build, and installed with setup.py install.
Note: Many examples you'll see online use either the distutils ext_modules=[cffi_example.ffi.distribute_extension()] method, or the more complex keywords_with_side_effects method. To the best of my knowledge these methods are only necessary with CFFI < 1.0 or distutils. dstufft has written a fantastic post — https://caremad.io/2014/11/distributing-a-cffi-project/ — which details the drawbacks of the ext_modules method and explains the keywords_with_side_effects method, but I believe it was written before CFFI 1.0 so it does not include the now preferred cffi_modules method.
Distribution is just like any other Python package, with the obvious caveat that wheels will be platform-specific:
$ python setup.py sdist bdist_wheel ... $ ls dist/ cffi-example-0.1.tar.gz cffi_example-0.1-cp27-none-macosx_10_8_intel.whl
And the package can be uploaded to PyPI using upload:
$ python setup.py sdist upload
Note that users of the source package will need to have cffi (and a C compiler, and development headers of any libraries you're linking against) installed to build and install your package.
Note also that the MANIFEST.in file will need to be updated to include any new source or headers you may add during development. The tox tests will catch this error, but it may not be obvious how to correct it.
| Back | FazBrowse Home | New Git URL |