I want to use a Python function from within C++ code. To this end, I created a short CPython file with the function, compiled this file with Cython to C++ code and header and finally include the header file in a C++ main file.
The CPython file src/mypylib.pyx
looks as follows:
# distutils: language=c++
from libcpp.string cimport string
cdef public string lookup(string name):
return "Hello from Python!"
The build file setup.py
looks as follows:
from setuptools import setup, Extension
from Cython.Build import cythonize
setup(
name='mypylib',
ext_modules=cythonize(
Extension(
"mypylib", ["src/mypylib.pyx"],
),
)
)
The application's main file src/main.cpp
looks as follows:
#include <iostream>
#include <string>
#include "mypylib.h"
int main() {
std::string res = lookup("hello");
std::cout << "Result: " << res << std::endl;
}
I build and run the code as follows:
$ python setup.py build
$ cd src
$ g++ -fPIC -I/usr/include/python3.6 main.cpp mypylib.cpp -lpython3.6m -lpthread -ldl -lutil -lm -Xlinker -export-dynamic -Wl,-O1 -Wl,-Bsymbolic-function
$ ./a.out
Segmentation fault
Why and where would such a simple application have a segmentation fault? The stack trace is apparently as follows:
__Pyx_PyObject_AsStringAndSize(_object*, long*)
__pyx_convert_string_from_py_std__in_string(_object*)+
lookup
main
My environment:
- Ubuntu 18.04
- Python==3.6.9
- Cython==0.29.21
- g++==8.3.0
I'm honestly unsure where to start to debug this problem. Is this a software problem or did I missed something in my CPython code?
EDIT: Solution
As pointed out in the comments, I forgot to initialize the Python interpreter and I didn't import my CPython module. A working C++ main function would look like this:
#include <iostream>
#include <string>
#include <Python.h>
#include "mypylib.h"
int main() {
auto err = PyImport_AppendInittab("mypylib", PyInit_mypylib);
Py_Initialize();
auto mypylib = PyImport_ImportModule("mypylib");
std::string res = lookup("hello");
std::cout << "Result: " << res << std::endl;
Py_Finalize();
}
PyInit_mypylib
is defined in the mypylib.h
header file generated by Cython.