C++에서 Python 코드 사용하기 (Boost.Python 사용)

14499 단어 boost.pythonPythonC++

추기: 함부로 쓰지 않도록 주의해라!


만약 C++로 번거로운 처리를 포기하고 파이톤으로 '가볍다' 를 쓴다면, 절대로 이 글을 쓰지 마세요.
환경 간 파이토존과 포장의 설치 상황 문제 등으로 인해 유지보수를 위해 앞으로 고통스러울 것으로 보인다.
이 글의 방법은 목적 라이브러리가 파이톤에서만 사용할 수 있다면 어떻게든 필요할 때의 최종 수단으로 추천하는 것이다.
기본적으로 C++용 프로그램 라이브러리를 사용해서 C++부터 std::system("python3 xxx.py") 파이톤 명령을 두드리거나 파이톤으로만 코드를 완성하는 것을 권장합니다.
(예를 들어 OpenCV와 Pytric는 C++에서 직접 처리할 수 있고 매트릭스 계산은nupy 대신 C++로 매트릭스 라이브러리에 있는 Eigen을 사용할 수 있다.)

개시하다


Boost.파이톤은 주로 C++를 사용하여 파이톤용 프로그램 라이브러리를 만드는 데 사용되고, 반대로 파이톤의 코드는 C++ 옆에 있는 이른바 '끼워넣기' (Embeding) 에도 사용된다.
C++에서 파이톤을 사용하는 코드에 대한 수요가 많지 않아'boost pythhon'등에서 검색해도 상반된 용도(Pythn에서 C++로 코드를 사용하는 경우)에 대한 글만 나온다.
이 경우, 'embed' (끼워넣기) 라는 검색 키워드가 포함되면, C++에 파이톤이 끼워진 글을 쉽게 찾을 수 있습니다.

가장 간단한 코드 예시


main.cpp
#include <boost/python.hpp>
namespace py = boost::python;

int main()
{
    Py_Initialize(); // 最初に呼んでおく必要あり

    try
    {
        // Pythonで「print('Hello World!')」を実行
        py::object global = py::import("__main__").attr("__dict__");
        py::exec("print('Hello World!')", global);
    }
    catch (const py::error_already_set &)
    {
        // Pythonコードの実行中にエラーが発生した場合はエラー内容を表示
        PyErr_Print();
    }

    return 0;
}
이 견본은 py::exec() 함수를 사용하여 파이톤 코드 print('Hello World!') 를 간단하게 실행합니다.
변수global에 파이톤의 전역 이름 공간 대상을 가져오면 코드가 파이톤의 전역 이름 공간에서 실행됩니다.
Boost.파이톤은 뒤에서 파이톤의 C 인터페이스를 부르기 때문에 사용하기 전에 Py_Initialize() 함수를 먼저 불러야 한다.
(※ 또한 공식 튜토리얼Py_Finalize()에 따라 코드 내에서 호칭할 수 없음)
또한 파이썬이 실행될 때 오류가 발생했을 때py::error_already_set는 형식 예외를 보내기 때문에catch 후PyErr_Print()에 내용이 표시됩니다.

컴파일 방법(Linux+GCC 시)


Linux+GCC에서는 다음 명령을 사용하여 컴파일할 수 있습니다.
편역 방법
$ g++ main.cpp `pkg-config python3-embed --cflags --libs` -lboost_python38
환경에 따라 python3-embed의 버전이 없을 수 있습니다. 적절히 pkg-config python3python3-embed의 버전으로 변경해 주십시오. 원래 버전에서 끼워 넣는 프로그램 라이브러리를 제외하고 pkg-config python3를 사용하면 링크 오류가 발생할 수 있습니다).
또한 상기boost_python38의 부분은 버전과 환경에 따라 boost_python-py38의 형식이 다르다.
링크해야 하는 Boost입니다.파이톤의 라이브러리 이름을 모르면 다음 명령을 통해 조사할 수 있습니다.
나온 lib**.so** 부분은 창고 이름이다.
Boost.파이썬의 라이브러리 이름을 모를 때 조사하는 방법
$ ldconfig -p | grep "boost_python3"

기본용법


다음은 각 구체적인 함수의 사용 방법을 살펴보자.
이후에는 namespace py = boost::python;라고 쓰여 있다고 가정하고 py로 표시한다.
코드의 global는 첫 번째 샘플과 마찬가지로 다음 코드를 통해 얻은 전역 이름 공간 대상입니다.
py::object global = py::import("__main__").attr("__dict__");

■py:eval (): 파이톤으로 공식을 평가하고 결과를 되돌려줍니다


파이톤의 표현식을 문자열로 제시하면 결과는 py::object 형식으로 되돌아옵니다.
아래와 같이 py::extract<型名> 조합은 C++ 형식으로 결과를 얻을 수 있다.
// "2**3"の結果を取得
py::object result = py::eval("2**3", global);

// 結果をint型に変換して出力
std::cout << py::extract<int>(result) << std::endl;
실행 결과
8
이 예에서는 파이썬 내 함수 등을 특별히 사용하지 않아 두 번째 매개변수의 네임스페이스global를 생략해도 이동할 수 있습니다.
그러나 두 번째 인자를 생략하면 pow 등 파이톤이 함수에 삽입되고 다른 사용자가 정의한 변수, 함수를 사용할 수 없음을 주의하십시오.

■py:exec(): 문자열을 통한 파이썬 코드 실행 전달


첫 번째 견본과 같이 py::exec() 함수는 문자열에 파이톤 코드를 제공한 후 바로 실행됩니다.py::eval()와 달리 여러 명령을 실행하거나 분류를 구분할 수 있습니다.
py::exec(
    "print('Hello!')\n"
    "print('World!')", global);
실행 결과
Hello!
World!
변수를 새로 만들면 두 번째 매개변수의 네임스페이스에 생성됩니다.
// Pythonのグローバル名前空間内のresult変数に2**3を代入
py::exec("result = 2**3", global);

// 結果をint型に変換して出力
std::cout << py::extract<int>(global["result"]) << std::endl;
실행 결과
8

■ py::exec_파일에서 Python 코드 실행하기

py::exec_file()를 사용하면 파일 내용을 읽을 수 있으며 py::exec()와 같이 실행할 수 있습니다.
첫 번째 매개 변수는 Pythhon 스크립트의 파일 경로를 지정합니다.
py::exec_file("hello.py", global);
사용자 정의 클래스의 정의를 C++와 분리해서 Python 스크립트 파일로 준비하면 편리합니다.

■py:object::attra():참조 객체의 필드/방법

py::object의 필드(구성원 변수)나 방법(구성원 함수)은 attr() 함수를 사용할 수 있습니다.
str형join 방법을 호출하는 예
// ['hoge','fuga','piyo']というリストを作成
py::object list = py::eval("['hoge','fuga','piyo']", global);

// 「','.join(list)」を実行し、リストの文字列をカンマ区切りで結合
py::object result = py::object(",").attr("join")(list);

// 結果を文字列型に変換して出力
std::string resultStr = py::extract<std::string>(result);
std::cout << resultStr << std::endl;
실행 결과
hoge,fuga,piyo

■py:import():Python 라이브러리 사용

py::import를 사용하면 파이톤의 import 문장과 같이 라이브러리를 가져올 수 있습니다.
py::object np = py::import("numpy");
예를 들어 다음 Python 코드py::exec()는 사용하지 않고 C++로 써 보세요.
matplotlib에 y=x^2 도표의 견본을 표시합니다.
코드 샘플
import numpy as np
import matplotlib.pyplot as plt

x = np.arange(-10, 10, 0.1)
y = x ** 2
plt.plot(x, y)
plt.show()
지금까지 Boost였습니다.파이썬을 사용하여 C++로 작성한 샘플
py::object np = py::import("numpy");
py::object plt = py::import("matplotlib.pyplot");

py::object x = np.attr("arange")(-10, 10, 0.1);
py::object y = x * x;
plt.attr("plot")(x, y);
plt.attr("show")();
(C++측은 직접 쓸 수 없기 때문에x ** 2x * x로 대체)
실행하면 다음 matplotlib을 통해 도표를 표시합니다.

참고 자료

  • 공식 웹사이트 자습서:
  • https://www.boost.org/doc/libs/1_62_0/libs/python/doc/html/tutorial/tutorial/embedding.html
  • 정보 부족...
  • 공식 창고의 샘플 프로그램:
  • https://github.com/boostorg/python/blob/.../example/quickstart/embedding.cpp
  • 본고에서 소개하지 않은 Python류 C++ 자물쇠py::extract()의 전환 예시
  • 좋은 웹페이지 즐겨찾기