前置き
最近、数値計算する言語をpythonからcに移植しています。
cでグラフをプロットするのに良いライブラリはないかと探して、matplotlib-cppがおすすめされていたので軽い気持ちで使おうとしたらエラーにハマりました。
lava/matplotlib-cpp
環境はVScodeのDockerのc++向けのubuntuサンプルを少しいじっただけだったので環境のせいではないと思います。(一応末尾にDockerfile載せときます)
先にオチを言ってしまうと、matplotlib-cppに限った話でなく、外部ライブラリを使うときにはそのライブラリが内部で使っている他のライブラリを入れたり、ライブラリパスやライブラリ自体を指定し無ければなりませんでした。
エラー
まず1のエラーがでて、1を解決したら2のエラーに悩まされました。
-
fatal error: Python.h: No such file or directory
matplotlib-cpp.hないで使うpythonヘッダがないよっていうエラー。
-
error: ld returned 1 exit status
(おそらくこの場合は)ライブラリが不足していて未定義の関数, 変数があるよっていうエラー。
chatGPT様に聞いたところ、/usr/bin/ldにはLinuxシステム上で使用されるリンカー(linker)プログラムの実行可能ファイルがあり、オブジェクトファイルのリンクに問題が無ければ0, 問題があれば1を返すのだそう。
解決策
-
環境にpython, matplotlib(+numpy)パッケージをインストールして、インクルードパスを指定しなければなりませんでした。numpyに限ってはコンパイル時に
WITHOUT_NUMPY
を指定すれば入れてなくてもいいそうです。apt install libpython3-all-dev python3-matplotlib python3-numpy
Dockerfileに書いておくと楽ですね。
実行時は-I/usr/include/python3.10
のようにiclude以下のpythonまでパスを指定します。Macでhomebrewを使っている方ならパスは
/opt/homebrew/include/python3.10
になるんでしょうか。 -
上でライブラリを入れても、それをコンパイラに認識してもらわなければなりませんでした。
-L/usr/lib/python3.10 -lpython3.10
のようにライブラリのパスと使用するライブラリを指定すれば大丈夫でした。
結果的にコンパイル時のプロンプトは
g++ -O3 -std=c++20 animation.cpp -I/usr/include/python3.10 -L/usr/lib/python3.10 -lpython3.10
となりました。animation.cppはmatplotlib-cppのサンプルコードです。pythonのバージョンはその時々でインストールされたものに変えてください。
vscodeを使っている方はsettings.jsonで"code-runner.executorMap"を編集すれば毎回入力しなくて済みますね。
Dockerfile
FROM mcr.microsoft.com/devcontainers/cpp:0-ubuntu-22.04
ARG REINSTALL_CMAKE_VERSION_FROM_SOURCE="3.22.2"
\# Optionally install the cmake for vcpkg
COPY ./reinstall-cmake.sh /tmp/
RUN if [ "${REINSTALL_CMAKE_VERSION_FROM_SOURCE}" != "none" ]; then \
chmod +x /tmp/reinstall-cmake.sh && /tmp/reinstall-cmake.sh ${REINSTALL_CMAKE_VERSION_FROM_SOURCE}; \
fi \
&& rm -f /tmp/reinstall-cmake.sh \
&& apt update \
&& export DEBIAN_FRONTEND=noninteractive \
&& apt install -y \
libeigen3-dev \
libpython3-all-dev \
python3-numpy \
python3-matplotlib
参考
stackoverflowのおかげで解決できました。
c言語からpythonを埋め込んだ場合に-py-initializeが存在しないエラーが発生する
間違っている所などありましたら、コメントで指摘お願いします。