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
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.
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.
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.
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.
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.
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.
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.
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