Reputation: 1080
Here is my basic problem:
I have a Python file with an import of
from math import sin,cos,sqrt
I need this file to still be 100% CPython compatible to allow my developers to write 100% CPython code and employ the great tools developed for Python.
Now enter Cython. In my Python file, the trig functions get called millions of times (fundamental to the code, can't change this). Is there any way that through some Python-fu in the main python file, or Cython magic otherwise I can instead use the C/C++ math functions using some variation on the Cython code
cdef extern from "math.h":
double sin(double)
That would give me near-C performance, which would be awesome.
Stefan's talk says specifically this can't be done, but the talk is two years old, and there are many creative people out there
Upvotes: 10
Views: 6970
Reputation: 953
Answering this question eight years later, this is what worked for me on Ubuntu 19.10 using the system CPython vesion 3.7.5 and Cython3 version 0.29.10 from the Ubuntu repostory.
The Cython documents on Pure Python Mode give an example that works. It looks a bit different to the examples in the old answers here so I guess the document has been updated since.
The Python file needs a conditional import, which works fine using normal CPython:
#!/usr/bin/env python3
# from: https://cython.readthedocs.io/en/latest/src/tutorial/pure.html
# mymodule.py
import cython
# override with Python import if not in compiled code
if not cython.compiled:
from math import sin
# calls sin() from math.h when compiled with Cython and math.sin() in Python
print(sin(0.5))
The Cython language constructs must be put in a file with the same name but a ".pxd" suffix:
#cython: language_level=3
# from: https://cython.readthedocs.io/en/latest/src/tutorial/pure.html
# mymodule.pxd
# declare a C function as "cpdef" to export it to the module
cdef extern from "math.h":
cpdef double sin(double x)
I used the "--embed" option to create C-code for a stand-alone Linux ELF executable to test this. The GCC compiler line needs "-lm" to import the maths module that contains sin.
cython3 --embed mymodule.py
gcc -o mymodule mymodule.c -I/usr/include/python3.7 -lpython3.7m -lm
Upvotes: 1
Reputation: 831
In an example from Cython's documentation, they use a cimport from a C library to achieve this:
from libc.math cimport sin
Upvotes: 4
Reputation: 3231
I may have misunderstood your problem, but the Cython documentation on interfacing with external C code seems to suggest the following syntax:
cdef extern from "math.h":
double c_sin "sin" (double)
which gives the function the name sin
in the C code (so that it correctly links to the function from math.h
), and c_sin
in the Python module. I'm not really sure I understand what this achieves in this case, though - why would you want to use math.sin
in Cython code? Do you have some statically typed variables, and some dynamically typed ones?
Upvotes: 0
Reputation: 28846
I'm not a Cython expert, but AFAIK, all you could do is write a Cython wrapper around sin
and call that. I can't imagine that's really going to be faster than math.sin
, though, since it's still using Python calling semantics -- the overhead is in all the Python stuff to call the function, not the actual trig calculations, which are done in C when using CPython too.
Have you considered using Cython pure mode, which makes the source CPython-compatible?
Upvotes: 2