I was following the Cython tutorial on using C libraries and found out I can do the same for C++, and consulted the equivalent guide. Instead of a class, I wanted to start simple and import and use a function.
After not being succesful with the class-like syntax for defining external functions, like cdef extern from "<filename>":
, I found out a way to properly compile and use the C++ code, but it’s not behaving as expected.
There are 4 files which interact with each other:
hello.cpp
#include <iostream>
void hello_from_cpp() {
std::cout << "Hello from C++!" << std::endl;
}
cpp_hello.pyx
# distutils: language = c++
# cython: language_level = 3
cpdef extern void hello_from_cpp()
def myfun():
hello_from_cpp()
setup.py
from setuptools import setup, Extension
from Cython.Build import cythonize
setup(
ext_modules=cythonize([
Extension("cpp_hello", ["cpp_hello.pyx", "hello.cpp"])
]),
)
main.py
import cpp_hello
if __name__ == "__main__":
cpp_hello.hello_from_cpp()
When this is compiled (cythonized) with python setup.py build_ext --inplace
or python setup.py build_ext -i
, I can run python main.py
and get the return Hello from C++!
as expected.
The weird behavior is that removing the unused myfun()
definition from cpp_hello.pyx
breaks the compilation process
[1/1] Cythonizing cpp_hello.pyx
running build_ext
building 'cpp_hello' extension
creating build
creating build/temp.linux-x86_64-cpython-310
x86_64-linux-gnu-gcc -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O2 -Wall -g -fstack-protector-strong -Wformat -Werror=format-security -g -fwrapv -O2 -fPIC -I/usr/include/python3.10 -c cpp_hello.cpp -o build/temp.linux-x86_64-cpython-310/cpp_hello.o
cpp_hello.cpp: In function ‘int __pyx_pymod_exec_cpp_hello(PyObject*)’:
cpp_hello.cpp:3027:84: error: ‘hello_from_cpp’ was not declared in this scope
3027 | PyObject* wrapped = __Pyx_CFunc_9cpp_hello_void__lParen__rParennoexcept_to_py_(hello_from_cpp);
| ^~~~~~~~~~~~~~
cpp_hello.cpp: At global scope:
cpp_hello.cpp:2362:18: warning: ‘PyObject* __Pyx_CFunc_9cpp_hello_void__lParen__rParennoexcept_to_py_(void (*)())’ defined but not used [-Wunused-function]
2362 | static PyObject *__Pyx_CFunc_9cpp_hello_void__lParen__rParennoexcept_to_py_(void (*__pyx_v_f)(void)) {
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: command '/usr/bin/x86_64-linux-gnu-gcc' failed with exit code 1
My end goal is to be able to create libraries of C++ code which can be used in Python programs. The .pyx
and setup.py
files glue them together by providing Python definitions of the C++ equivalents with cpdef
instead of cdef
.