Easiest way to access C module in Python
bartc
bc at freeuk.com
Tue Nov 7 08:11:40 EST 2017
On 07/11/2017 12:14, Lele Gaifax wrote:
> bartc <bc at freeuk.com> writes:
>
>> But just staying with the "function with no arguments" for the minute (the
>> equivalent of Hello World for this exercise), how would it be done in
>> Cython? Would a working example be simple enough to show in a usenet post?
>
> fred.c::
>
> int fred(void) {
> return 42;
> }
>
> life.pyx::
>
> cdef extern:
> int fred()
>
> def life():
> return fred()
>
> setup.py::
>
> from distutils.core import setup
> from distutils.extension import Extension
> from Cython.Build import cythonize
>
> setup(
> ext_modules = cythonize([Extension("life", ["life.pyx", "fred.c"])])
> )
>
> $ python setup.py build_ext --inplace
OK, thanks. Although when I get to this bit, my system still says:
17.299999999999997
Traceback (most recent call last):
File "setup.py", line 1, in <module>
from distutils.core import setup
....
So obviously something is wrong with it, but I'll have to assume it
normally works.
> Compiling life.pyx because it changed.
> [1/1] Cythonizing life.pyx
> running build_ext
> building 'life' extension
> creating build
> creating build/temp.linux-x86_64-3.6
> x86_64-linux-gnu-gcc -pthread -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -g -fdebug-prefix-map=/build/python3.6-5reRaQ/python3.6-3.6.3=. -specs=/usr/share/dpkg/no-pie-compile.specs
-fstack-protector-strong -Wformat -Werror=format-security -Wdate-time
-D_FORTIFY_SOURCE=2 -fPIC -I/tmp/ct/include -I/usr/include/python3.6m -c
life.c -o build/temp.linux-x86_64-3.6/life.o
However, it doesn't look that simple a process, and it seems to solve a
different problem from the ctypes solution. That one took an EXISTING
function, already compiled and linked into a binary, and does not need
the C source nor need to compile it. Often, you will only have the
binary shared library anyway.
-I/tmp/ct/include -I/usr/include/python3.6m -c fred.c -o
build/temp.linux-x86_64-3.6/fred.o
OK, compiling fred.c. Is there a dependency on gcc too? This looks more
like makefile hell. People use languages like Python to get away from
this stuff.
> x86_64-linux-gnu-gcc -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions -specs=/usr/share/dpkg/no-pie-link.specs -Wl,-z,relro -specs=/usr/share/dpkg/no-pie-link.specs -Wl,-z,relro -g -fdebug-prefix-map=/build/python3.6-5reRaQ/python3.6-3.6.3=. -specs=/usr/share/dpkg/no-pie-compile.specs -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 build/temp.linux-x86_64-3.6/life.o build/temp.linux-x86_64-3.6/fred.o -o /tmp/ct/life.cpython-36m-x86_64-linux-gnu.so
> $ python -c "import life; print(life.life())"
> 42
>
> As other said, for a single function accepting no arguments and returning a
> single value Cython may be an heavy tool, but I bet you can imagine more
> complex situations...
In my normal work, I'm calling C functions from interpreted code all the
time, just not in Python (example below sig).
It's not that complicated. With this Cython solution you have the .c
(which has to be compiled and linked using this process), you have .pyx,
whatever that is, you have .py which is not really Python, but has to be
processed as Cython, and then you have .py which is actual Python, which
is the code that wanted to call that C function in the first. So simple.
I understand that Cython lets you write Python-like code with special
annotations that allows it to be compiled to efficient native code (or
something like that), but that's not what this task is, which is 100%
Python calling 100% C, with both developed using their normal tools.
--
bartc
# in interpreted code, run as normal:
importdll jpeg =
clang function loadjpeg(string, ref int64, ref int64)ref byte
end
In C:
byte* loadjpeg(char* file, int64* width, int64* height) {...
More information about the Python-list
mailing list