LoginSignup
3
2

More than 5 years have passed since last update.

mrb_protect使ってみた

Last updated at Posted at 2016-07-19

今回、mruby-io-consoleを実装した時にmrb_protectの使い方をおぼえたので、内容を共有します。

mrb_protectはmruby標準添付ライブラリーmruby-errorにあるCの関数です。

mrb_protectは、指定した関数内でエラーが起こった場合、エラーをraiseせずエラーオブジェクトを返して処理をアプリケーション側に委ねるものです。
ようするにC内でmrubyのensure的なことがやりたい時に便利です。
実際にmrb_ensureもあるのですが、ensure節でやりたいことが簡単なものであればmrb_protectで十分だと思います。

build_config.rbでmruby-errorを使えるようにして(conf.gembox 'default'に含まれてます)、

Cのソースで

#include "mruby/error.h"

とすれば使えます。

定義は以下。

mrb_value mrb_protect(
  mrb_state *mrb,  // おなじみのやつ
  mrb_func_t body, // コールバック関数
  mrb_value data,  // コールバック関数の引数
  mrb_bool *state  // エラーが起こったらtrue、でなければfalse
);

実装例として、メソッドに与えられたブロックを実行して、エラーでもエラーじゃなくても特定の関数を実行する場合を書いてみます。

// mrb_protectで守りたい部分
static mrb_value
only_yield(mrb_state *mrb, mrb_value block)
{
  // blockをyieldで実行する。
  return mrb_yield_argv(mrb, block, 0, NULL);
}

// 絶対に実行させたい関数
static void
zettai_zikkou(void)
{
  printf("YATTA!\n"); // 絶対に"YATTA!"と表示する
}

static mrb_value
honyahonya_method(mrb_state *mrb, mrb_value self)
{
  mrb_value block;
  mrb_value result;
  mrb_bool state;

  // blockを取得
  mrb_get_args(mrb, "&", &block);

  // resultにはエラーが起こらなかったらonly_yieldの返り値が、
  // エラーが起こったらエラーオブジェクトが入る。
  result = mrb_protect(mrb, only_yield, block, &state);

  // mrb_protectのおかげで
  // エラーが起きようが起きまいが絶対に実行したい関数が呼べる
  zettai_zikkou();

  if (state) { // trueならエラー
    mrb_exc_raise(mrb, result); // ブロックで起こったエラーをそのまま発生させる
  }
  return result; // エラーじゃなかったらonly_yieldの返り値(ブロックの実行結果)を返す
}

こうしてmrb_protectを使うことによって、mruby-io-consoleでもrawモード時にエラーが起こっても、rawモードのまま終了することなく、cookedモードに戻すといったことが実現できました。

リンク

rawモードとcookedモードについて: http://qiita.com/ksss/items/9c8a237f452cd8aa7c11
mruby-errorのソース: https://github.com/mruby/mruby/blob/master/mrbgems/mruby-error/src/exception.c
mruby-io-consoleのソース: https://github.com/ksss/mruby-io-console/blob/f7baf75361f37bdcf4667da24bb98a5006b45c1c/src/io-console.c#L68
mrb_protect導入PR: https://github.com/mruby/mruby/pull/2845

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2