non vorrei lavorare

昔はおもにプログラミングやガジェット系、今は?

Ubuntu16.04LTSでapt install imagemagick-devしてもImageMagickがリンクされない件

おはようございます。長男発熱で実家に数日いましたが、次男の時とは違い徐々に回復して、自宅に戻ってきました。@kjunichiです。

背景

mruby-mrmagickを最近はWindowsメインで開発すること多く、 久しぶりにLinux環境でビルドをしようとして躓いた。

トラブル

Magick++-configがなくてmruby-mrmagickのビルドで怒られた。

sudo apt install libmagick++-dev

と、それっぽいパッケージを入れたが、それでも Magick++-configが見つからない!と怒られる。

調査

dpkg -L libmagick++-dev
/.
/usr
/usr/share
/usr/share/doc
/usr/share/doc/libmagick++-dev
/usr/share/doc/libmagick++-dev/copyright
/usr/share/doc/libmagick++-dev/changelog.Debian.gz
/usr/share/doc/libmagick++-dev/NEWS.Debian.gz

あれ、.soファイルすらインストールされていない!

じゃぁ、/usr/bin/Magick++-configはどのパッケージで入るのか?

apt-fileコマンドで確認できた。

以下の様にapt install直後にデータベースの更新をする必要がある。

sudo apt install apt-file
apt-file update
apt-file search /usr/bin/Magick++-config
graphicsmagick-libmagick-dev-compat: /usr/bin/Magick++-config

ということで、graphicsmagick-libmagick-dev-compatパッケージを入れれば良いことが分かった。

sudo apt install graphicsmagick-libmagick-dev-compat
dpkg -L graphicsmagick-libmagick-dev-compat
/.
/usr
/usr/include
/usr/bin
/usr/share
/usr/share/doc
/usr/share/doc/graphicsmagick-libmagick-dev-compat
/usr/share/doc/graphicsmagick-libmagick-dev-compat/copyright
/usr/share/perl5
/usr/share/perl5/Image
/usr/share/perl5/Image/Magick.pm
/usr/share/man
/usr/share/man/man3
/usr/share/man/man3/Image::Magick.3.gz
/usr/share/man/man1
/usr/lib
/usr/lib/pkgconfig
/usr/include/Magick++
/usr/include/Magick++.h
/usr/include/magick
/usr/include/wand
/usr/bin/Wand-config
/usr/bin/Magick-config
/usr/bin/Magick++-config
/usr/share/doc/graphicsmagick-libmagick-dev-compat/changelog.Debian.gz
/usr/share/man/man1/Wand-config.1.gz
/usr/share/man/man1/Magick-config.1.gz
/usr/share/man/man1/Magick++-config.1.gz
/usr/lib/libMagick++.so
/usr/lib/libMagick.so
/usr/lib/libWand.so
/usr/lib/pkgconfig/ImageMagick++.pc
/usr/lib/pkgconfig/ImageMagick.pc

以下の様にGraphicsMagickにシンボリックリンクが張られていた。

ls -l /usr/lib/libMagick++.so 
lrwxrwxrwx 1 root root 22 Dec 18  2015 /usr/lib/libMagick++.so -> libGraphicsMagick++.so

学んだこと

Ubuntu 16.04LTSでは普通にMagick++-configしてリンクするとgraphicsmagickが使われる。

apt-fileコマンド便利

まえまえから、便利コマンドっぽいことはうっすら感じていたが、ヘタレが使う軟弱なツールだろ!と 敬遠していたwしかし、今回のトラブルで役に立ち、常用することにするw。

参考資料

ずいぶん前にブクマしてたのにすっかり忘れてた。

miettal.hatenablog.com

関連記事

ImageMgaickつながり

mruby-mrmagickにMrmagick#formatsを追加した

こんばんは。次男と実家にちょっと前にきたと思ったら、今度は長男が発熱で保育園から呼び出され、そのまま実家に来ている@kjunichiです。

背景

自分自身がどの様な画像フォーマットに対応しているかの一覧を取得することで、 利用者に、別のImageMagickや、指定したオプションやライブラリをサポートしたものを 組み込んでくれ!といったAI的な動きが可能になり、ユーザーフレンドリーになれるのではないかと考え作業を始めた。 (RMagickが対応しているのにしてないからともいう)

思い出したことや学んだこと

  • mrbgemでC++のコードを呼び出す
  • C++での文字列連結
  • メッソッドにブロックが指定されているかを判定するには
  • ImageMagickでデフォルトでサポートされている画像形式に関して
  • Cでのmrubyのハッシュの作り方

mrbgemでC++のコードを呼び出す

C++側では「extern "C"」を付けて宣言しておく。一時期、この辺り、mrubyではC++の扱いが 変わって混乱があったと記憶しているが、今は、一般的なCとC++の連携方法で通用するようになったっぽい。

extern "C" mrb_value
mrb_mrmagick_formats(mrb_state *mrb, mrb_value self)

C側で

extern mrb_value
mrb_mrmagick_formats(mrb_state *mrb, mrb_value self);

とexternで受けて、以下の様に直接mrb_define_module_functionにC++側の関数を直接指定できる。

mrb_define_module_function(mrb, mrmagick_module, "capi_formats", mrb_mrmagick_formats, MRB_ARGS_NONE());

mrb_define_module_functionに登録するのにいったんCで関数をかます必要はない。

C++での文字列連結

最近のC++での文字列はホント便利。

#include <string>
using namespace std;

string str;

とstring型で変数strを宣言すれば、あとはメモリ領域の事など考えずに代入したり、つなげたり出来る。

str = "*";
if ( entry->isReadable() ) 
  str += "r"; 
else 
  str += "-"; 
if ( entry->isWritable() ) 
  str += "w"; 
else 
  str += "-"; 
if ( entry->isMultiFrame() ) 
  str += "+"; 
else 
  str += "-";

編集して出来たC++の文字列は以下の様にmrb_str_newにてmrubyの文字列に変換できる。

mrb_value val = mrb_str_new(mrb, str.c_str(), str.length());

メッソッドにブロックが指定されているかを判定するには

ブロックはそのメソッドの最後の引数でしか取れないという制限があった記憶があるが、 今回は、そもそもブロックがあれば、ブロックを受け取るだけなので、引数の順番は特に考慮する必要がなかった。 受け取る際には「&」を変数名の前につける事さえ忘れなければ、あとは特に気にするところは無い。 具体的には以下の様に記述。

def self.formats(&blk)
    #puts "formats"
    h = self.capi_formats
    if blk then
      h.each {|item|
        blk.call(item)
      }
    else 
      return h
    end
end

ImageMagickでデフォルトでサポートされている画像形式に関して

これは、テストを書く際に必要になった。

ImageMagick - File Formats

を読む限り、

は、ImageMagick単独でサポートされているようだった。

Webでよく使うJPEGPNGはライブラリを入れてる必要がある。

Cでのmrubyのハッシュの作り方

本家のRMagickで#formtsメソッドはハッシュを返すので、mruby-mrmagickもこれに合わせて、 ハッシュを返すようにした。

そのため、取得した対応フォーマットの文字列からハッシュを作成する方法を学んだ。

// ハッシュの用意
mrb_value table = mrb_hash_new(mrb);

// キー
string keystr = "key";
mrb_value key = mrb_str_new(mrb, keystr.c_str(), keystr.length());
// 値
mrb_value val = mrb_str_new(mrb, str.c_str(), str.length());

// キーと値をハッシュにセットする
mrb_hash_set(mrb, table, key, val);

課題

最初のフィールドがダミー。RMagickではネイティブブロブの対応有無のフィールドとなっているが、 Magick++ APIでどうやって取得するにか分からなかった。

あと、このことを英語でドキュメント化すること

関連記事

13年前の記事

8年前の記事

7年前の記事

mruby-mrmagickをWindowsでもv7系のImageMagickに対応させた

おはようございます。次男がちょっと咳をするようになってますが、鼻水も多めで、ちょっと花粉症疑惑もかかってます。@kjunichiです。

背景

ちょっと前にCI環境を整備した。 この時に長らく結果的にv6系のImageMagickにしか対応していたWindows向けの mruby-mrmagickをv7系に対応した。

学んだこと

DLLの名称がv7とv6で異なっていた

v6だと

  • CORE_RL_magick_
  • CORE_RL_Magick++_
  • CORE_RL_wand_

v7だと

  • CORE_RL_MagickCore_
  • CORE_RL_Magick++_
  • CORE_RL_MagickWand_

と、共有ライブラリの名称が微妙に異なっていた。

対策

Rakeファイルで以下のようにインストールされているImageMagickのバージョンで 分岐を設けて、この差異に対応した。

文字列の比較は以下のメソッドを知って、これを使った。 mrbgem作れるけど、Rubyは勉強中なのでw。。

obj#include?(文字列)

当初、v6の指定を6としていて、

ImageMagick-7.0.3-Q16

もv6と判定されてしまった。

 imHome.include?("-6")

と前方にハイフンをつけることでこれに対応した。

関連記事

3年後の記事