On 07/11/2017 12:14, Lele Gaifax wrote:
bartc <b...@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) {...

--
https://mail.python.org/mailman/listinfo/python-list

Reply via email to