mieki256's diary



2018/03/16(金) [n年前の日記]

#1 [ruby][mruby] Cで書いたプログラムからmrubyを呼び出せるか実験

SDLを使ったCのプログラムに、mrubyを組み込んで使う事例を、DXRuby作者様が昔公開してくれていたので、それのSDL2版を書いて試そうとしていたのだけど。

_SDL_imageとmrubyを使ってみた - mirichiの日記

そもそも、ビルドの仕方が分からない…。ので、まずはシンプルな形でビルドの仕方を確認しようと。以下の記事を参考にしつつ作業。

_手探りでおぼえるmruby その1:クラスを定義する、メソッドを定義する - エンジニアのソフトウェア的愛情
_mrubyで書いたコードをC言語内で読み出す方法 - Bye Bye Moore
_Hello World - mruby/mruby Wiki

環境は、Windows10 x64 + MSYS2。

ディレクトリ構成。 :

以下のような構成にしてみたり。
~/prg
|
+---- mruby
      |
      +---- callmruby
      |
      +---- mruby

~/prg/mruby/mruby/ の中に、 _mruby 1.4.0 のファイル一式を置いた。

MSYS2 のシェルを起動。スタートメニュー内の、MSYS2 MinGW 32-bit (32bit) を実行。

カレントディレクトリを変更して、makeを実行してビルド。
cd ~/prg/mruby/mruby/
make

ビルドが成功すると、以下のような状態になる。
  • ~/prg/mruby/mruby/include/ 内に *.h ファイルが入ってる。(mrubyをDL・解凍した時点で既に入ってる)
  • ~/prg/mruby/mruby/build/host/lib/ 内に、libmruby.a ファイルが出来上がる。この .a ファイルを、Cで書いたプログラムのビルド時にリンクする。

mruby はビルドできたので、callmruby/ の中で、CソースやMakefileを用意して、mruby を組み込めそうか実験していく。

mrubyを呼び出すだけのCプログラムを書いてみる。 :

callmruby/ の中に、callmruby.c というファイル名でCソースを用意。

_callmruby.c
#include "mruby.h"
#include "mruby/compile.h"
#include "mruby/proc.h"
#include <stdio.h>

int main(int argc, char *argv[])
{
  // open mruby state
  mrb_state *mrb = mrb_open();
  if (mrb == 0)
  {
    printf("cannot open mruby state.\n");
    return -2;
  }

  // file open
  FILE *fp = fopen("main.rb", "r");

  // run mruby script
  mrb_load_file(mrb, fp);

  // file close
  fclose(fp);

  // close mruby state
  mrb_close(mrb);
  return 0;
}

上記ソースは、main.rb を読み込んで実行するので、main.rb も用意する。

_main.rb
puts "Hello, I am mruby."
puts "Ok. mruby, your number is 7. instrument recorder on."
puts "Permission to sortie."
puts "Permission granted. GOOD LUCK, mruby."

Makefile も作る。Makefile てのは、make を実行した際にどんな処理をするのか、ルールを記述するファイル。

_Makefile
TARGETS = callmruby

all: $(TARGETS)

SDL_PREFIX  = /mingw32
# SDL_PREFIX  = /mingw

MRB_HEAD    = ../mruby/include
MRB_LIBS    = ../mruby/build/host/lib

# CG_LIBS     = 

CROSS_COMPILE = $(SDL_PREFIX)/bin/
CC = $(CROSS_COMPILE)gcc
CXX = $(CROSS_COMPILE)g++

CFLAGS = -g -Wall -I$(MRB_HEAD)
CXXFLAGS = -g -Wall -I$(MRB_HEAD)

LIBS = -L$(MRB_LIBS) -lmruby -lpthread -lm
LDFLAGS = -Wl,-rpath -static -static-libgcc -static-libstdc++

clean:
	rm -f *.o *.a *~ $(TARGETS)

$(TARGETS): $(TARGETS).o
	$(CXX) -o $@ $^ $(LIBS) $(LDFLAGS)

  • mruby の includeフォルダ、libフォルダは、相対パスで指定してる。
  • LIBS に、-L$(MRB_LIBS) -lmruby を記述して、mruby をリンクするように指定してる。
  • MSYS2 でビルドしたプログラムは libwinpthread-1.dll を要求するので、-lpthread と -static を記述して、スタティックリンクをするように指定してる。

ビルドする。
$ cd ~/prg/mruby/callmruby/
$ make
/mingw32/bin/gcc -g -Wall -I../mruby/include   -c -o callmruby.o callmruby.c
/mingw32/bin/g++ -o callmruby callmruby.o -L../mruby/build/host/lib -lmruby -lpthread -Wl,-rpath -static -static-libgcc -static-libstdc++

もし、上手く行かなかったら、以下を実行することで、作業ファイル・出力ファイルを全部消すことができる。
make clean

出来上がった .exe を実行してみる。
$ ./callmruby.exe
Hello, I am mruby.
Ok. mruby, your number is 7. instrument recorder on.
Permission to sortie.
Permission granted. GOOD LUCK, mruby.
Cで書いたプログラムを実行したはずなのに、main.rb に書かれた処理が実行されて、メッセージが出力された。

これで、mruby をCプログラムの中に組み込んでビルドすることはできた。ここまでは、なんとかなった…。

少し説明。 :

Cプログラムから mruby を使うときは、
#include "mruby.h"
#include "mruby/compile.h"
#include "mruby/proc.h"
を書いて…。

  mrb_state *mrb = mrb_open();
で、mrubyの何かを開く、のかな。mrb_state ってなんだか分からんけど、コレを使って mruby のスクリプトを動かすのだろう…。

_mrb_state 解説(必ずしも徹底ではない) - Qiita

mrubyスクリプトが書かれたファイルを読み込んで実行するだけなら、以下を使うのだろう。
  FILE *fp = fopen("main.rb", "r");
  mrb_load_file(mrb, fp);
  fclose(fp);
fopen()、fclose() はCのソレで、ファイルを開いたり閉じたりする。mrb_load_file() で、開いたファイルを mruby に渡して、実行。なのかな。

Cにおいて、開いた何かしらは、えてして閉じないといけない。mruby も開いたのだから、閉じる。
  mrb_close(mrb);

#2 [nitijyou] 某所から連絡

朝方、某所から連絡。昨日のトラブルは、NTT側で、基板が故障していたらしい…。そんなこともあるのか…。何にせよ問題が解決したようで一安心。詳細はGRPでメモ。

以上、1 日分です。

過去ログ表示

Prev - 2018/03 -
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31

カテゴリで表示

検索機能は Namazu for hns で提供されています。(詳細指定/ヘルプ


注意: 現在使用の日記自動生成システムは Version 2.19.6 です。
公開されている日記自動生成システムは Version 2.19.5 です。

Powered by hns-2.19.6, HyperNikkiSystem Project