3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

mruby/cデバイス側のC実装

Last updated at Posted at 2018-10-27

はじめに

mruby/cを勉強中なので少しずつ書いていく予定です。(デバイス側のCの実装)
間違っている箇所があればコメントしていただけるとありがたいです。
(mrb・mrbcがバージョンの違いで混ざっているかもしれない)

mruby/cの導入やチュートリアルに関してはこちらを参照くださいm(_ _"m)

ハードウェア設定:hal.h

新しいハードウェアへ適応させるための記述法

上がタイマーを使用する場合の記述で下がタイマーを使用しない場合となっている。
タイマーを使用する場合は別途タイマーの実装が必要となる。
タイマーを使用しない場合は1ms単位のスリープを入れてあげる。

下記PIC32の例
xc32を使用(ドキュメント:MPLAB® XC32 C/C++ コンパイラユーザガイド)

hal.h
# ifndef MRBC_NO_TIMER
# define hal_init()        ((void)0)
# define hal_enable_irq()  __builtin_enable_interrupts()
# define hal_disable_irq() __builtin_disable_interrupts()
# define hal_idle_cpu()    _wait()

# else // MRBC_NO_TIMER
# define hal_init()        ((void)0)
# define hal_enable_irq()  ((void)0)
# define hal_disable_irq() ((void)0)
# define hal_idle_cpu()    ((delay(1)), mrbc_tick())

# endif

ちなみにdelayは作った関数 → https://qiita.com/aikawa_YO/items/3f95c597907c53f0999d

クラス、メソッド定義

MY_CLASS.funcを定義する。

void main{
  mrb_class *my_class;
  my_class = mrbc_define_class(0, "MY_CLASS",	mrbc_class_object);
  mrbc_define_method(0, my_class, "func",	c_func);
}

関数の書き方

/*
mrb_vm *vm    :vm構造体へのポインタ
mrb_value v[] :引数
 v[0]:自分自身
  v[1..n]:引数
int argc      : 引数の数
*/
static void c_func(mrb_vm *vm, mrb_value v[], int argc){}

関数の中身

static void c_func(mrb_vm *vm, mrb_value v[], int argc)
{
  # 引数6個ありますか?
  if(argc == 6){}
  # 引数の型をチェック
  # v[1].tt :引数1のタイプ 
  # タイプはvalue.hに定義されてる
  #ストリングですか?
  if(v[1].tt == MRB_TT_STRING){};
  # フロートですか?
  if(v[2].tt == MRB_TT_FLOAT){};
  
  #引数を受け取る
  # intの場合
  int nam = v[4].i;
  

  # 文字列を返す
  mrb_value moji = mrbc_string_new_cstr(vm, "moji");
  SET_RETURN(moji);
  # 配列を返す
  mrb_value hako = mrbc_array_new(vm, 4);
  SET_RETURN(hako);
}

int

取得した整数をそのまま返すプログラム

関数名 役割 第一引数 第二引数
[mruby value].i int化
SET_INT_RETURN intを返す int
static void c_test(mrb_vm *vm, mrb_value *v, int argc)
{
    int val;
    //値を取得(int)
    if(v[1].tt == MRB_TT_FIXNUM){
        val = v[1].i;
    };
    /* 別方法
    val = GET_INT_ARG(1);
    */

    //intを返す
    SET_INT_RETURN(val);

    /* 別方法
    mrb_value mv = mrb_fixnum_value(val);
    SET_RETURN(mv);
    */
}

float

取得した浮動小数点数をそのまま返すプログラム

関数名 役割 第一引数 第二引数
[mruby value].d float化
SET_FLOAT_RETURN floatを返す float
static void c_test_float(mrb_vm *vm, mrb_value *v, int argc)
{
    double val;
    
    //値を取得(float)
    if(v[1].tt == MRB_TT_FLOAT){
        val = v[1].d;
    };
    /* 別方法
    val = GET_FLOAT_ARG(1);
    */

    //floatを返す
    SET_FLOAT_RETURN(val);

    /* 別方法
    mrb_value mv = mrb_float_value(val);
    SET_RETURN(mv);
    */
}

配列

取得した配列をそのまま返すプログラム(整数のみが入った配列)

関数名 役割 第一引数 第二引数
mrbc_array_size 配列のサイズを取得 引数
mrbc_array_get 配列の要素を取得 引数 取得したい配列位置番号
mrbc_array_new 新しくruby用の配列作成 vm 配列のサイズ
mrbc_array_set ruby用配列に値を挿入 mruby value(配列) 挿入位置 mruby value(挿入値)
SET_RETURN ruby用の値を返す mruby value
static void c_test_array(mrb_vm *vm, mrb_value *v, int argc)
{
  //rubyから配列取得
  int n = mrbc_array_size(&v[1]);
  int a[n]; //aがc用の配列
  for(int i=0;i < n;i++){
    a[i] = mrbc_array_get(&v[1] ,i).i;
  }
  //配列の取得完了

  //ruby用の配列に入れ直して返す
  mrbc_value hako = mrbc_array_new(vm, n);
  for(int j=0;j < n;j++){
    mrbc_value v = mrb_fixnum_value(a[j]);
    mrbc_array_set(&hako,j,&v);
  }
  SET_RETURN(hako);
}

hash

関数名 役割 第一引数 第二引数
mrbc_hash_size ハッシュ数を取得 引数
mrbc_hash_iterator イテレーター取得? 引数
mrbc_hash_i_has_next 次の要素を確認有無 mrb_hash_iterator
mrbc_hash_i_next キーを取得 mrb_hash_iterator
static void c_test(mrb_vm *vm, mrb_value *v, int argc)
{
    int val;
    val = mrbc_hash_size(&v[1]);
    mrb_hash_iterator it = mrbc_hash_iterator(&v[1]);
    mrb_value a;
    int ab[val];
    int num = 0;
    for(int num=0;mrbc_hash_i_has_next(&it);num++){
        mrb_value *key = mrbc_hash_i_next(&it);
        a =  mrbc_hash_get(&v[1], key);
        ab[num] = a.i;
    }
    mrb_value hash = mrbc_array_new(vm, val);
    for(int j=0;j < val;j++){
      mrb_value v = mrb_fixnum_value(ab[j]);
      mrbc_array_set(&hash,j,&v);
    }
    
    SET_RETURN(hash);
}

文字列

文字が"a"なのかチェックするプログラム

関数名 役割 第一引数 第二引数
mrbc_string_size 文字の数を取得 引数
mrbc_string_cstr 文字列を取得 引数
mrbc_string_new_cstr 新しくruby用の文字列作成 vm 文字列
SET_RETURN ruby用の値を返す mruby value
static void c_test_string(mrb_vm *vm, mrb_value *v, int argc)
{
  mrb_value moji;
  //int size = mrbc_string_size(&v[1]);

  //文字列取得
  char *mo = mrbc_string_cstr(&v[1]);

  //判別
  if(!strcmp(mo, "a")){
    moji = mrbc_string_new_cstr(vm, "ok");
  }else{
    moji = mrbc_string_new_cstr(vm, "no");
  }
  
  //文字を返す(ok or no)
  SET_RETURN(moji);
}
3
1
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
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?