Call a Python script from Embedded Python in C ++ / C ++

This article was written at the online Mokumokukai of the Sapporo C ++ Study Group. The Sapporo C ++ Study Group is looking for participants in the Mokumoku Group. For more information, please contact @ignis_fatuus

Overview

It's hard to do everything in C ++. So partly make it easier with Python. You can do it with Boost.Python. I also tried using it with the Twitter API.

Background Python is convenient. I have a situation where I want to make a GUI application with Python, but there is a problem. A binding library for Qt and Python.

GUI library Python Bindings

To use the GUI with Python, use a GUI library for C or C ++, such as Qt or Gtk. The mechanism for calling these libraries in other languages from Python is called bindings. Qt is a very famous GUI library for C ++, and if you select it, it won't lose much, so I want to use it. There are Gtk and other options, but Qt is safe.

Python Qt bindings

There are PyQt and PySide. You can use PyQt5 to handle the latest version of Qt (as of March 31, 2016), Qt5. However, PyQt5 is a GPL or commercial license, so I would like to avoid it. On the other hand, PySide is the latest stable release version (as of March 31, 2016), PySide 1.2.4 is only compatible with Qt 4.8. PySide2 seems to support Qt5, but at the moment it seems to fail to build on Windows.

The GUI part is done in C ++.

As mentioned above, there is no GUI library that can be used from Python and that I can understand at this time. However, since Qt is originally a C ++ library, you can use its full functionality by writing it in C ++ from the beginning. However, trying to write everything in C ++ is very annoying. Therefore, the part that must be written in C ++ (in this case, the GUI part) is written in C ++, and the internal part that does not require much performance is written in Python. For example, network communication is done in Python. Because even if you improve the performance with C ++, there is a network delay, so there is not much advantage.

What to explain in this article

Explain how to call Python from C ++ using Boost.Python. As an example, I will introduce a program that acquires the Twitter timeline and outputs it to standard output in C ++. Use the Python library tweepy to get the timeline.

Installation

C++、Qt、Python、Boost.Python If you are using Windows Msys2 environment, you can install it with pacman.

$ pacman -S mingw-w64-x86_64-gcc
$ pacman -S mingw-w64-x86_64-qt5
$ pacman -S mingw-w64-x86_64-python3
$ pacman -S mingw-w64-x86_64-gcc

tweepy

$ pip3 install tweepy

Maybe you needed something like python3 -m ensurepip --default-pip. If you want to use pyvenv, virtualenv, etc., you can use it without any problem.

Python script

Write Python code that is called from C ++. The file name is embed.py.

embed.py


#!/usr/bin/env python3
#vim:fileencoding=utf8
import sys
#If you installed tweepy in a different location than usual with pyvenv or Anaconda, specify that location.
# sys.path.append('C:/Anaconda3/envs/MyEnvironments/Lib/site-packages')

#Get the token from Twitter.
consumer_key        = "...."  
consumer_secret     = "...."
access_token        = "...."
access_token_secret = "...."

#For how to use tweepy, refer to other articles and official websites.
import tweepy
auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_token, access_token_secret)
api = tweepy.API(auth)

#Call this function C++Call from
def timeline():
   public_tweets = api.home_timeline()
   tweets = [ (tweet.author.name, tweet.text) for tweet in public_tweets ]
   return tweets

First of all, add the directory where tweepy and its dependent libraries are installed. This is necessary if you're using Anaconda, pyvenv, etc., but may not be necessary if you're not. The tokens required to use the Twitter API are obtained by registering as a developer on the Twitter site and applying for it. I will not explain tweepy in particular. The last defined timeline is the function to call from C ++. This time, the name of the tweeter and the content of the tweet were made into tuples, and the list was returned to make the data on the timeline.

Prepare C ++ source

twitter.cpp


#include<iostream>
#include<string>
#include<fstream>
#include<streambuf>
#include<boost/python.hpp>

#In a python script(tweet.author.name, tweet.text)A structure equivalent to a tuple
struct Status {
    std::string name;
    std::string text;
    Status(const boost::python::tuple t) :
        name(boost::python::extract<std::string>(t[0])),
        text(boost::python::extract<std::string>(t[1]))
    { }
};

int main() {
    //Set the PYTHONHOME environment variable, Py_Initialize()Call before
    //It may not be necessary depending on the environment.
    wchar_t python_home[] = L"c:\\msys64\\mingw64"; //In python2, char is fine. wchar for python3_t。
    Py_SetPythonHome(python_home);

    Py_Initialize();
    auto main_mod = boost::python::import("__main__");
    auto main_ns  = main_mod.attr("__dict__");

    // read python script
    std::ifstream ifs("embed.py");
    std::string script((std::istreambuf_iterator<char>(ifs)),
                        std::istreambuf_iterator<char>());
    // execute python script,
    // but not invoke timeline() function (definition only)
    boost::python::exec(script.c_str(), main_ns);

    // call python's timeline function and get the timeline data
    using input_iterator = boost::python::stl_input_iterator<boost::python::tuple>;
    auto timeline_data = main_mod.attr("timeline")();
    input_iterator begin(timeline_data), end;

    std::vector<Status> tweets(begin,end);
    for(auto tweet: tweets) {
        std::cout << tweet.name << ":" << tweet.text << std::endl;
    }
}

The time for the Mokumokukai has run out, so I will explain it briefly. The first point is "how to receive data from Python". This can be easily done with Iterator in Boost.Python. that is

    using input_iterator = boost::python::stl_input_iterator<boost::python::tuple>;
    auto timeline_data = main_mod.attr("timeline")();
    input_iterator begin(timeline_data), end;
    std::vector<Status> tweets(begin,end);

Part of. I'm really sorry, but the time is up here. Please read the source and guess.

Postscript: Leave only an example of how to build

g++ -o twitter.exe twitter.cpp -std=c++14 -I/mingw64/include/python3.5m -lboost_python3-mt -lpython3.5m

Recommended Posts

Call a Python script from Embedded Python in C ++ / C ++
Run a Python script from a C # GUI application
[Python] How to call a c function from python (ctypes)
Call a Python function from p5.js.
Call C from Python with DragonFFI
Call popcount from Ruby / Python / C #
Solve ABC036 A ~ C in Python
Solve ABC037 A ~ C in Python
Call C / C ++ from Python on Mac
Call c language from python (python.h)
Run the Python interpreter in a script
Generate a class from a string in Python
Use Django from a local Python script
Generate C language from S-expressions in Python
Call a command from Python (Windows version)
Create a New Todoist Task from Python Script
Next Python in C
"Python Kit" that calls a Python script from Swift
Create a datetime object from a string in Python (Python 3.3)
I tried adding a Python3 module in C
C API in Python 3
Run a python script from excel (using xlwings)
C language to see and remember Part 3 Call C language from Python (argument) c = a + b
Try to make a Python module in C language
Receive dictionary data from a Python program in AppleScript
Try embedding Python in a C ++ program with pybind11
A memorandum to run a python script in a bat file
Python points from the perspective of a C programmer
What's in that variable (when running a Python script)
Solve Atcoder ABC176 (A, B, C, E) in Python
Python script to create a JSON file from a CSV file
Extend python in C ++ (Boost.NumPy)
Call CPLEX from Python (DO cplex)
Take a screenshot in Python
Create a function in Python
Create a dictionary in Python
OCR from PDF in Python
Run illustrator script from python
Binary search in Python / C ++
Make a bookmarklet in Python
Dynamically call methods in Python
Draw a heart in Python
I was soberly addicted to calling awscli from a Python 2.7 script registered in crontab
A mechanism to call a Ruby method from Python that can be done in 200 lines
How to slice a block multiple array from a multiple array in Python
How to run a Python program from within a shell script
How to use the __call__ method in a Python class
Let's create a script that registers with Ideone.com in Python.
Get macro constants from C (++) header file (.h) in Python
A set of script files that do wordcloud in Python3
Run a multi-line script in a PDB
Call Matlab from Python to optimize
Execute Python script from batch file
Maybe in a python (original title: Maybe in Python)
Write a binary search in Python
Solve ABC163 A ~ C with Python
Write a table-driven test in C
[python] Manage functions in a list
Touch a Python object from Elixir
Hit a command in Python (Windows)
Get data from Quandl in Python