Ruby_extLib 3 - gfd-dennou-club/mrubyc-esp32 GitHub Wiki
mruby/c 㯠mruby, Ruby ãšåæ§ã«ïŒ ãœãŒã¹ã³ãŒãããã€ãã³ãŒã (äžéã³ãŒã) ã«ã³ã³ãã€ã«ã, ãããä»®æ³ãã·ã³ (Virtual Machine; VM) ã§å®è¡ãããããªåŠçã®æµãã«ãªã£ãŠãã. ã³ã³ãã€ã«ãŸã§ã®è€éãªåŠçãšä»®æ³ãã·ã³ã®å®è¡ç°å¢ã å¥ã ã«ããããšãã§ããããïŒmruby/c ã§ã¯ä»¥äžã®ããã«äžé£ã®åŠçãããœã³ã³ãšãã€ã³ã³ã«åããŠããïŒ
- Rubyããã°ã©ã ããã€ãã³ãŒãã«ã³ã³ãã€ã« âããœã³ã³ã§è¡ã
- VM (Virtual machine) ã䜿ã£ãŠå®è¡ âãã€ã³ã³ã§è¡ã
mruby/c ã§ã¯ Parser ãš Code Generator ã®éšå (mrbc ã³ãã³ã) 㯠mruby ã®å®è£ ããã®ãŸãŸäœ¿çšã, VM ã ãç¬èªã®ã³ã³ãã¯ããªå®è£ ãçšããŠãã. mruby/c ã§ã¯ã©ã¹ãæ°ãã«å®çŸ©ããå Žåã¯ïŒ[æºå] C èšèªã§ Ruby æ¡åŒµã©ã€ãã©ãªã®äœæ ã®å Žåãšç°ãªãïŒãã€ã³ã³ã®å ¬åŒéçºç°å¢ (C èšèª) ã« Ruby ãçµã¿èŸŒã圢ãšãªãïŒ ããªãã¡ïŒã¡ãŒã«çãçšæãã C èšèªéçºç°å¢ãš VM ã®ãœãŒã¹ã³ãŒãã䜿ã£ãŠ, æ¢åã® C èšèªã®ããã°ã©ã ã« mruby ãã€ãã³ãŒããçµåãã.
ESP-IDF ã®ãµã³ãã«ãã³ããŒããŠïŒãããäœæ¥çšãããžã§ã¯ããšããïŒ
$ cp -r ~/esp/esp-idf/examples/get-started/hello_world ./mrubyc-hello_world
$ cd mrubyc-hello_world/
ESP-IDF ã§ã¯ïŒcomponents ãã£ã¬ã¯ããªä»¥äžã«èªã¿èŸŒããœãŒã¹ã眮ãïŒ ãã®ãœãŒã¹ãã£ã¬ã¯ããªå ã«ã³ã³ãã€ã«æ¹æ³ãæ瀺ãã component.mk ãã¡ã€ã«ã眮ãã®ãæµåã§ããïŒ ãã®ããïŒcomponents ãã£ã¬ã¯ããªãäœæãïŒããã« mrubyc ã®ãœãŒã¹ã git clone ããïŒ ãªãïŒmruby-3.1.0 ã䜿ãã®ã§ïŒmrubyc ã®ãã©ã³ã㯠release3.1 ãšããããšïŒ
$ mkdir components
$ cd components
$ git clone -b release3.1 https://github.com/mrubyc/mrubyc.git
$ cd ../
make ã®ã«ãŒã«ãèšè¿°ããïŒcomponents/mrubyc/component.mk ã®äžèº«ã¯ä»¥äžã®ããã«ããïŒ
CFLAGS = -mlongcalls -DMRBC_USE_HAL_ESP32
COMPONENT_ADD_INCLUDEDIRS := src
COMPONENT_SRCDIRS := src
main/component.mk ã®äžèº«ã¯ä»¥äžã®ããã«ããïŒ
CFLAGS = -mlongcalls -DMRBC_USE_HAL_ESP32
hal (Hardware Abstraction Layer) ã¯ãã€ã³ã³ã®çš®é¡ã«äŸåããã®ã§ïŒ src 以äžã® hal_esp32 (ESP32 çš) ã hal ãžãªããŒã ãã.
$ cd main/
$ ln -s ../components/mrubyc/src/hal_esp32/hal.* .
$ cd ../
ã¡ã€ã³ããã°ã©ã (main/hello_world_main.c) ãç·šéããŠç°¡çŽ åããŠããïŒ
#include <stdio.h>
void app_main(void)
{
int i;
for (i = 0; i < 100; i++) {
printf("%02d, Hello world!\n", i);
}
}
mrubyc ãã£ã¬ã¯ããªå ã®ãœãŒã¹ã®ã³ã³ãã€ã« & å®è¡
$ make
$ make flash
$ make monitor
...(ç¥)...
0, Hello world!
1, Hello world!
2, Hello world!
3, Hello world!
4, Hello world!
...(äžç¥)...
98, Hello world!
99, Hello world!
mruby/c 㧠hello world ãæžãïŒmruby/c ã®ææ³ã¯ Ruby ã®ãµãã»ãããªã®ã§ïŒ hello world çšåºŠã®ããã°ã©ã 㯠mruby/c ãš Ruby ã§å šãåããšãªãïŒ ãŸã㯠Ruby ã®ã¡ã€ã³ããã°ã©ã ã眮ããã£ã¬ã¯ã㪠(src) ãäœæããïŒ
$ mkdir src
ã«ã¬ã³ããã£ã¬ã¯ããªã« .ruby-version ãäœæããïŒ
mruby-3.1.0
äœæãããã£ã¬ã¯ããªå ã«ã¡ã€ã³ããã°ã©ã ãäœæããïŒsrc/master.rb ã以äžã®ããã«æžãïŒ
100.times do |i|
puts "#{sprintf('%02d',i)} Hello World! from ESP32 by mruby/c"
sleep 1
end
äžèšã® mruby/c ã³ãŒãã mrbc ã§ã³ã³ãã€ã«ããŠäžéã³ãŒã (ãã€ãã³ãŒã) ãçæããïŒ mruby/c åŽã®ã¡ã€ã³ããã°ã©ã ã¯ããããã¡ã€ã«ãšã㊠C èšèªåŽã®ã¡ã€ã³ããã°ã©ã (main/hello_world_main.c) ã«èªã¿èŸŒãã®ã§ïŒåºåãã¡ã€ã«å㯠main/master.h ãšããŠããïŒ
$ mrbc -B master -o main/master.h src/master.rb
$ ls main/master.*
main/master.h main/master.rb (<-- .h ãã¡ã€ã«ãåºæ¥ãŠãã)
ã³ã³ãã€ã«ããçµæåŸããããã¡ã€ã« (main/master.h) å ãèŠãŠã¿ããšïŒ äžè¿°ã® mrbc ã³ãã³ãã® -B ã®åŒæ°ã§æž¡ããåå (master) ã® é åãå®çŸ©ãããŠããïŒããã®äžã«ãã€ãã³ãŒããåã蟌ãŸããŠããããšãåããïŒ
$ less main/master.h
#include <stdint.h>
#ifdef __cplusplus
extern
#endif
const uint8_t master[] = {
0x52,0x49,0x54,0x45,0x30,0x33,0x30,0x30,0x00,0x00,0x00,0xeb,0x4d,0x41,0x54,0x5a,
0x30,0x30,0x30,0x30,0x49,0x52,0x45,0x50,0x00,0x00,0x00,0xb9,0x30,0x33,0x30,0x30,
0x00,0x00,0x00,0x29,0x00,0x01,0x00,0x03,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x0d,
0x03,0x01,0x64,0x57,0x02,0x00,0x30,0x01,0x00,0x00,0x38,0x01,0x69,0x00,0x00,0x00,
0x01,0x00,0x05,0x74,0x69,0x6d,0x65,0x73,0x00,0x00,0x00,0x00,0x84,0x00,0x03,0x00,
0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x24,0x34,0x04,0x00,0x00,0x51,0x04,0x00,
0x51,0x06,0x01,0x01,0x07,0x01,0x2d,0x05,0x00,0x02,0x52,0x04,0x51,0x05,0x02,0x52,
0x04,0x2d,0x03,0x01,0x01,0x07,0x04,0x2d,0x03,0x02,0x01,0x38,0x03,0x00,0x03,0x00,
0x00,0x00,0x00,0x00,0x00,0x04,0x25,0x30,0x32,0x64,0x00,0x00,0x00,0x23,0x20,0x48,
0x65,0x6c,0x6c,0x6f,0x20,0x57,0x6f,0x72,0x6c,0x64,0x21,0x20,0x66,0x72,0x6f,0x6d,
0x20,0x45,0x53,0x50,0x33,0x32,0x20,0x62,0x79,0x20,0x6d,0x72,0x75,0x62,0x79,0x2f,
0x63,0x00,0x00,0x03,0x00,0x07,0x73,0x70,0x72,0x69,0x6e,0x74,0x66,0x00,0x00,0x04,
0x70,0x75,0x74,0x73,0x00,0x00,0x05,0x73,0x6c,0x65,0x65,0x70,0x00,0x4c,0x56,0x41,
0x52,0x00,0x00,0x00,0x16,0x00,0x00,0x00,0x02,0x00,0x01,0x69,0x00,0x01,0x26,0x00,
0x00,0x00,0x01,0x45,0x4e,0x44,0x00,0x00,0x00,0x00,0x08,
};
mruby/c ã®ã³ãŒããçµã¿èŸŒãå ã®ã¡ã€ã³ããã°ã©ã (main/hello_world_main.c) ãäœæããïŒ ãã㯠C èšèªã§æžãïŒ main/hello_world_main.c ã以äžã®ããã«ä¿®æ£ããïŒ
#include "mrubyc.h" //mruby/c ã®ããããã¡ã€ã«ã®èªã¿èŸŒã¿
#include "master.h" //mruby/c åŽã®ã¡ã€ã³ããã°ã©ã (master.rb) ã®ãã€ãã³ãŒãã®èªã¿èŸŒã¿ (ãã€ãã³ãŒããããããã¡ã€ã«ãšããŠèªã¿èŸŒã)
#define MEMORY_SIZE (1024*40) //䜿çšããã¡ã¢ãªãµã€ãºã®æå®ïŒçŸåšã¯ 40 k ãã€ãïŒ
static uint8_t memory_pool[MEMORY_SIZE]; //æå®ããã¡ã¢ãªéãçšããŠã¡ã¢ãªçšã®å€æ°ãå®çŸ©ïŒ
//ã¡ã€ã³é¢æ°
void app_main(void) {
mrbc_init(memory_pool, MEMORY_SIZE); //ã¡ã¢ãªãµã€ãºãæå®ããŠåæå
//æå®ãããã€ãã³ãŒã "master" ãå®è¡ããããšã宣èš
// 第 1 åŒæ°ã¯ master.h ã§ãã€ãã³ãŒããæ ŒçŽããé
åã®ååã«åããã
// 第 2 åŒæ°ã¯ïŒåæå®è¡ç¶æ
ãæ瀺ããããã®æ¡åŒµçšïŒæ®éã«å®è¡ããå Žåã¯ãŒãã§è¯ãïŒ
mrbc_create_task( master, 0 );
//mruby/c ããã°ã©ã ã®å®è¡éå§
mrbc_run();
}
ã¡ã€ã³ããã°ã©ã ã®ã³ã³ãã€ã«ãšå®è¡ïŒESP-IDF ã®æµåã«åŸã£ãŠïŒ make ããã°è¯ãïŒ
$ make
$ make flash monitor
....(ç¥)....
98 Hello World! from ESP32 by mruby/c
99 Hello World! from ESP32 by mruby/c
Ruby åŽã®ã¡ã€ã³ããã°ã©ã ã§ã¯ïŒGreeter ã¯ã©ã¹ã® hello ã¡ãœãããåŒã¶ããã«ããŠãã. src/master.rb ã以äžã®ããã«ä¿®æ£ããïŒ
greeter = Greeter.new
100.times do |i|
greeter.hello
sleep 1
end
Ruby ã³ãŒãã mrbc ã§ã³ã³ãã€ã«ããïŒ
$ mrbc -B master -o main/master.h src/master.rb
mruby/c ã®ã¯ã©ã¹ãèªäœããå Žåã¯ïŒ [æºå] C èšèªã§ Ruby æ¡åŒµã©ã€ãã©ãªã®äœæ 㧠説æããã®ãšåæ§ã«ïŒ ããã C èšèªåŽã§å®çŸ©ãããïŒ mruby/c åŽã§å®çŸ©ãããã® 2 éãã®éžæè¢ãããïŒ ä»¥äžã§ã¯ïŒããããã«ã€ããŠäŸç€ºããïŒ
C åŽã®ã¡ã€ã³ããã°ã©ã (main/hello_world_main.c) ã以äžã®ããã«ä¿®æ£ããïŒ[æºå] C èšèªã§ Ruby æ¡åŒµã©ã€ãã©ãªã®äœæ ã§ã¯ ã¯ã©ã¹å®çŸ©ã« rb_define_classïŒã¡ãœããå®çŸ©ã« rb_define_method é¢æ°ãçšãããïŒ mruby/c ã§ã¯ mrbc_define_class ãš mrbc_define_method é¢æ°ãçšããïŒ
#include "mrubyc.h" //mruby/c ã®ããããã¡ã€ã«ã®èªã¿èŸŒã¿
#include "master.h" //mruby/c åŽã®ã¡ã€ã³ããã°ã©ã (master.rb) ã®ãã€ãã³ãŒãã®èªã¿èŸŒã¿ (ãã€ãã³ãŒããããããã¡ã€ã«ãšããŠèªã¿èŸŒã)
#define MEMORY_SIZE (1024*40) //䜿çšããã¡ã¢ãªãµã€ãºã®æå®ïŒçŸåšã¯ 40 k ãã€ãïŒ
static uint8_t memory_pool[MEMORY_SIZE]; //æå®ããã¡ã¢ãªéãçšããŠã¡ã¢ãªçšã®å€æ°ãå®çŸ©ïŒ
static struct RClass* mrbc_class_greeter; //C åŽã§ã¯ã©ã¹å®çŸ©ããããã«å¿
èŠãªæ§é äœãå®çŸ©
//ã¡ãœãããšããŠäœ¿ãé¢æ°ãå®çŸ©ïŒ
// åã¯åžžã« void. static ãä»ããïŒ
// åŒæ°ã¯åžžã« (mrb_vm* vm, mrb_value* v, int argc) ãšããŠããïŒå€æŽã®å¿
èŠã¯ãªãïŒ
static void
mrbc_hello(mrb_vm* vm, mrb_value* v, int argc){
printf("Hello world! by C\n");
}
//C åŽã®ã¯ã©ã¹ã®åæåé¢æ°
void mrbc_greeter_init(struct VM* vm){
//mrbc_define_class ã§ã¯ã©ã¹åãå®çŸ©
//第 1 åŒæ°ïŒåžžã« vm, 第 2 åŒæ°ïŒã¯ã©ã¹å, 第 3 åŒæ°ïŒäžäœã¯ã©ã¹ (åžžã« mrbc_class_object ã§è¯ã)
mrbc_class_greeter = mrbc_define_class(vm, "Greeter", mrbc_class_object);
//mrbc_define_method ã§ã¡ãœãããå®çŸ©
//第 1 åŒæ°ïŒåžžã« vm, 第 2 åŒæ°ïŒã¯ã©ã¹çšã®æ§é äœã®åå, 第 3 åŒæ°ïŒã¡ãœããå, 第 4 åŒæ°ïŒã¡ãœããã«å¯Ÿå¿ãã C ã®é¢æ°å
mrbc_define_method(vm, mrbc_class_greeter, "hello", mrbc_hello);
}
//ã¡ã€ã³é¢æ°
void app_main(void) {
mrbc_init(memory_pool, MEMORY_SIZE); //ã¡ã¢ãªãµã€ãºãæå®ããŠåæå
//C åŽã§å®çŸ©ããã¯ã©ã¹ãæå¹å
//åŒæ°ïŒãŒã (NULL ãã€ã³ã¿)
//C èšèªã§ã¯ã©ã¹ãé¢æ°ãå®çŸ©ããå Žåã«ã¯ïŒåæååŠçã«ãããŠãŸã ã¿ã¹ã¯ã®å®£èšãè¡ã£ãŠããªãç¶æ
ïŒ
//ããªãã¡ mrbc_create_task() ãåŒãã§ããªãããã« VM æ§é äœã確ä¿ãããŠããªãç¶æ
ïŒã§è¡ãããããšãå€ãïŒ
//ãã®å Žåãããã§ããïŒ ãããã£ãå Žåã«ã¯ãŒãïŒ=NULLãã€ã³ã¿ïŒã§ãèš±ããããªèšèªãã¶ã€ã³ã«ãªã£ãŠããïŒ
mrbc_greeter_init(0);
//æå®ãããã€ãã³ãŒã "master" ãå®è¡ããããšã宣èš
// 第 1 åŒæ°ã¯ master.h ã§ãã€ãã³ãŒããæ ŒçŽããé
åã®ååã«åããã
// 第 2 åŒæ°ã¯ïŒåæå®è¡ç¶æ
ãæ瀺ããããã®æ¡åŒµçšïŒæ®éã«å®è¡ããå Žåã¯ãŒãã§è¯ãïŒ
mrbc_create_task( master, 0 );
//mruby/c ããã°ã©ã ã®å®è¡éå§
mrbc_run();
}
ã¡ã€ã³ããã°ã©ã ã®ã³ã³ãã€ã«ãšå®è¡ïŒESP-IDF ã®æµåã§è¡ãã°è¯ãïŒ
$ make
$ make flash monitor
....(ç¥)....
Hello world! by C
Hello world! by C
ãã¡ã€ã«ã眮ãããã®ãã£ã¬ã¯ããªãäœæããŠããïŒ
$ mkdir -p mrblib
mrblib/greeter.rb ã以äžã®ããã«äœæããïŒ
class Greeter
def hello
puts "Hello World! by mruby/c"
end
end
ã¯ã©ã¹å®çŸ©ãã¡ã€ã«ã§ãã£ãŠãïŒ ä»¥äžã®å³ã«ããããã«ïŒmruby/c ã®ã³ãŒããäžéã³ãŒãã«ã³ã³ãã€ã«ããå¿ èŠãããïŒ
äžèšã® mruby/c ã³ãŒãã mrbc ã§ã³ã³ãã€ã«ããŠäžéã³ãŒã (ãã€ãã³ãŒã) ãçæããïŒ ãªã以äžã®äŸã§ã¯ïŒC åŽã®ã¡ã€ã³ããã°ã©ã ã§ã®èªã¿èŸŒã¿æ¹ãç°ãªãã®ã§ïŒ ã³ã³ãã€ã«çµæã®æ¡åŒµå㯠.c (main/mrblib.c) ãšããŠããïŒ
$ mrbc -B myclass_bytecode --remove-lv -o main/mrblib.c mrblib/greeter.rb
$ less main/mrblib.c
#include <stdint.h>
#ifdef __cplusplus
extern
#endif
const uint8_t myclass_bytecode[] = {
0x52,0x49,0x54,0x45,0x30,0x33,0x30,0x30,0x00,0x00,0x00,0xbc,0x4d,0x41,0x54,0x5a,
0x30,0x30,0x30,0x30,0x49,0x52,0x45,0x50,0x00,0x00,0x00,0xa0,0x30,0x33,0x30,0x30,
0x00,0x00,0x00,0x2b,0x00,0x01,0x00,0x03,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x0d,
0x11,0x01,0x11,0x02,0x5c,0x01,0x00,0x5e,0x01,0x00,0x38,0x01,0x69,0x00,0x00,0x00,
0x01,0x00,0x07,0x47,0x72,0x65,0x65,0x74,0x65,0x72,0x00,0x00,0x00,0x00,0x26,0x00,
0x01,0x00,0x03,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x0a,0x63,0x01,0x58,0x02,0x00,
0x5f,0x01,0x00,0x38,0x01,0x00,0x00,0x00,0x01,0x00,0x05,0x68,0x65,0x6c,0x6c,0x6f,
0x00,0x00,0x00,0x00,0x43,0x00,0x02,0x00,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x0d,0x34,0x00,0x00,0x00,0x51,0x03,0x00,0x2d,0x02,0x00,0x01,0x38,0x02,0x00,0x01,
0x00,0x00,0x17,0x48,0x65,0x6c,0x6c,0x6f,0x20,0x57,0x6f,0x72,0x6c,0x64,0x21,0x20,
0x62,0x79,0x20,0x6d,0x72,0x75,0x62,0x79,0x2f,0x63,0x00,0x00,0x01,0x00,0x04,0x70,
0x75,0x74,0x73,0x00,0x45,0x4e,0x44,0x00,0x00,0x00,0x00,0x08,
};
C èšèªåŽã®ã¡ã€ã³ããã°ã©ã (main/hello_world_main.c) ã®ä¿®æ£ãïŒmruby/c åŽã§äœæããã¯ã©ã¹ãèªã¿èŸŒãããã«ããïŒ
#include "mrubyc.h" //mruby/c ã®ããããã¡ã€ã«ã®èªã¿èŸŒã¿
#include "master.h" //mruby/c åŽã®ã¡ã€ã³ããã°ã©ã (master.rb) ã®ãã€ãã³ãŒãã®èªã¿èŸŒã¿ (ãã€ãã³ãŒããããããã¡ã€ã«ãšããŠèªã¿èŸŒã)
#define MEMORY_SIZE (1024*40) //䜿çšããã¡ã¢ãªãµã€ãºã®æå®ïŒçŸåšã¯ 40 k ãã€ãïŒ
static uint8_t memory_pool[MEMORY_SIZE]; //æå®ããã¡ã¢ãªéãçšããŠã¡ã¢ãªçšã®å€æ°ãå®çŸ©ïŒ
//ã¡ã€ã³é¢æ°
void app_main(void) {
mrbc_init(memory_pool, MEMORY_SIZE); //ã¡ã¢ãªãµã€ãºãæå®ããŠåæå
//mrblib.c ã§ã¯ãã€ãã³ãŒã㯠myclass_bytecode é
åã«æ ŒçŽãããŠãã
extern const uint8_t myclass_bytecode[];
//ã¯ã©ã¹çšã® mruby/c ã³ãŒããã³ã³ãã€ã«ããŠäœããã C ã®ãã¡ã€ã«ã®èªã¿èŸŒã¿
mrbc_run_mrblib(myclass_bytecode);
//æå®ãããã€ãã³ãŒã "master" ãå®è¡ããããšã宣èš
// 第 1 åŒæ°ã¯ master.h ã§ãã€ãã³ãŒããæ ŒçŽããé
åã®ååã«åããã
// 第 2 åŒæ°ã¯ïŒåæå®è¡ç¶æ
ãæ瀺ããããã®æ¡åŒµçšïŒæ®éã«å®è¡ããå Žåã¯ãŒãã§è¯ãïŒ
mrbc_create_task( master, 0 );
//mruby/c ããã°ã©ã ã®å®è¡éå§
mrbc_run();
}
ã¡ã€ã³ããã°ã©ã ã®ã³ã³ãã€ã«ãšå®è¡ïŒESP-IDF ã®æµåã§è¡ãã°è¯ãïŒ
$ make
$ make flash monitor
....(ç¥)....
Hello World! by mruby/c
Hello World! by mruby/c
以äžã§ã¯ïŒäžèšã®ããã¿ãŒã³ (2) mruby/c åŽã§ Greeter ã¯ã©ã¹ã®å®çŸ©ã ã§äœæããããã°ã©ã ãæ¡åŒµãïŒC åŽã§å®çŸ©ããã足ãç®çšé¢æ° c_add ã mruby/c åŽã®ã¯ã©ã¹ Calc ããå©çšããäŸãäœæããïŒ
mruby åŽã®ã¡ã€ã³ããã°ã©ã (src/master.rb) ãä¿®æ£ããŠïŒ 以äžã®ããã« Greeter ã¯ã©ã¹ã® hello ã¡ãœãããšïŒ Calc ã¯ã©ã¹ã® add ã¡ãœãããåŒã¶ããã«ããŠããïŒ
greeter = Greeter.new
greeter.hello
sleep 1
obj = Calc.new
sum = obj.add(1,2)
puts "1 + 2 = #{sum}"
ä¿®æ£ããã®ã§ïŒmrbc ã³ãã³ã㧠main/master.rb ãã³ã³ãã€ã«ãçŽãïŒ
$ mrbc -B master -o main/master.h src/master.rb
æ¢ã« Greeter ã¯ã©ã¹ã¯äœæããŠããã®ã§ïŒããã§ã¯ Calc ã¯ã©ã¹ãäœæããïŒ mrblib/calc.rb ã以äžã®ããã«äœæããïŒããã§ïŒmruby/c ã®ã¯ã©ã¹ãã C èšèªåŽã®é¢æ°ãåŒã¶ãããªåœ¢ã«ããŠããïŒ
class Calc
def add(a, b)
c_add(a, b) #Cã®é¢æ°ãåŒã¶
end
end
ã¯ã©ã¹å®çŸ©ã®ãã¡ã€ã«ãè¿œå ããã®ã§ïŒæ¹ããŠã³ã³ãã€ã«ãè¡ãïŒ ä»¥äžã®ããã« mrbc ã³ãã³ãã§åŒæ°ãšããŠäžãã ruby ãã¡ã€ã«ãè€æ°äžããã°è¯ãïŒ
$ mrbc -B myclass_bytecode --remove-lv -o main/mrblib.c mrblib/greeter.rb mrblib/calc.rb
C åŽã®ããã°ã©ã (main/hello_world_main.c) ãä¿®æ£ããïŒä»å㯠mruby/c åŽããåŒã³åºã C åŽã®é¢æ°ã 1 ã€ã®ãã¡ã€ã«ã«ãŸãšããïŒåœç¶ïŒå¥ã®ãã¡ã€ã«ã«åããããšãåºæ¥ãïŒ
#include "mrubyc.h" //mruby/c ã®ããããã¡ã€ã«ã®èªã¿èŸŒã¿
#include "master.h" //mruby/c åŽã®ã¡ã€ã³ããã°ã©ã (master.rb) ã®ãã€ãã³ãŒãã®èªã¿èŸŒã¿ (ãã€ãã³ãŒããããããã¡ã€ã«ãšããŠèªã¿èŸŒã)
#define MEMORY_SIZE (1024*40) //䜿çšããã¡ã¢ãªãµã€ãºã®æå®ïŒçŸåšã¯ 40 k ãã€ãïŒ
static uint8_t memory_pool[MEMORY_SIZE]; //æå®ããã¡ã¢ãªéãçšããŠã¡ã¢ãªçšã®å€æ°ãå®çŸ©ïŒ
// mruby/c ããåŒã¶é¢æ°ã®å®äœ
// åã¯åžžã« void. static ãä»ããïŒ
// åŒæ°ã¯åžžã« (mrb_vm* vm, mrb_value* v, int argc) ãšããŠããïŒå€æŽã®å¿
èŠã¯ãªãïŒ
// * GET_INT_ARG : int åãžå€æ, GET_STRING_ARG : char åãžå€æ
// * SET_INT_RETURN : int åãæ»ã, SET_FLOAT_RETURN : float åãæ»ã, SET_NIL_RETURN : nil ãæ»ã,
// SET_TRUE_RETURN : true ãæ»ã, SET_FALSE_RETURN : false ãæ»ã, SET_BOOL_RETURN : bool åãæ»ã
static void c_add(mrb_vm *vm, mrb_value *v, int argc) {
int a = GET_INT_ARG(1);
int b = GET_INT_ARG(2);
int sum = a + b;
SET_INT_RETURN(sum);
}
//ã¡ã€ã³é¢æ°
void app_main(void) {
mrbc_init(memory_pool, MEMORY_SIZE); //ã¡ã¢ãªãµã€ãºãæå®ããŠåæå
//mrblib.c ã§ã¯ãã€ãã³ãŒã㯠myclass_bytecode é
åã«æ ŒçŽãããŠãã
extern const uint8_t myclass_bytecode[];
//ã¯ã©ã¹çšã® mruby/c ã³ãŒããã³ã³ãã€ã«ããŠäœããã C ã®ãã¡ã€ã«ã®èªã¿èŸŒã¿
mrbc_run_mrblib(myclass_bytecode);
// mrbc_define_method 㧠C ã®é¢æ°ã mruby/c åŽããåŒã¹ãããã«ããïŒ
// * 第 1 åŒæ°ïŒvm ã§ãªããŒã (NULL ãã€ã³ã¿)
// * 第 2 åŒæ°ïŒå¯Ÿè±¡ã®ã¯ã©ã¹ (ããã§ã¯äžäœã¯ã©ã¹ã§ãã mrbc_class_object ãæå®)
// * 第 3 åŒæ°ïŒã¡ãœããå
// * 第 4 åŒæ°ïŒã¡ãœããã«å¯Ÿå¿ãã C ã®é¢æ°å
mrbc_define_method(0, mrbc_class_object, "c_add", c_add);
//æå®ãããã€ãã³ãŒã "master" ãå®è¡ããããšã宣èš
// 第 1 åŒæ°ã¯ master.h ã§ãã€ãã³ãŒããæ ŒçŽããé
åã®ååã«åããã
// 第 2 åŒæ°ã¯ïŒåæå®è¡ç¶æ
ãæ瀺ããããã®æ¡åŒµçšïŒæ®éã«å®è¡ããå Žåã¯ãŒãã§è¯ãïŒ
mrbc_create_task( master, 0 );
//mruby/c ããã°ã©ã ã®å®è¡éå§
mrbc_run();
}
ã¡ã€ã³ããã°ã©ã ã®ã³ã³ãã€ã«ãšå®è¡ïŒESP-IDF ã®æµåã«åŸã£ãŠïŒ make ããã°è¯ãïŒ
$ make
$ make flash monitor
Hello World! by mruby/c
1 + 2 = 3
äžèšã§ã¯ mrbc ã³ãã³ããæåã§å®è¡ããŠãããïŒMake ã®ã«ãŒã«ãäœæããŠãããšã³ãã³ãäžçºã§èªåå®è¡ãããã®ã§ç°¡åã§ããïŒ äŸãã° main/component.mk ã æ¬ãªããžããªã«å«ãŸãã main/component.mk ã®ããã«èšå®ããŠããã°ããïŒ