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単独でサポートされているようだった。
Webでよく使うJPEGやPNGはライブラリを入れてる必要がある。
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でどうやって取得するにか分からなかった。
あと、このことを英語でドキュメント化すること
関連記事
- mrubyでselfを呼び出されたメソッドのインスタンスとして実行するには
- mruby-mrmagick開発記 2015初秋編
- mrubyで簡単に回転画像が生成出来るコマンドを作ろうとしている
- mruby-mrmagickをWindowsでもv7系のImageMagickに対応させた