C++からPythonを呼び出す時、環境構築でハマった
題名の通り、makeコマンドを使っての環境構築でハマったので対処法を記載します。
環境は以下です。
OS:ubuntu 18.04
Python:3.6.8
現象
C++からpythonを呼び出す場合、C++のコードの先頭でPython.hというファイルをインクルードする必要があり、安直にPython.hの場所を調べmakefileにそのパスを記載しました。
すると、makeコマンド実行時に以下のメッセージが出ました。
make python undefined reference to py_initialize'
ソースコード内に記載したPy_Initializeが見つからない・・・
そりゃヘッダーファイルインクルードしただけでsoファイルとか読めてないから仕方ないですよね。。。
対処法
下記リファレンスに記載ありますが、unix系のOSで推奨されるコンパイルオプション、リンクオプションを調べられます。
1. 他のアプリケーションへの Python の埋め込み — Python 3.8.2 ドキュメント
これに従って、オプションを調べます。
推奨されるコンパイルオプション
$ /opt/bin/python3.6-config --cflags
推奨されるリンクオプション
$ /opt/bin/python3.6-config --ldflags
makefileのCFLAGにコンパイルオプションを、LDFLAGSにリンクオプションを追加すればmakeコマンド実行時のエラーは解決しました。
リファレンスちゃんと読めばハマらなかったんだけどなぁ・・・
フォルダごとzip、unzipするスクリプト
ubuntuで特定のディレクトリ配下をディレクトリ毎にzip、解凍するスクリプトを記載します。
環境:ubuntu18.04
ディレクトリ配下のディレクトリ毎にzipにするスクリプト
#! /bin/bash input_dir='/home/user/input' output_dir='/home/user/zip' cd $input_dir dir=$(ls -d */) for dir in $dirs do ret=$(dir%/) dirname="${input_dir}/${ret}" filrname="${output_dir}/${ret}.zip" zip -r $filename $ret done
処理は以下の流れです。
まずカレントをinput_dirに移動し、lsコマンドで配下のディレクトリの一覧を取得します。
lsコマンドで取得したフォルダ名を1つづつfor文でループし、%/で末尾の/を削除します。
最後にpathをくっつけて、zip化します。
ディレクトリ配下のzipファイルを全て別フォルダにunzipするスクリプト
#! /bin/bash iinput_dir='/home/user/zip' output_dir='/home/user/out' cd $input_dir files=`find $input_dir -name "*.zip"` for file in $files do echo $file unzip $file -d $output_dir done
処理は以下の流れです。
まずカレントをinput_dirに移動し、findコマンドで拡張子がzipのファイルの一覧を取得します。
findコマンドで取得したファイルを1つづつfor文でループしoutput_dirに解凍します。
QLabelでの画像のリサイズ方法
QPixmapで画像を開きQLabel上に画像を貼り付けるというのはよくやると思います。
QLabelのサイズを超える画像をQPixmapで開いた場合はリサイズする必要がありますよね。
そんなとき、下のツイートの問題が発生しました。
今日ハマったこと
— yam (@yamamon_Lab) 2020年4月1日
QPixmap::scaled()は戻り値を使う
scaled呼び出したインスタンスがリサイズされると勘違いしてて小一時間ムダにした…
リサイズにハマったので、対処法を記載します。
(ツイートに答え書いてるけどね・・・)
環境:python3.6.8, PyQt5
関連するリファレンスは以下です。
QPixmap:QPixmap Class | Qt GUI 5.15.0
ダメなコード
import sys from PyQt5.QtCore import Qt from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QVBoxLayout from PyQt5.QtGui import QPixmap class ImageViewer(QWidget): def __init__(self): super().__init__() self.width = 512 self.height = 512 self._init_ui() def _init_ui(self): self.resize(self.width,self.height) layout = QVBoxLayout() self.title = QLabel() self.image = QLabel() layout.addWidget(self.image) self.setLayout(layout) pixmap = QPixmap('test.png') pixmap.scaled(self.width,self.height,Qt.KeepAspectRatio,Qt.FastTransformation) self.image.setPixmap(pixmap) self.show() if __name__ == '__main__': app = QApplication(sys.argv) widget = ImageViewer() sys.exit(app.exec_())
このコードを実行すると512 x 512を超えるサイズの画像を表示するとウインドウが広がってしまいます。
正しく動くコード
import sys from PyQt5.QtCore import Qt from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QVBoxLayout from PyQt5.QtGui import QPixmap class ImageViewer(QWidget): def __init__(self): super().__init__() self.width = 512 self.height = 512 self._init_ui() def _init_ui(self): self.resize(self.width,self.height) layout = QVBoxLayout() self.title = QLabel() self.image = QLabel() layout.addWidget(self.image) self.setLayout(layout) pixmap = QPixmap('test.png') pixmap = pixmap.scaled(self.width,self.height,Qt.KeepAspectRatio,Qt.FastTransformation) self.image.setPixmap(pixmap) self.show() if __name__ == '__main__': app = QApplication(sys.argv) widget = ImageViewer() sys.exit(app.exec_())
このコードを実行すると512 x 512を超えるサイズの画像を表示してもウインドウは512 x 512で固定となります。
何がいけなかったのか?
全てはQPixmapの仕様に対する私の勘違いに原因がありました。
ミソになるのは下の一文です。
pixmap = pixmap.scaled(self.width,self.height,Qt.KeepAspectRatio,Qt.FastTransformation)
QPixmapにはscaled()というメソッドがあり、このメソッドを使用することでリサイズできます。
私はscaled()を呼び出した、QPixmapのインスタンスがそのままリサイズされると考えていました。
(↑referenceよく読め・・・)
しかし実際は、scaled()の戻り値のQPixmapの変数にリサイズ後のデータが格納され、scaled()を呼び出したインスタンスは何も変化していません。
ダメな例では scaled() を呼び出した後もそのインスタンスを使い続けていたため画像が正しくリサイズされませんでした。
皆さんもお気をつけください。
Qtの環境構築
Qt環境構築で少し詰まったので備忘録。
と言ってもあまり、使うことはないかもですが・・・
まずダウンロードページは↓
ここからダウンロードすると、バージョンを直感的に指定してダウンロードできます。
今回は5.13.0を使いたいので5.13/をクリック
続いて5.13.0を再度クリック
対応するOSを選んでクリック
Windowsなら『qt-opensource-windows-x86-5.13.0.exe』
Macなら『qt-opensource-mac-x64-5.13.0.dmg』
Linuxなら『qt-opensource-linux-x64-5.13.0.run』
Macならpipで入れてもよいと思いますが、今回はインストーラーでのインストール方法を説明します。
インストーラーのダウンロードが終わったらインストーラーを起動しましょう!
この後に一つはまりポイントがあります。
(私は後で自分の無知さ加減に死にたくなりました・・・)
確か英語表示だとSelect Componentって出てたと思いますが、この画面をそのままスルーしてしまい、QtがVisual Studioで使えないとか、Eclipseで使えないってなりました・・・
さて、今回はVisual Studio 2017を例にとりますので、迷わず下の赤枠をチェック!
あとはそのまま流れに任せてインストールを続けてください。
要はここで自分のIDEなどに合うものを選択すればよいです。
余談として、Visual Studio2017上でQtを使う手順を説明します。
1.Visual Studio 2017を起動
2.ツールバーのツールから拡張機能と更新プログラムをクリック
3.オンラインタブをクリックし、ウインドウ右上の検索ボックスにQtと入力します。
以下の画像のように結果が表示されたら、ダウンロードをクリック
4.ダウンロードが完了したらVisual Studioの全ウインドウを終了します。
5.Visual Studio 終了後 インストール用のWindowが表示されるのでModifiyを選択してインストール
6.Visual Studio を起動し、ツールバーのQt VS ToolsよりQt Optionsを選択
Qt OptionsではVisual Studioで使用するQtを設定できます。
Addボタンを押下し、使用するQtのバージョンを指定します。
Version nameは何でもよいと思いますが、わかりやすいように今回であれば『Qt-5.13.0』とするとよいと思います。
PathはQtをインストールしたフォルダ内の対応した『msvc2017_64』があるフォルダを指定します。
例えば、Cドライブ直下にQtをインストールしている場合、以下になります。
『C:\Qt\Qt5.13.0\5.13.0\msvc2017_64』
以上となります。
Visual Studio 2017のダウンロード (Visual Studio 過去バージョンのダウンロード)
開発環境を整えるため、Visual Studio 2017をダウンロードしたかったが参考になる外部サイトが見つからなかった(本家サイトが上位に出てるのですが気づきませんでした。。。)ので同じことでつまらないように備忘録として記載します。
この方法を使えば Visual Studio の最新版以外を手軽に入手できます。
2017、2015、2010どれでも大丈夫です。
さて、今回はVisual Studio 2017を例に説明します。
まず、以下のURLにアクセスします。
移動したら、community版であれば下記赤枠のアイコンをクリックすればインストーラーのダウンロードが始まります。
めちゃくちゃ簡単に入手できました。
Visual Studio 2017で検索をかけると最新版だったころにトップページからダウンロードした記事しかなく困りました・・・
誰かのお役に立てば幸いです。
初投稿!
はじめまして!
yamamonといいます。
このブログでは私生活で得た情報を共有することを目標としています。
正直何も考えていないので、ビジネス書や実用書、IT関連の技術の話もあれば、ゲームや映画といった趣味についても発信すると思います。
その中で何か一つでもいいので共感したり、ご自身の意見を言いたくなるような記事がかければ幸いです。
ご意見があればお気軽にどうぞ(笑)
簡単な自己紹介をさせていただきます。
趣味はマンガ、アニメ、ゲームです。
その影響もあり、今はIT関係の仕事についています。
最近気になっている技術は流行りの機械学習なのですが、仕事では使っていないので、これから手探りでやっていこうと思っています。
将来的には機械学習を利用した皆さんに活用していただける製品を作りたいと考えています。
ということで、趣味全開で自分の書きたいことを書き連ね、たまに自分が学習した技術関連や、読書についても情報を発信できたらと思っています。
これからどうぞよろしくお願いします。