質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

1回答

996閲覧

Ruby(mruby)とvector等のC++のSTLを連携させるには?

KureteRubyLua

総合スコア206

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2017/08/16 13:27

編集2017/08/19 03:38

Ruby(mruby)とC++を連携させようと考えています。

int等、C++のプリミティブ型や関数、クラスを連携させるのは
mrubybindという外部のソースコードを
借りる形で出来たのですが、std::vector等のstlの連携がmrubybindを改造しても
上手く出来ません。

例えば以下のソースコードを実現できません。

Ruby

1#A_DataはCと連携させたクラス 2data=A_Data.new() 3#b_arrayはA_Dataの中にあるstd::vector<int>型の変数 4#b_arrayに添字を添え、中身を表示する事はできる 5print data.b_array[0] 6#data.b_array[0]にbufを代入しているが、何故か代入できない 7buf=99; 8data.b_array[0]=buf;

mrubyのバインドは通常のRubyとcの連携に似ている事は分かったので
おそらく通常のRubyとCの連携においてSTLをバインドする
方法がわかれば、そのままmrubyでも転用できると考えているのですが
全くやり方が分かりません。

上記のソースコードが実現できるようにRubyとSTLをバインドするには
どうすれば良いのでしょうか?mrubyにおいてmrubybindを使わずに
連携させる方法については下記に書かれています

http://qiita.com/cubicdaiya/items/fc0620c7b9629bb85d6f

もし足りない部分があれば質問をお願いします。よろしくお願いします。

追記

ソースコードをaxfcにアップしました。
https://www.axfc.net/u/3835671

改造した部分のみを書くと、こうなります。

C++

1 2 //改造ここから 3 4 //独自クラスでも扱えるように改造 5 template<typename T> 6 struct Type { 7 static T(*SetFunc)(mrb_state* mrb, mrb_value v); 8 static mrb_value(*RetFunc)(mrb_state* mrb, T& p); 9 static const char* TYPE_NAME; 10 static int check(mrb_state* mrb, mrb_value v) { return mrb_class_ptr(v) != nullptr; } 11 static T get(mrb_state* mrb, mrb_value v) 12 { 13 return SetFunc(mrb, v); 14 } 15 16 static mrb_value ret(mrb_state* mrb, T& p) 17 { 18 return RetFunc(mrb, p); 19 } 20 }; 21 22 template<typename T> 23 T(*Type<T>::SetFunc)(mrb_state* mrb, mrb_value v); 24 25 template<typename T> 26 mrb_value(*Type<T>::RetFunc)(mrb_state* mrb, T& p); 27 28 template<typename T> 29 const char* Type<T>::TYPE_NAME; 30 31 32 //Vectorを扱えるように改造 33 template<typename T> 34 struct Type<std::vector<T>> { 35 static const char* TYPE_NAME; 36 static int check(mrb_state* mrb, mrb_value v) { return mrb_array_p(v); } 37 static std::vector<T> get(mrb_state* mrb, mrb_value v) 38 { 39 std::vector<T> indexes; 40 int len_i = RARRAY_LEN(v); 41 indexes.resize(len_i); 42 for (int i = 0; i < len_i; ++i) 43 { 44 indexes.push_back(static_cast<T>(Type<T>::get(mrb, v))); 45 } 46 return indexes; 47 } 48 static mrb_value ret(mrb_state* mrb, std::vector<T> p) 49 { 50 mrb_value foo = mrb_ary_new(mrb); 51 for (int i = 0; i < p.size(); ++i) 52 { 53 mrb_ary_push(mrb, foo, Type<T>::ret(mrb, p[i])); 54 } 55 return foo; 56 } 57 }; 58 template<typename T> 59 const char* Type<std::vector<T>>::TYPE_NAME = "Array"; 60 //Vector 61 template<typename T> 62 struct Type<std::vector<T>&> { 63 static const char* TYPE_NAME; 64 static int check(mrb_state* mrb, mrb_value v) { return mrb_array_p(v); } 65 static std::vector<T> get(mrb_state* mrb, mrb_value v) 66 { 67 std::vector<T> indexes; 68 int len_i = RARRAY_LEN(v); 69 indexes.resize(len_i); 70 for (int i = 0; i < len_i; ++i) 71 { 72 indexes.push_back(static_cast<T>(Type<T>::get(mrb, v))); 73 } 74 return indexes; 75 } 76 static mrb_value ret(mrb_state* mrb, std::vector<T> p) 77 { 78 mrb_value foo = mrb_ary_new(mrb); 79 for (int i = 0; i < p.size(); ++i) 80 { 81 mrb_ary_push(mrb, foo, Type<T>::ret(mrb, p[i])); 82 } 83 //return mrb_ary_value(&p); 84 return foo; 85 } 86 }; 87 template<typename T> 88 const char* Type<std::vector<T>&>::TYPE_NAME = "Array"; 89 90 //改造ここまで 91 92//中略 93 94 95 //改造ここから 96 template <class T> 97 void bind_set_func(T(*SetFunc)(mrb_state* mrb, mrb_value v)) { 98 Type<T>::SetFunc = SetFunc; 99 } 100 template <class T> 101 void bind_ret_func(mrb_value(*RetFunc)(mrb_state* mrb, T& p)) { 102 Type<T>::RetFunc = RetFunc; 103 } 104コード

問題点はRubyの部分に書いたとおりで、C++で作ったクラスを用いて
作った変数の中にあるVectorの配列の一要素を代入できないという事です。
もし、他に問題点や聞きたい事があれば指摘をお願いします。

二回目の追記

想定通りに動かないRubyのソースを書きました。このソースを通すと「0,99」と表示されるはずが「0,0」と表示されてしまいます。

Ruby

1 2#A_DataはCと連携させたクラス 3data=A_Data.new() 4#b_arrayはA_Dataの中にあるstd::vector<int>型の変数 5#b_arrayに添字を添え、中身を表示する事はできる 6p data.b_array[0] 7#data.b_array[0]にbufを代入しているが、何故か代入できない 8buf=99; 9data.b_array[0]=buf; 10p data.b_array[0]

上のRubyのA_DataはC++で作成した独自クラスをRubyにバインドした物です。
下のような形でバインドせずに通すとエラーが起きるのでご注意下さい。

C++

1 2#include <vector> 3#include "mrubybind.h" 4 5class AData 6{ 7 protected: 8 std::vector<int> b_array; 9 public: 10 AData() 11 { 12 b_array.resize(1); 13 b_array[0] = 0; 14 }; 15 std::vector<int>& GetBArray() 16 { 17 return b_array; 18 } 19 void SetBArray(std::vector<int> set) 20 { 21 b_array=set; 22 } 23 virtual ~AData(){}; 24}; 25 26 27AData* newAData() 28{ 29 return new AData(); 30} 31 32void installADataClass(mrb_state* mrb) 33{ 34 mrubybind::MrubyBind b(mrb); 35 mrubybind::Type<AData>::TYPE_NAME = "A_Data"; 36 b.bind_class("A_Data", newAData); 37 b.bind_instance_method("A_Data", "b_array", &AData::GetBArray); 38 b.bind_instance_method("A_Data", "b_array=", &AData::SetBArray); 39} 40 41int main(int argc, char *argv[]) 42{ 43 // ファイルを開く 44 const char* fn = "hoge.rb"; 45 std::shared_ptr< FILE > file(fopen(fn, "r"), [](FILE* f) { if (f != nullptr) { fclose(f); } }); 46 47 // エラー処理は程々に 48 if (file == nullptr) { 49 std::cout << "Load " << fn << " failed." << std::endl; 50 return 1; 51 } 52 // 仮想マシンを初期化して 53 std::shared_ptr< mrb_state > mrb(mrb_open(), [](mrb_state* p) { if (p != nullptr) { mrb_close(p); } }); 54 // 一時オブジェクトがつくられるのでGC arenaを保存 55 int ai = mrb_gc_arena_save(mrb.get()); 56 mrbc_context *context = mrbc_context_new(mrb.get()); 57 installADataClass(mrb.get()); 58 59 // 実行する ("Hello, World!" が出る) 60 mrb_load_file(mrb.get(), file.get()); 61 if (mrb->exc) { 62 mrb_value exc = mrb_obj_value(mrb->exc); 63 64 // エラー内容を取得 65 mrb_value backtrace = mrb_get_backtrace(mrb.get()); 66 puts(mrb_str_to_cstr(mrb.get(), mrb_inspect(mrb.get(), backtrace))); 67 68 // バックトレースを取得 69 mrb_value inspect = mrb_inspect(mrb.get(), exc); 70 puts(mrb_str_to_cstr(mrb.get(), inspect)); 71 72 // 例外をクリア 73 mrb->exc = 0; 74 } 75 76 mrb_gc_arena_restore(mrb.get(), ai); 77 78 mrbc_context_free(mrb.get(), context); 79 return 0; 80}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mattn

2017/08/16 16:11

どう改造してどう駄目だったか書かないと回答できません。
KureteRubyLua

2017/08/17 22:27

大変申し訳ありません。ソースコードの改造部分を追加しました
guest

回答1

0

うまく動いている様です。

diff

1diff --git a/codegen/mrubybind_types.1.h b/codegen/mrubybind_types.1.h 2index d5abd95..276bee1 100644 3--- a/codegen/mrubybind_types.1.h 4+++ b/codegen/mrubybind_types.1.h 5@@ -110,6 +110,25 @@ struct Type<void*> { 6 static mrb_value ret(mrb_state* mrb, void* p) { return mrb_cptr_value(mrb, p); } 7 }; 8 9+template<typename T> 10+struct Type { 11+ static T(*SetFunc)(mrb_state* mrb, mrb_value v); 12+ static mrb_value(*RetFunc)(mrb_state* mrb, T& p); 13+ static const char* TYPE_NAME; 14+ static int check(mrb_state* mrb, mrb_value v) { return mrb_class_ptr(v) != nullptr; } 15+ static T get(mrb_state* mrb, mrb_value v) { return SetFunc(mrb, v); } 16+ static mrb_value ret(mrb_state* mrb, T& p) { return RetFunc(mrb, p); } 17+}; 18+ 19+template<typename T> 20+T(*Type<T>::SetFunc)(mrb_state* mrb, mrb_value v); 21+ 22+template<typename T> 23+mrb_value(*Type<T>::RetFunc)(mrb_state* mrb, T& p); 24+ 25+template<typename T> 26+const char* Type<T>::TYPE_NAME; 27+ 28 //=========================================================================== 29 // Binder 30 31diff --git a/mrubybind.h b/mrubybind.h 32index 5029f5b..0913400 100644 33--- a/mrubybind.h 34+++ b/mrubybind.h 35@@ -30,12 +30,14 @@ 36 #include "mruby/class.h" 37 #include "mruby/data.h" 38 #include "mruby/proc.h" 39+#include "mruby/array.h" 40 #include "mruby/variable.h" 41 //#include "mrubybind_types.h" 42 // Describe type conversion between C type value and mruby value. 43 44 #include "mruby/string.h" 45 #include <string> 46+#include <vector> 47 48 namespace mrubybind { 49 50@@ -45,17 +47,12 @@ namespace mrubybind { 51 // Base template class. 52 template <class T> 53 struct Type { 54- // Type name used for error message. 55- // static const char TYPE_NAME[]; 56- 57- // Returns whether the given mrb_value can be converted into type T. 58- //static int check(mrb_value v) = 0; 59- 60- // Converts mrb_value to type T value. 61- //static T get(mrb_value v) = 0; 62- 63- // Converts type T value to mrb_value. 64- //static mrb_value ret(mrb_state*, T i) = 0; 65+ static T(*SetFunc)(mrb_state* mrb, mrb_value v); 66+ static mrb_value(*RetFunc)(mrb_state* mrb, T& p); 67+ static const char* TYPE_NAME; 68+ static int check(mrb_state* mrb, mrb_value v) { return mrb_class_ptr(v) != nullptr; } 69+ static T get(mrb_state* mrb, mrb_value v) { return SetFunc(mrb, v); } 70+ static mrb_value ret(mrb_state* mrb, T& p) { return RetFunc(mrb, p); } 71 }; 72 73 // Fixnum 74@@ -144,6 +141,15 @@ struct Type<void*> { 75 static mrb_value ret(mrb_state* mrb, void* p) { return mrb_cptr_value(mrb, p); } 76 }; 77 78+template<typename T> 79+T(*Type<T>::SetFunc)(mrb_state* mrb, mrb_value v); 80+ 81+template<typename T> 82+mrb_value(*Type<T>::RetFunc)(mrb_state* mrb, T& p); 83+ 84+template<typename T> 85+const char* Type<T>::TYPE_NAME; 86+ 87 //=========================================================================== 88 // Binder 89 90@@ -1233,6 +1239,68 @@ private: 91 int arena_index_; 92 }; 93 94+ 95+ template<typename T> 96+ struct Type<std::vector<T>> { 97+ static const char* TYPE_NAME; 98+ static int check(mrb_state* mrb, mrb_value v) { return mrb_array_p(v); } 99+ static std::vector<T> get(mrb_state* mrb, mrb_value v) 100+ { 101+ std::vector<T> indexes; 102+ int len_i = RARRAY_LEN(v); 103+ indexes.resize(len_i); 104+ for (int i = 0; i < len_i; ++i) 105+ { 106+ indexes.push_back(static_cast<T>(Type<T>::get(mrb, v))); 107+ } 108+ return indexes; 109+ } 110+ static mrb_value ret(mrb_state* mrb, std::vector<T> p) 111+ { 112+ mrb_value foo = mrb_ary_new(mrb); 113+ for (int i = 0; i < p.size(); ++i) 114+ { 115+ mrb_ary_push(mrb, foo, Type<T>::ret(mrb, p[i])); 116+ } 117+ return foo; 118+ } 119+ }; 120+ template<typename T> 121+ const char* Type<std::vector<T>>::TYPE_NAME = "Array"; 122+ //Vector 123+ template<typename T> 124+ struct Type<std::vector<T>&> { 125+ static const char* TYPE_NAME; 126+ static int check(mrb_state* mrb, mrb_value v) { return mrb_array_p(v); } 127+ static std::vector<T> get(mrb_state* mrb, mrb_value v) 128+ { 129+ std::vector<T> indexes; 130+ int len_i = RARRAY_LEN(v); 131+ indexes.resize(len_i); 132+ for (int i = 0; i < len_i; ++i) 133+ { 134+ indexes.push_back(static_cast<T>(Type<T>::get(mrb, v))); 135+ } 136+ return indexes; 137+ } 138+ static mrb_value ret(mrb_state* mrb, std::vector<T> p) 139+ { 140+ mrb_value foo = mrb_ary_new(mrb); 141+ for (int i = 0; i < p.size(); ++i) 142+ { 143+ mrb_ary_push(mrb, foo, Type<T>::ret(mrb, p[i])); 144+ } 145+ //return mrb_ary_value(&p); 146+ return foo; 147+ } 148+ }; 149+ template<typename T> 150+ const char* Type<std::vector<T>&>::TYPE_NAME = "Array"; 151+ 152+ template <class T> 153+ void bind_set_func(T(*SetFunc)(mrb_state* mrb, mrb_value v)) { Type<T>::SetFunc = SetFunc; } 154+ template <class T> 155+ void bind_ret_func(mrb_value(*RetFunc)(mrb_state* mrb, T& p)) { Type<T>::RetFunc = RetFunc; } 156 } // namespace mrubybind 157 158 #endif 159diff --git a/test/Makefile b/test/Makefile 160index 472a399..cbe5454 100644 161--- a/test/Makefile 162+++ b/test/Makefile 163@@ -36,6 +36,9 @@ float: float.o $(MRUBYBIND_OBJ) 164 string: string.o $(MRUBYBIND_OBJ) 165 g++ -o $@ $^ $(LIB) 166 167+vector: vector.o $(MRUBYBIND_OBJ) 168+ g++ -o $@ $^ $(LIB) 169+ 170 cptr: cptr.o $(MRUBYBIND_OBJ) 171 g++ -o $@ $^ $(LIB) 172

テストコードは以下。

c

1#include <mruby.h> 2#include <mruby/compile.h> 3#include "mrubybind.h" 4#include <stdlib.h> 5 6#include <string> 7using namespace std; 8 9string emphasize(const char* str) { 10 return "* " + string(str) + " *"; 11} 12 13int main() { 14 mrb_state* mrb = mrb_open(); 15 16 { 17 mrubybind::MrubyBind b(mrb); 18 b.bind("emphasize", emphasize); 19 } 20 if (mrb->gc.arena_idx != 0) { 21 fprintf(stderr, "Arena increased!\n"); 22 return EXIT_FAILURE; 23 } 24 25 mrb_load_string(mrb, 26 "data=Array.new();" 27 "data[0] = 1;" 28 "data[1] = 2;" 29 "puts data[0] + data[1]"); 30 if (mrb->exc) { 31 mrb_p(mrb, mrb_obj_value(mrb->exc)); 32 return EXIT_FAILURE; 33 } 34 35 mrb_close(mrb); 36 return EXIT_SUCCESS; 37}

投稿2017/08/18 06:09

mattn

総合スコア5030

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

KureteRubyLua

2017/08/18 13:10

アップしたhoge.rbのコードを動かしてみて下さい。本来0,99と表示されるところが0,0と表示されてしまいます
mattn

2017/08/18 13:53

んー。ダウンロードできませんでした。質問文に貼って貰えますか?
KureteRubyLua

2017/08/19 03:39

貼りました。何度も申し訳ありません
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問