3

I try to conditionally compile (or generate) to c code from a Cython pxd. I read that I can DEF to define aa value and IF to conditionally generate based on its value, but how can I get this value to get from outside of the pxd file?

Specifically these two cases are interesting for me now:

  • give some command-line define to Cython, preferrably through the Cython.Distutils setuptools way
  • the extern-ed C header file defines some value, and conditionally define using Cython based on this value (maybe impossible now?)

Thank you

ron
  • 9,262
  • 4
  • 40
  • 73
  • Actually the second point is not viable, since as I learned Cython doesn't actually parse the externed header files. – ron Sep 30 '10 at 13:48
  • A better answer to a similar problem is given in http://stackoverflow.com/questions/26225187/try-statement-in-cython-for-cimport-for-use-with-mpi4py/26226758#26226758. (I don't know if that was a viable solution when this question was asked) – DavidW Jan 04 '17 at 19:30
  • @DavidW The answer using `compile_time_env` is indeed easier (probably), but it won't automatically recompile if the values change. The method in the accepted answer here will (but see my comment under it). – lapis Apr 29 '20 at 19:47

2 Answers2

13

You could generate a pxi file, and include it before doing your IF (same as ./configure generate a config.h too.) This is what we do in Kivy setup.py for example :

c_options = { 
'use_opengl_es2': True,
'use_opengl_debug': False,
'use_glew': False,
'use_mesagl': False}

print 'Generate config.pxi'
with open(join(dirname(__file__), 'kivy', 'graphics', 'config.pxi'), 'w') as fd:
    for k, v in c_options.iteritems():
        fd.write('DEF %s = %d\n' % (k.upper(), int(v)))

And then, in your pxd :

include "config.pxi"
IF USE_OPENGL_DEBUG == 1:
  # do other import or whatever you want
tito
  • 12,990
  • 1
  • 55
  • 75
  • You can also do the same generation of a "config.h" by duplicate and change `'DEF %s = %d'` to `'#define %s %d'` – tito Mar 02 '11 at 00:19
  • i found that editing that file doesn't trigger cache busting of that file. i.e. if you change config.pxi, the old one will be still built. any way around that? – Ilia Sidorenko Jan 27 '17 at 12:50
  • ah got a way, need to include config.pxi into source_files in your setup.py – Ilia Sidorenko Jan 27 '17 at 12:54
  • You probably also want to generate config.pxi only when the options change, e.g. move the options to a separate file and check if it's newer than config.pxi. Otherwise the pxd is recompiled every time. BTW, auto-recompilation (i.e. cache busting) works for me even without including config.pxi in sources_list. – lapis Apr 29 '20 at 19:39
3

Actually, the second option is easier. Create a FLAG in some .h file and then do

cdef extern from "header.h":
    cdef int FLAG

then when you want to use it, just write

if FLAG:
    ...

and even though Cython will generate the code, the C compiler will automatically trim this away as it knows the value of FLAG at compile time.

robertwb
  • 4,891
  • 18
  • 21
  • This works ok for simple things, but it won't let you do conditional externs, whereas the accepted answer does. – totaam Apr 09 '14 at 10:40
  • and it wouldn't let you `ctypedef` to decide, for example, between single and double precision floats. So the accepted answer is certainly more powerful – Fred Schoen Mar 15 '17 at 13:45