Beginner, don't know how to call C functions.

30 views
Skip to first unread message

谭九鼎

unread,
May 15, 2021, 10:08:37 AM5/15/21
to cython-users
Hello everyone,

I just started to learn Cython and I have read some of the official docs.

Let's say I have this simple test.h and test.c:

```c
// test.h
int fun(int a);
// test.c
int fun(int a) { return a; }
```

As I understand I have to write this test.pyx:

```pyx
cdef extern from "test.h":
    cpdef int fun(int a)
```

But it seems that I can't use it:

```py
__import__('pyximport').install()
import test
print(test.fun(123))
```

Output from one online jupyter lab:

```
Traceback (most recent call last):
  File "main.py", line 2, in <module>
    import test
ImportError: /data/nas/workspace/jupyter/download/test.cpython-36m-x86_64-linux-gnu.so: undefined symbol: fun
```

Output from Google Colaboratory:

```
Traceback (most recent call last): File "main.py", line 3, in <module> print(test.fun(123)) AttributeError: module 'test' has no attribute 'fun'
```

I don't know what's wrong.


谭九鼎

unread,
May 15, 2021, 11:28:13 AM5/15/21
to cython-users
If I add this in the front of test.pyx

```
# distutils: sources = test.c
```

And use `cythonize test.pyx -i`, the output is:

```
running build_ext
building 'test' extension
creating /data/nas/workspace/jupyter/download/tmpxd6aoxxp/data
creating /data/nas/workspace/jupyter/download/tmpxd6aoxxp/data/nas
creating /data/nas/workspace/jupyter/download/tmpxd6aoxxp/data/nas/workspace
creating /data/nas/workspace/jupyter/download/tmpxd6aoxxp/data/nas/workspace/jupyter
creating /data/nas/workspace/jupyter/download/tmpxd6aoxxp/data/nas/workspace/jupyter/download
gcc -pthread -B /opt/conda/compiler_compat -Wl,--sysroot=/ -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -fPIC -I. -I/data/nas/workspace/jupyter/download -I/opt/conda/include/python3.6m -c /data/nas/workspace/jupyter/download/test.c -o /data/nas/workspace/jupyter/download/tmpxd6aoxxp/data/nas/workspace/jupyter/download/test.o
gcc -pthread -B /opt/conda/compiler_compat -Wl,--sysroot=/ -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -fPIC -I. -I/data/nas/workspace/jupyter/download -I/opt/conda/include/python3.6m -c test.c -o /data/nas/workspace/jupyter/download/tmpxd6aoxxp/test.o
gcc -pthread -shared -B /opt/conda/compiler_compat -L/opt/conda/lib -Wl,-rpath=/opt/conda/lib -Wl,--no-as-needed -Wl,--sysroot=/ /data/nas/workspace/jupyter/download/tmpxd6aoxxp/data/nas/workspace/jupyter/download/test.o /data/nas/workspace/jupyter/download/tmpxd6aoxxp/test.o -o /data/nas/workspace/jupyter/download/test.cpython-36m-x86_64-linux-gnu.so
/data/nas/workspace/jupyter/download/tmpxd6aoxxp/test.o:(.bss+0x0): multiple definition of `__pyx_module_is_main_test'
/data/nas/workspace/jupyter/download/tmpxd6aoxxp/data/nas/workspace/jupyter/download/test.o:(.bss+0x0): first defined here
/data/nas/workspace/jupyter/download/tmpxd6aoxxp/test.o: In function `__Pyx_CyFunction_set_annotations':
/home/admin/jupyter/download/test.c:2134: multiple definition of `PyInit_test'
/data/nas/workspace/jupyter/download/tmpxd6aoxxp/data/nas/workspace/jupyter/download/test.o:/data/nas/workspace/jupyter/download/test.c:2134: first defined here
collect2: error: ld returned 1 exit status
error: command 'gcc' failed with exit status 1
```

谭九鼎

unread,
May 16, 2021, 2:28:45 AM5/16/21
to cython-users
I have figured out some of the reasons.

One is that I shouldn't name it test.pyx, because it would to be compiled to test.c so that conficts with real test.c

Two is that `# distutils: sources = test.c` must be there when using static linking.

But I still have trouble using pyximport. According to docs[^1], I have created a `modname.pyxdep` and write test.h in it.

But the result is:

```
/home/codespace/.pyxbld/temp.linux-x86_64-3.8/pyrex/calltest.c:808:10: fatal error: test.h: No such file or directory
  808 | #include "test.h"
      |          ^~~~~~~~
compilation terminated.
```

When using `pyximport.install(build_in_temp=False)`, the result becomes:

```
ImportError: /home/codespace/.pyxbld/lib.linux-x86_64-3.8/calltest.cpython-38-x86_64-linux-gnu.so: undefined symbol: fun
```

I don't know what to do again.

Stefan Behnel

unread,
May 16, 2021, 6:13:18 AM5/16/21
to cython...@googlegroups.com
谭九鼎 schrieb am 16.05.21 um 05:48:
> I have figured out some of the reasons.
>
> One is that I shouldn't name it test.pyx, because it would to be compiled
> to test.c so that conficts with real test.c
>
> Two is that `# distutils: sources = test.c` must be there when using static
> linking.

That's one way of doing it, yes. If you have your C and Cython sources in
the same project (i.e. you are not using an external system library, for
example), then that's probably ok for you.


> But I still have trouble using pyximport. According to docs[^1], I have
> created a `modname.pyxdep` and write test.h in it.
>
> But the result is:
>
> ```
> /home/codespace/.pyxbld/temp.linux-x86_64-3.8/pyrex/calltest.c:808:10:
> fatal error: test.h: No such file or directory
> 808 | #include "test.h"
> | ^~~~~~~~
> compilation terminated.
> ```

You should rather add the directory that contains "test.h" to the distutils
include dirs of your extension module.

https://cython.readthedocs.io/en/latest/src/userguide/source_files_and_compilation.html#configuring-the-c-build


> When using `pyximport.install(build_in_temp=False)`, the result becomes:
>
> ```
> ImportError:
> /home/codespace/.pyxbld/lib.linux-x86_64-3.8/calltest.cpython-38-x86_64-linux-gnu.so:
> undefined symbol: fun
> ```
>
> I don't know what to do again.

pyximport is known to have its quirks. It doesn't obey the "#distutils"
directive, for one. This is a known issue.

Using cythonize instead of pyximport might work better for you.

Stefan

谭九鼎

unread,
May 16, 2021, 9:56:42 AM5/16/21
to cython-users
Thanks, I know how to use setup.py and cythonize CLI now. Since pyximport has its issue, I won't dive into it. No more questions, cheers.
Reply all
Reply to author
Forward
0 new messages