2012年06月24日

mrubyでNative関数を作るメモ 2012/06

mrubyでNative関数を作るメモ 2012/06
* はじまり
以下の方々のページを参考にさせて頂いて、
2. MRuby 探索
http://www.oki-osk.jp/esc/mruby-oa/02.html
mrubyにクラスとメソッドを組み込んでみた(Windows 7)
http://akasata.hatenablog.com/entry/2012/05/30/202432
mruby で自前の組み込み関数を呼び出してみた。Add Star
http://mattn.kaoriya.net/software/lang/ruby/20120420141103.htm

mrubyスクリプトからNative関数(C言語関数)を呼び出す簡単なプロジェクトの雛形を作ってみました。
(MinGW上の簡単な実行ファイルを生成します)

これができると超組み込みマイコン用の雛形の原型ができたような感じになります。 :D

*コンパイル
makeの実行はMinGWのコンソール上で行います。(注1)

用意する物
(1)このファイル mruby_native_c_test_v01_201206.tar.gz
(2)mrubyのコンパイル済み(MinGW上で)のソースフォルダ。

(1)をMinGW環境コーンソルで適当なワークフォルダに解凍します。
$ tar zxvf mruby_native_c_test_v01_201206.tar.gz

Makefileの
MRUBY_ROOT = ../../mruby-lf
の部分を各自の環境に合わせて変更します。
指定は絶対パスか相対パスにします。「~/」(ホーム相対表現)を含んだパスだとうまくコンパイルできない様です。
(MRUBY_ROOTにmrubyのソースコードフォルダ名を指定します)

ワークフォルダでmakeを実行すると、
$ make
cat mod_easy_io.rb test.rb  > _tmp.rb
../../mruby-lf/bin/mrbc -Cmain_rb  _tmp.rb
gcc -MMD -MF "dep/main.d" -c -Os -I../../mruby-lf/include -I. -L../../mruby-lf/lib -Wl,-Map=target.map -Wl,--cref main.c -o main.o
gcc -MMD -MF "dep/_tmp.d" -c -Os -I../../mruby-lf/include -I. -L../../mruby-lf/lib -Wl,-Map=target.map -Wl,--cref _tmp.c -o _tmp.o
gcc -MMD -MF "dep/easy_io.d" -c -Os -I../../mruby-lf/include -I. -L../../mruby-lf/lib -Wl,-Map=target.map -Wl,--cref easy_io.c -o easy_io.o
gcc -Os -I../../mruby-lf/include -I. -L../../mruby-lf/lib -Wl,-Map=target.map -Wl,--cref main.o _tmp.o easy_io.o -lmruby -o target.exe
   text    data     bss     dec     hex filename
 296252    2840    2612  301704   49a88 target.exe
という感じで「target.exe」ができるので実行します。 黄色い部分がArduino風の名前のNative関数を呼び出したところ。 この例では関数名と引数を表示するだけのNative関数。 
$ ./target.exe
-- Start ---
Init test --- [ added the string of local variable ]
pinMode( 13, OUTPUT )
pinMode(  1, OUTPUT )
delay_ms( 100 )
digitalOut( 13,  1 )
Direct call from user Class  --- testsub string
Default argument ! --- [ added the string of local variable ]
15.5
Object method call  --- testsub string
digitalOut(  1,  0 )
以下が、メインのmrubyスクリプト。実験用なのでプログラム自体に大きな意味はないです。 Native関数は「EasyIo」(2行目)というモジュール名で定義してあるのでincludeする。
class Msg
	include EasyIo
	def initialize( str )
		@instr = "[ added the string of local variable ]"
		msg( str )
		pinMode( 13, 1 )
		pinMode(  1, 1 )
		delay_ms( 100 )
		digitalOut( 13, 1 )
		test_sub( "Direct call from user Class" ) 
	end

	def msg( str="Default argument !")
		print "\n",str, " --- " + @instr
	end

end

def func_main()
	print "\n--- Start ---"
	obj = Msg.new("Init test")
	obj.msg()
	x =  3.1 * 5
	print "\n", x
	obj.test_sub( "Object method call" )
	obj.digitalOut( 1, 0 );
end

func_main()
以下の「easy_io.c」でモジュール「EasyIo」を定義、登録して、 モジュールメソッドとしてdigitalOut()などのNative関数を定義しました。
#include <mruby.h>
#include <mruby/proc.h>
#include <stdio.h>

struct RClass *mod_easy_io;

static mrb_value delay_ms( mrb_state *mrb, mrb_value self )
{
	mrb_int ms;
	mrb_get_args( mrb, "i", &ms );
	printf("\ndelay_ms( %d )", ms); 

	return self; 
}

static mrb_value digitalOut( mrb_state *mrb, mrb_value self )
{
	mrb_int pin, level;
	mrb_get_args( mrb, "ii", &pin, &level);
	printf("\ndigitalOut( %2d, %2d )", pin, level ); 

	return self; 
}

static mrb_value pinMode( mrb_state *mrb, mrb_value self )
{
	mrb_int pin, mode;
	char *str_mode;
	char *in = "INPUT";
	char *out= "OUTPUT";
	mrb_get_args( mrb, "ii", &pin, &mode);
	str_mode = ( mode == 0 ) ? in : out ;
	printf("\npinMode( %2d, %s )", pin, str_mode ); 

	return self; 
}

void init_easy_io( mrb_state *mrb )
{
	mod_easy_io = mrb_define_module( mrb, "EasyIo");
	mrb_define_method( mrb, mod_easy_io, "delay_ms", delay_ms, ARGS_REQ(1)); 
	mrb_define_method( mrb, mod_easy_io, "digitalOut", digitalOut, ARGS_REQ(2)); 
	mrb_define_method( mrb, mod_easy_io, "pinMode", pinMode, ARGS_REQ(2)); 

}
以下が仮想コードを実行するトップレベルの関数「main.c」。
#include "mruby.h"
#include "easy_io.h"

extern void main_rb( mrb_state* mrb);

int main()
{
	mrb_state* mrb = mrb_open();

	init_easy_io( mrb );
	main_rb( mrb );

	mrb_close( mrb );
	return 0;
}
*超組み込みマイコン用(注2)に変更する ここまでくると上の雛形を基にして、 (1) gccを「arm-none-eabi-gcc」等に変更。 (2) リンカスクリプトの追加。 (3) syscall.c 系の関数追加。 で、いけると思う。 (注1) Linux上でも同様なやり方でコンパイル可能です。 (注2)超組み込みマイコンをSRAMが極小のマイコンと定義してみた。(動くかどうかは別として) Information technology -- Programming languages -- Ruby http://www.iso.org/iso/iso_catalogue/catalogue_tc/catalogue_detail.htm?csnumber=59579


posted by Copyright (C) avrin All Rights Reserved. at 00:00| Comment(0) | mruby | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
コメントを書く
お名前: [必須入力]

メールアドレス:

ホームページアドレス:

コメント: [必須入力]

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。
×

この広告は180日以上新しい記事の投稿がないブログに表示されております。