Commit 6e4779ce authored by scoder's avatar scoder Committed by GitHub

Merge pull request #2326 from gabrieldemarmiesse/test_calling_c_functions

Adding tests for the code snippets in "Calling C functions".
parents 60e6c1fd e9fdcd7f
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!
"""
>>> sin(0)
0.0
"""
cdef extern from "math.h":
cpdef double sin(double x)
cdef extern from "string.h":
char* strstr(const char *haystack, const char *needle)
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)
print(pos != NULL)
from libc.math cimport sin
cdef double f(double x):
return sin(x * x)
from cpython.version cimport PY_VERSION_HEX
# Python version >= 3.2 final ?
print(PY_VERSION_HEX >= 0x030200F0)
from distutils.core import setup
from distutils.extension import Extension
from Cython.Build import cythonize
ext_modules = [
Extension("demo",
sources=["demo.pyx"],
libraries=["m"] # Unix-like specific
)
]
setup(name="Demos",
ext_modules=cythonize(ext_modules))
...@@ -13,13 +13,9 @@ functions for you. So you can just cimport and use them. ...@@ -13,13 +13,9 @@ functions for you. So you can just cimport and use them.
For example, let's say you need a low-level way to parse a number from 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 a ``char*`` value. You could use the ``atoi()`` function, as defined
by the ``stdlib.h`` header file. This can be done as follows:: by the ``stdlib.h`` header file. This can be done as follows:
from libc.stdlib cimport atoi .. literalinclude:: ../../examples/tutorial/external/atoi.pyx
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!
You can find a complete list of these standard cimport files in You can find a complete list of these standard cimport files in
Cython's source package Cython's source package
...@@ -30,19 +26,13 @@ Cython declarations that can be shared across modules ...@@ -30,19 +26,13 @@ Cython declarations that can be shared across modules
Cython also has a complete set of declarations for CPython's C-API. Cython also has a complete set of declarations for CPython's C-API.
For example, to test at C compilation time which CPython version For example, to test at C compilation time which CPython version
your code is being compiled with, you can do this:: your code is being compiled with, you can do this:
from cpython.version cimport PY_VERSION_HEX
# Python version >= 3.2 final ?
print PY_VERSION_HEX >= 0x030200F0
Cython also provides declarations for the C math library:: .. literalinclude:: ../../examples/tutorial/external/py_version_hex.pyx
from libc.math cimport sin Cython also provides declarations for the C math library:
cdef double f(double x): .. literalinclude:: ../../examples/tutorial/external/libc_sin.pyx
return sin(x*x)
Dynamic linking Dynamic linking
...@@ -52,24 +42,9 @@ The libc math library is special in that it is not linked by default ...@@ -52,24 +42,9 @@ The libc math library is special in that it is not linked by default
on some Unix-like systems, such as Linux. In addition to cimporting the on some Unix-like systems, such as Linux. In addition to cimporting the
declarations, you must configure your build system to link against the declarations, you must configure your build system to link against the
shared library ``m``. For distutils, it is enough to add it to the shared library ``m``. For distutils, it is enough to add it to the
``libraries`` parameter of the ``Extension()`` setup:: ``libraries`` parameter of the ``Extension()`` setup:
from distutils.core import setup
from distutils.extension import Extension
from Cython.Build import cythonize
ext_modules=[
Extension("demo",
sources=["demo.pyx"],
libraries=["m"] # Unix-like specific
)
]
setup(
name = "Demos",
ext_modules = cythonize(ext_modules)
)
.. literalinclude:: ../../examples/tutorial/external/setup.py
External declarations External declarations
--------------------- ---------------------
...@@ -95,15 +70,9 @@ library. ...@@ -95,15 +70,9 @@ library.
Note that you can easily export an external C function from your Cython Note that you can easily export an external C function from your Cython
module by declaring it as ``cpdef``. This generates a Python wrapper module by declaring it as ``cpdef``. This generates a Python wrapper
for it and adds it to the module dict. Here is a Cython module that for it and adds it to the module dict. Here is a Cython module that
provides direct access to the C ``sin()`` function for Python code:: provides direct access to the C ``sin()`` function for Python code:
"""
>>> sin(0)
0.0
"""
cdef extern from "math.h": .. literalinclude:: ../../examples/tutorial/external/cpdef_sin.pyx
cpdef double sin(double x)
You get the same result when this declaration appears in the ``.pxd`` You get the same result when this declaration appears in the ``.pxd``
file that belongs to the Cython module (i.e. that has the same name, file that belongs to the Cython module (i.e. that has the same name,
...@@ -124,19 +93,15 @@ names like this:: ...@@ -124,19 +93,15 @@ names like this::
However, this prevents Cython code from calling it with keyword However, this prevents Cython code from calling it with keyword
arguments (supported since Cython 0.19). It is therefore preferable arguments (supported since Cython 0.19). It is therefore preferable
to write the declaration like this instead:: to write the declaration like this instead:
cdef extern from "string.h": .. literalinclude:: ../../examples/tutorial/external/keyword_args.pyx
char* strstr(const char *haystack, const char *needle)
You can now make it clear which of the two arguments does what in 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 your call, thus avoiding any ambiguities and often making your code
more readable:: more readable:
cdef char* data = "hfvcakdfagbcffvschvxcdfgccbcfhvgcsnfxjh"
pos = strstr(needle='akd', haystack=data) .. literalinclude:: ../../examples/tutorial/external/keyword_args_call.pyx
print pos != NULL
Note that changing existing parameter names later is a backwards Note that changing existing parameter names later is a backwards
incompatible API modification, just as for Python code. Thus, if incompatible API modification, just as for Python code. Thus, if
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment