diff options
-rw-r--r-- | docs/examples/tutorial/external/atoi.py | 6 | ||||
-rw-r--r-- | docs/examples/tutorial/external/atoi.pyx | 1 | ||||
-rw-r--r-- | docs/examples/tutorial/external/keyword_args_call.py | 8 | ||||
-rw-r--r-- | docs/examples/tutorial/external/keyword_args_call.pyx | 1 | ||||
-rw-r--r-- | docs/examples/tutorial/external/libc_sin.py | 5 | ||||
-rw-r--r-- | docs/examples/tutorial/external/libc_sin.pyx | 1 | ||||
-rw-r--r-- | docs/examples/tutorial/external/py_version_hex.py | 4 | ||||
-rw-r--r-- | docs/examples/tutorial/external/strstr.pxd | 2 | ||||
-rw-r--r-- | docs/src/tutorial/external.rst | 55 |
9 files changed, 79 insertions, 4 deletions
diff --git a/docs/examples/tutorial/external/atoi.py b/docs/examples/tutorial/external/atoi.py new file mode 100644 index 000000000..250b26a5c --- /dev/null +++ b/docs/examples/tutorial/external/atoi.py @@ -0,0 +1,6 @@ +from cython.cimports.libc.stdlib import atoi + +@cython.cfunc +def parse_charptr_to_py_int(s: cython.p_char): + assert s is not cython.NULL, "byte string value is NULL" + return atoi(s) # note: atoi() has no error detection! diff --git a/docs/examples/tutorial/external/atoi.pyx b/docs/examples/tutorial/external/atoi.pyx index 96a67d73c..ef1219854 100644 --- a/docs/examples/tutorial/external/atoi.pyx +++ b/docs/examples/tutorial/external/atoi.pyx @@ -1,5 +1,6 @@ from libc.stdlib cimport atoi + cdef parse_charptr_to_py_int(char* s): assert s is not NULL, "byte string value is NULL" return atoi(s) # note: atoi() has no error detection! diff --git a/docs/examples/tutorial/external/keyword_args_call.py b/docs/examples/tutorial/external/keyword_args_call.py new file mode 100644 index 000000000..af5b06020 --- /dev/null +++ b/docs/examples/tutorial/external/keyword_args_call.py @@ -0,0 +1,8 @@ +import cython +from cython.cimports.strstr import strstr + +def main(): + data: p_char = "hfvcakdfagbcffvschvxcdfgccbcfhvgcsnfxjh" + + pos: p_char = strstr(needle='akd', haystack=data) + print(pos is not cython.NULL) diff --git a/docs/examples/tutorial/external/keyword_args_call.pyx b/docs/examples/tutorial/external/keyword_args_call.pyx index de2b6f2b2..3a6b85c8b 100644 --- a/docs/examples/tutorial/external/keyword_args_call.pyx +++ b/docs/examples/tutorial/external/keyword_args_call.pyx @@ -1,6 +1,7 @@ cdef extern from "string.h": char* strstr(const char *haystack, const char *needle) + cdef char* data = "hfvcakdfagbcffvschvxcdfgccbcfhvgcsnfxjh" cdef char* pos = strstr(needle='akd', haystack=data) diff --git a/docs/examples/tutorial/external/libc_sin.py b/docs/examples/tutorial/external/libc_sin.py new file mode 100644 index 000000000..f4223253d --- /dev/null +++ b/docs/examples/tutorial/external/libc_sin.py @@ -0,0 +1,5 @@ +from cython.cimports.libc.math import sin + +@cython.cfunc +def f(x: cython.double) -> cython.double: + return sin(x * x) diff --git a/docs/examples/tutorial/external/libc_sin.pyx b/docs/examples/tutorial/external/libc_sin.pyx index fb247c03d..2de8444d6 100644 --- a/docs/examples/tutorial/external/libc_sin.pyx +++ b/docs/examples/tutorial/external/libc_sin.pyx @@ -1,4 +1,5 @@ from libc.math cimport sin + cdef double f(double x): return sin(x * x) diff --git a/docs/examples/tutorial/external/py_version_hex.py b/docs/examples/tutorial/external/py_version_hex.py new file mode 100644 index 000000000..3b19d0d02 --- /dev/null +++ b/docs/examples/tutorial/external/py_version_hex.py @@ -0,0 +1,4 @@ +from cython.cimports.cpython.version import PY_VERSION_HEX + +# Python version >= 3.2 final ? +print(PY_VERSION_HEX >= 0x030200F0) diff --git a/docs/examples/tutorial/external/strstr.pxd b/docs/examples/tutorial/external/strstr.pxd new file mode 100644 index 000000000..7c2a786cc --- /dev/null +++ b/docs/examples/tutorial/external/strstr.pxd @@ -0,0 +1,2 @@ +cdef extern from "string.h": + char* strstr(const char *haystack, const char *needle) diff --git a/docs/src/tutorial/external.rst b/docs/src/tutorial/external.rst index 83ec75375..d0c5af0a0 100644 --- a/docs/src/tutorial/external.rst +++ b/docs/src/tutorial/external.rst @@ -1,6 +1,9 @@ Calling C functions ==================== +.. include:: + ../two-syntax-variants-used + This tutorial describes shortly what you need to know in order to call C library functions from Cython code. For a longer and more comprehensive tutorial about using external C libraries, wrapping them @@ -15,7 +18,17 @@ For example, let's say you need a low-level way to parse a number from a ``char*`` value. You could use the ``atoi()`` function, as defined by the ``stdlib.h`` header file. This can be done as follows: -.. literalinclude:: ../../examples/tutorial/external/atoi.pyx +.. tabs:: + + .. group-tab:: Pure Python + + .. literalinclude:: ../../examples/tutorial/external/atoi.py + :caption: atoi.py + + .. group-tab:: Cython + + .. literalinclude:: ../../examples/tutorial/external/atoi.pyx + :caption: atoi.pyx You can find a complete list of these standard cimport files in Cython's source package @@ -28,14 +41,33 @@ Cython also has a complete set of declarations for CPython's C-API. For example, to test at C compilation time which CPython version your code is being compiled with, you can do this: -.. literalinclude:: ../../examples/tutorial/external/py_version_hex.pyx +.. tabs:: + + .. group-tab:: Pure Python + + .. literalinclude:: ../../examples/tutorial/external/py_version_hex.py + :caption: py_version_hex.py + + .. group-tab:: Cython + + .. literalinclude:: ../../examples/tutorial/external/py_version_hex.pyx + :caption: py_version_hex.pyx .. _libc.math: Cython also provides declarations for the C math library: -.. literalinclude:: ../../examples/tutorial/external/libc_sin.pyx +.. tabs:: + .. group-tab:: Pure Python + + .. literalinclude:: ../../examples/tutorial/external/libc_sin.py + :caption: libc_sin.py + + .. group-tab:: Cython + + .. literalinclude:: ../../examples/tutorial/external/libc_sin.pyx + :caption: libc_sin.pyx Dynamic linking --------------- @@ -83,6 +115,9 @@ This allows the C declaration to be reused in other Cython modules, while still providing an automatically generated Python wrapper in this specific module. +.. note:: External declarations must be placed in a ``.pxd`` file in Pure + Python mode. + Naming parameters ----------------- @@ -103,7 +138,19 @@ You can now make it clear which of the two arguments does what in your call, thus avoiding any ambiguities and often making your code more readable: -.. literalinclude:: ../../examples/tutorial/external/keyword_args_call.pyx +.. tabs:: + + .. group-tab:: Pure Python + + .. literalinclude:: ../../examples/tutorial/external/keyword_args_call.py + :caption: keyword_args_call.py + .. literalinclude:: ../../examples/tutorial/external/strstr.pxd + :caption: strstr.pxd + + .. group-tab:: Cython + + .. literalinclude:: ../../examples/tutorial/external/keyword_args_call.pyx + :caption: keyword_args_call.pyx Note that changing existing parameter names later is a backwards incompatible API modification, just as for Python code. Thus, if |