From: Stefan Behnel Date: Thu, 20 Jan 2011 20:36:13 +0000 (+0100) Subject: rewrote the initial tutorial on calling into C libraries X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=9be1a5271548d6ffe3bb42bbdcf16deaac2cb958;p=cython.git rewrote the initial tutorial on calling into C libraries --- diff --git a/src/tutorial/external.rst b/src/tutorial/external.rst new file mode 100644 index 00000000..6af6887f --- /dev/null +++ b/src/tutorial/external.rst @@ -0,0 +1,79 @@ +Calling C functions +==================== + +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 +and handling errors, see :doc:`clibraries`. + +For simplicity, let's start with a function from the standard C +library. This does not add any dependencies to your code, and it has +the additional advantage that Cython already defines many such +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 +a ``char*`` value. You could use the ``atoi()`` function, as defined +by the ``stdlib.h`` header file. This can be done as follows:: + + 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! + +You can find a complete list of these standard cimport files in +Cython's source package ``Cython/Includes/``. It 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:: + + from cpython.version cimport PY_VERSION_HEX + + print PY_VERSION_HEX >= 0x030200F0 # Python version >= 3.2 final + +Cython also provides declarations for the C math library:: + + from libc.math cimport sin + + cdef double f(double x): + return sin(x*x) + +However, this is a library that is not linked by default on Unix-like +systems, such as Linux or MacOS-X. In addition to cimporting 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 +``libraries`` parameter of the ``Extension()`` setup:: + + from distutils.core import setup + from distutils.extension import Extension + from Cython.Distutils import build_ext + + ext_modules=[ + Extension("demo", + ["demo.pyx"], + libraries=["m"]) # Unix-like specific + ] + + setup( + name = "Demos", + cmdclass = {"build_ext": build_ext}, + ext_modules = ext_modules + ) + +If you want to access C code for which Cython does not provide a ready +to use declaration, you must declare them yourself. For example, the +above ``sin()`` function is defined as follows:: + + cdef extern from "math.h": + double sin(double) + +This instructs Cython to generate code that imports the ``math.h`` +header file and declares the ``sin()`` function in a way that makes it +available to Cython code. The C compiler will see the original +declaration in ``math.h`` at compile time, but Cython does not parse +"math.h" and requires a separate definition. + +Just like the ``sin()`` function from the math library, it is possible +to declare and call into any C library as long as the module that +Cython generates is properly linked against the shared or static +library. diff --git a/src/tutorial/index.rst b/src/tutorial/index.rst index 925e46c6..d7972a60 100644 --- a/src/tutorial/index.rst +++ b/src/tutorial/index.rst @@ -4,6 +4,7 @@ Tutorials .. toctree:: :maxdepth: 2 + external clibraries cdef_classes pxd_files