kumitatepazuru's blog

中学生のメモブログ。みんなの役に立ちたい。

C++をpythonで実行した時に関数の戻り値とかってC++側はどうやって入手させよう?

f:id:kumitatepazuru:20201206122322p:plain

まさかの2日連続投稿。

注意と言う名の宣伝

今回は前回の記事の続きになっているのでまず先にそちらをみることをおすすめします。

kumitatepazuru.hatenablog.com

インストールは良かったけど...

関数の戻り値とかってC++側はどうやって入手するの? そんなふうに思って検索をしたら、ありましたありました。

stackoverflow.com

As explained before, using PyRun_SimpleString seems to be a bad idea.

訳: 前に説明したように、PyRun_SimpleStringを使用することはあまりいい考えじゃないと思うよ。

なるほどね。それは薄々気付いていたよ。それで?

You should definitely use the methods provided by the C-API (http://docs.python.org/c-api/).

訳: C-APIで提供されるメソッドを使用しなくちゃ考えてることは実現できないよ。 (http://docs.python.org/c-api/).

そうなの?あれちょっと面倒じゃない?

First, import your module

PyObject* myModuleString = PyString_FromString((char*)"mytest");
PyObject* myModule = PyImport_Import(myModuleString);

Then getting a reference to your function

PyObject* myFunction = PyObject_GetAttrString(myModule,(char*)"myabs");
PyObject* args = PyTuple_Pack(1,PyFloat_FromDouble(2.0));

Then getting your result

PyObject* myResult = PyObject_CallObject(myFunction, args)

And getting back to a double

double result = PyFloat_AsDouble(myResult);

マジで?天才かよ。

実践

main.cpp

#include <Python.h>
#include <iostream>

int main() {
    Py_Initialize();
    PyObject* myModuleString = PyUnicode_FromString((char*)"mytest");
    PyObject* myModule = PyImport_Import(myModuleString);
    PyObject* myFunction = PyObject_GetAttrString(myModule,(char*)"myabs");
    PyObject* args = PyTuple_Pack(1,PyFloat_FromDouble(2.0));
    PyObject* myResult = PyObject_CallObject(myFunction, args);
    double result = PyFloat_AsDouble(myResult);
    std::cout << result << std::endl;
    Py_Finalize();
    return 0;
}

mytest.py

import math

def myabs(x):
    return math.fabs(x)

ビルド&実行

$ gcc main.cpp `pkg-config python3 --cflags` -lpython3.8 -lstdc++
$ PYTHONPATH=. ./a.out
2

出典元のプログラムはパスが通っておらず、セグメンテーション違反になってしまったので、実行時にPYTHONPATH=. a.outでパスを設定してあげている。gccの引数については前回の記事を見てほしい。

C/C++で何もライブラリを使用せずにpythonを動かしてみる。 - kumitatepazuru's blog

最後に

ちょっと面倒だけど、使い方をマスターすれば最強かも...?


個人的な質問等はこちらまで。

https://forms.gle/V6NRhoTooFw15hJdA

また、自分が参加しているRobocup soccer シミュレーションリーグのチームでは参加者募集中です!活動の見学、活動に参加したい方、ご連絡お待ちしております!

詳しくはこちら

kumitatepazuru.github.io