Python FFI through Boost.Python
A simple python FFI example on OpenBSD and macOS.
The program is a minimal example for Boost.Python.
#include <iostream>
#include <boost/python.hpp>
#include <boost/python/module_init.hpp>
using namespace boost::python;
void greet() {
// Retrieve the main module.
object main = import("__main__");
// Retrieve the main module's namespace
object global(main.attr("__dict__"));
// Define greet function in Python.
object result = exec("def greet(): \n"
"\timport sys \n"
"\tprint(sys.version_info)\n"
"\treturn 'Hello from Python 3!' \n", global, global);
// Create a reference to it.
object greet = global["greet"];
// Call it.
std::string message = extract < std::string > (greet());
std::cout << message << std::endl;
}
int main(int argc, char* argv[]) {
Py_Initialize();
greet();
Py_Finalize();
return 0;
}
It seems that compilation and running a program on OpenBSD and macOS differ a lot ...
OpenBSD
Install boost
pkg_add boost
Compile
c++ -I /usr/local/include/
-I /usr/local/include/python3.7m/
-L/usr/local/lib
-lboost_python3
-lpython3.7m
./hellopython.cpp
Run
./a.out
macOS
Install boost with brew
sudo brew install boost-python3
Compile on macOS assuming miniconda was used to get 3.8
conda activate py38
c++ -I /Users/peter/opt/miniconda3/envs/py38/include/python3.8/
-I /usr/local/Cellar/boost/1.73.0/include/
-L /usr/local/Cellar/boost-python3/1.73.0/lib/
-L /Users/peter/opt/miniconda3/envs/py38/lib/
-lboost_python38
-lpython3.8
./hellopython.cpp
Resulting binary has relative library paths. Fix that
Check library references. rpath is relative path
otool -L a.out
Correct paths with install_name_tool
install_name_tool -change @rpath/libc++.1.dylib /usr/lib/libc++.1.dylib a.out
install_name_tool -change @rpath/libpython3.8.dylib
Users/peter/opt/miniconda3/envs/py38/lib/libpython3.8.dylib a.out
Check that references match your system
To run the binary with miniconda paths you need to set PYTHONPATH
export PYTHONPATH=/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/
Finally run the binary
./a.out