mruby を c# に 組み込んでみる
TRANSCRIPT
自己紹介
名前 : 秋山 亮介
お仕事 : 業界向けパッケージソフトウェアを作ってる会社で
設計したりコード書いたり
好きな言語 : Ruby、Golang、C#
Kawasaki.rb : 初めて参加して1年半くらい経ちました
Twitter, GitHub : @kechako
C# とは
● マイクロソフトが開発したプログラミング言語
● 共通中間言語(CIL)にコンパイルされ、共通言語ランタイム(CLR)上で実行される
● この辺の仕様が共通言語基盤(CLI)
● CLR は JIT コンパイラによってネイティブコードに変換しつつプログラムを実行する
● 実装としては .NET Framework、Mono、.NET Core
● 開発環境は Microsoft Visual Studio など
● 現在、C# のバージョンは 6.0
● C# の名前の由来は「C++++」らしい
C# のバージョン
● C# 1.0 (2002年)
● C# 1.1 (2003年)
● C# 2.0 (2005年)○ ジェネリック、イテレーター、匿名メソッド、 Nullable...
● C# 3.0 (2007年)○ LINQ、ラムダ式、暗黙的片付け、拡張メソッド ...
● C# 4.0 (2010年)○ dynamic、オプション引数、名前付き引数、( Task)...
● C# 5.0 (2012年)○ 非同期メソッド(async、await)...
● C# 6.0 (2015年)○ オープンソース化、null 条件演算子、nameof 演算子、その他いろいろたくさん機能追加 ...
C# で Hello, Worldusing System;
namespace Hello{ class Program { static void Main(string[] args) { Console. WriteLine("Hello, World!"); } }}
C# で Duck Typingusing System;
namespace DuckTyping{ class Ruby { public void Hello() { Console.WriteLine("Hello, Ruby!"); } }
class CSharp { public void Hello() { Console.WriteLine("Hello, CSharp!"); } }
C# で Duck Typing class Program { static void Hello(dynamic lang) { lang.Hello(); }
static void Main(string[] args) { Hello(new Ruby()); Hello(new CSharp()); } }}
// => Hello, Ruby!// => Hello, CSharp!
.NET Core● 2016/06/27 .NET Core 1.0 リリース!
● オープンソース、マルチプラットフォームの .NET Framework 実装
● Windows のほか、Linux、OS X でも動作
● Web フレームワークとして、ASP.NET Core
mruby とは
● mruby は ISO 規格の一部にしがった Ruby の軽量な実装
● 必要最小限のクラス、メソッドしか定義されていない
○ mrbgem として拡張可能
○ mruby に組み込まれる
● 組み込み機器や、アプリケーションへの埋め込みを想定している
● 組み込み機器を想定しているだけあって、使用メモリが少ない
● mruby は、Ruby のコードをバイトコードに変換し、mrubyVM 上で逐次実行
● C言語で書かれている
mruby で Hello World#include "mruby.h"#include "mruby/compile.h"
int main(void){ mrb_state *mrb = mrb_open(); mrb_load_string(mrb, "puts 'Hello, World!'"); mrb_close(mrb);}
mruby に機能追加するために
● モジュール定義○ mrb_define_module
● モジュール関数を定義○ mrb_define_module_function
● クラスを定義○ mrb_define_class、mrb_define_class_under
● インスタンスメソッドを定義○ mrb_define_method
● クラスメソッドを定義○ mrb_define_class_method
そもそもなんでそんなこととやろうと思ったのか
● これまでの人生で一番コードを書いたのは C#
● その C# と Ruby を絡めてみたかった
○ IronRuby なんてものもありましたが
○ 最終リリースが2011年
● 実行時に Ruby で簡単な制御を入れたり、コンフィグを Ruby で書いたり
かっとなってやった
C++/CLI とは
● CLI 上で動作するプログラムを作るために C++ を拡張した言語
● C++ の上位互換
● ビルドされたライブラリは、C# からそのまま参照可能
● C のヘッダーファイルを include して、普通に使える
● 当然、スタティックリンクライブラリをリンクできる
● .NET の参照型はハンドルで保持する○ List<String^>^ list = gcnew List<String^>();
● マネージドとアンマネージドの2つの世界を繋ぐためにいろいろとおまじないが必要
● 現状、Windows でしか使えないようです
実際にやったこと(CSharp モジュール)
● C# のクラスを、Ruby のコードから呼び出せるようにするためのあれこれ
● アセンブリ(DLL)のロード○ あるDLLに実装されているクラスなどを使うには、アセンブリをロードする必要がある
○ アセンブリ厳密名またはDLLのフルパスを指定してアセンブリをロードする
● C# のクラスを Ruby のクラスとして mruby に定義する○ クラスのフルネーム(Namespace + クラス名)から、クラスの型情報を取得
○ 型情報からメソッドやプロパティなどの情報を取得できる
○ 型情報からクラスのインスタンスを生成できる
○ メソッドやプロパティーの情報と生成されたインスタンスを組み合わせてメソッドをコールできる
○ これらを C++/CLI で mruby に登録する
● mruby で(mruby が埋め込まれた .NET アプリケーション)で Ruby のコードを実
行
まとめ
● C++/CLI を絡めれば、mruby 以外も C# と C言語の世界をつなげられる
● mruby から C# のクラスにアクセスする部分がリフレクションで実現しているので、
パフォーマンスは期待しないほうが良さそう
● Ruby と C# の型の相互変換が悩ましい
● ほんとはデモ見せたかったんです……○ いつか Kawasaki.rb で……
● 今回一番苦労したのは C# でも mruby でもなく C++/CLI。
● C 言語が多少読めてかければ、mruby はそれなりに動かせる
○ あくまでもそれなりにです
Windows 以外でどうするか
● .NET Core には残念ながら C++/CLI がないっぽいです
● C の共有ライブラリーであれば、.NET Core からもコールできるっぽい
○ ごめんなさい、試してません。
● mruby であれば、共有ライブラリーとしてビルドして、各関数を呼び出す的な
● 構造体の定義を C# 側でやるとか、つらい未来しか待っていない予感