enhancements inlineable

robertwb edited this page Mar 17, 2009 · 9 revisions
Clone this wiki locally

CEP510 - Inlineable code in .pxd files

  • Status: Wanted
  • Implementation status: Done
  • Comments: This is part of DagSverreSeljebotn's GSoC 2008 project proposal

Warning: The author has no experience with the differences between pxd and pyx file and is making big assumptions all over the place. Somebody should look over this and remove this note if things are ok.

Currently, pxd files only contains declarations of things that live in C header files and is not allowed to contain code. pyx files contain code, and are compiled to Python modules. This gives a clear separation between declaration/export and the implementation.

The arguments in favor of this are easy to spot. This document will make a case for allowing code to live in pxd files anyway, and specify what is done about it.


Rather than only being allowed to declare the method in the pxd file, it should also be possible to provide a body. If a body is provided:
  • The method/function must be decorated with the inline
  • It is not allowed to provide an implementation in the pyx file

Specifically, the body of the method is used by the cimporting module to generate the appropriate code.

Public API: If possible, we should implement this so that inlineable functions doesn't get access to private members of the class. At any rate, any documentation on this feature must stress that inlineable code should only make use of the public API of the types, because as the code is going to be compiled into other modules, any changes in pxd files containing inlineable code means that all Cython modules built using it must also be rebuilt. If one only makes use of the public API (ie the inlineable code only covers standalone convenience functions) then already built modules should continue to work as expected.

Methods implemented like this will be included in the generated C file, marked "static inline", and left to GCC for inlining. See example on why this is necesarry.

This is all analogous to how inlineable functions is put in .h-files in C/C++.



cdef class Log:
    def log(self, str)

    cdef inline void debug(self, object str):
        self.log("DEBUG: %s" % str)

logging.pyx contains the implementation of the Log class (with the log method, but not the debug method).


cinclude logging

...make use of Log.debug()...


/* We do not have access to logging.c from here - luckily we
   implemented Log.debug in the pxd file so it is dumped as
   an inlineable function for GCC to find here. */

static inline void mangled_name_Log_debug(self, PyObject* s) {
  mangled_name_Log_log(self, s);


mangled_name_Log_debug(log, ...)


Inlining for speed purposes, while not having to write C code to do what one wants in a header file. Why should one have to choose between writing the code in C or not having it inlined?

  • To make the GCC able to inline across modules at all, this is needed. (This is not often needed, but sometimes, especially on things like implementing convenient NumPy operators in Cython -- making a non-inlineable function call for accessing an array won't work for numerical use).
  • This leaves the way open for methods having different behaviour depending on type arguments to be stream-lined by the Cython compiler depending on the compile-time type argument. If the method lives in a pyx file (and thus in another compiled module one doesn't have access to) then the type argument-specific behaviour has to be checked at run-time. Again this is useful for NumPy.

Future possibilites / current problems

This leads to multiple translation of any inlined methods to C, and also one cannot use precompiled headers like might be the case for things like this.

However I think that the functionality above is a precondition for doing anything about this; in the next stage, one can always implement a mode where Cython will translate a pure pxd file to a h file containing only the inlineable code, which can be used in a more advanced build system, in order for the code to only be translated to C once.