未验证 提交 a14a6fc7 编写于 作者: J Jim Anderson 提交者: GitHub

Merge pull request #157 from Znunu/master

Make python bindings article partially work on win
# Real Python - Python Bindings Sample Code Repo
This is the repo to accompany the [Python Bindings](https://realpython.com/python-bindings-overview/) article.
To be able to run the code, you must first install the requirements:
```console
$ python -m pip install -r requirements.txt
```
This should be done inside a virtual environment.
Once that is installed, you can use the invoke tool mentioned in the article to build and run the tests. See the tasks.py file or run invoke --list to get more details.
\ No newline at end of file
#!/usr/bin/env python3
# IDE might complain with "no module found" here, even when it exists
import cffi_example
if __name__ == "__main__":
......
float cmult(int int_param, float float_param);
#ifdef _MSC_VER
#define EXPORT_SYMBOL __declspec(dllexport)
#else
#define EXPORT_SYMBOL
#endif
EXPORT_SYMBOL float cmult(int int_param, float float_param);
\ No newline at end of file
#!/usr/bin/env python
""" Simple examples of calling C functions through ctypes module. """
import ctypes
import pathlib
import sys
if __name__ == "__main__":
# Load the shared library into c types.
libname = pathlib.Path().absolute() / "libcmult.so"
c_lib = ctypes.CDLL(libname)
if sys.platform.startswith("win"):
c_lib = ctypes.CDLL("cmult.dll")
else:
c_lib = ctypes.CDLL("libcmult.so")
# Sample data for our call:
x, y = 6, 2.3
......
""" Task definitions for invoke command line utility for python bindings
overview article. """
overview article.
"""
import cffi
import invoke
import pathlib
import sys
import os
import shutil
import re
import glob
on_win = sys.platform.startswith("win")
@invoke.task
def clean(c):
""" Remove any built objects """
for pattern in ["*.o", "*.so", "cffi_example* cython_wrapper.cpp"]:
c.run("rm -rf {}".format(pattern))
for file_pattern in (
"*.o",
"*.so",
"*.obj",
"*.dll",
"*.exp",
"*.lib",
"*.pyd",
"cffi_example*", # Is this a dir?
"cython_wrapper.cpp",
):
for file in glob.glob(file_pattern):
os.remove(file)
for dir_pattern in "Release":
for dir in glob.glob(dir_pattern):
shutil.rmtree(dir)
def print_banner(msg):
......@@ -17,32 +39,55 @@ def print_banner(msg):
print("= {} ".format(msg))
@invoke.task
def build_cmult(c):
@invoke.task()
def build_cmult(c, path=None):
""" Build the shared library for the sample C code """
print_banner("Building C Library")
invoke.run("gcc -c -Wall -Werror -fpic cmult.c -I /usr/include/python3.7")
invoke.run("gcc -shared -o libcmult.so cmult.o")
print("* Complete")
# Moving this type hint into signature causes an error (???)
c: invoke.Context
if on_win:
if not path:
print("Path is missing")
else:
# Using c.cd didn't work with paths that have spaces :/
path = f'"{path}vcvars32.bat" x86' # Enter the VS venv
path += f'&& cd "{os.getcwd()}"' # Change to current dir
path += "&& cl /LD cmult.c" # Compile
# Uncomment line below, to suppress stdout
# path = path.replace("&&", " >nul &&") + " >nul"
c.run(path)
else:
print_banner("Building C Library")
cmd = "gcc -c -Wall -Werror -fpic cmult.c -I /usr/include/python3.7"
invoke.run(cmd)
invoke.run("gcc -shared -o libcmult.so cmult.o")
print("* Complete")
@invoke.task(build_cmult)
@invoke.task()
def test_ctypes(c):
""" Run the script to test ctypes """
print_banner("Testing ctypes Module")
invoke.run("python3 ctypes_test.py", pty=True)
# pty and python3 didn't work for me (win).
if on_win:
invoke.run("python ctypes_test.py")
else:
invoke.run("python3 ctypes_test.py", pty=True)
@invoke.task(build_cmult)
@invoke.task()
def build_cffi(c):
""" Build the CFFI Python bindings """
print_banner("Building CFFI Module")
ffi = cffi.FFI()
this_dir = pathlib.Path().absolute()
this_dir = pathlib.Path().resolve()
h_file_name = this_dir / "cmult.h"
with open(h_file_name) as h_file:
ffi.cdef(h_file.read())
# cffi does not like our preprocessor directives, so we remove them
lns = h_file.read().splitlines()
flt = filter(lambda ln: not re.match(r" *#", ln), lns)
flt = map(lambda ln: ln.replace("EXPORT_SYMBOL ", ""), flt)
ffi.cdef(str("\n").join(flt))
ffi.set_source(
"cffi_example",
......@@ -66,7 +111,7 @@ def build_cffi(c):
def test_cffi(c):
""" Run the script to test CFFI """
print_banner("Testing CFFI Module")
invoke.run("python3 cffi_test.py", pty=True)
invoke.run("python cffi_test.py", pty=not on_win)
@invoke.task()
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册