MobiRuby/mruby-cocoaを読む
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
単語検索
|
最終更新
|
ヘルプ
]
開始行:
#contents
*はじめに [#ffe5d193]
[[mruby-cfuncを読んだ>MobiRuby/mruby-cfuncを読む]]ので次...
*test/main.m [#p04ea175]
mruby-cfuncと同様にtest/main.mからスタートします。
#code(C){{
struct mrb_state_ud {
struct cfunc_state cfunc_state;
struct cocoa_state cocoa_state;
};
int main(int argc, char *argv[])
{
mrb_state *mrb = mrb_open();
mrb->ud = malloc(sizeof(struct mrb_state_ud));
cfunc_state_offset = cfunc_offsetof(struct mrb_state_...
init_cfunc_module(mrb);
cocoa_state_offset = cocoa_offsetof(struct mrb_state_...
init_cocoa_module(mrb);
load_cocoa_bridgesupport(mrb, struct_table, const_tab...
init_unittest(mrb);
if (mrb->exc) {
mrb_p(mrb, mrb_obj_value(mrb->exc));
}
init_cocoa_test(mrb);
if (mrb->exc) {
mrb_p(mrb, mrb_obj_value(mrb->exc));
}
}
}}
mruby-cocoaはmruby-cfuncを使っているため、udにmruby-cfunc...
*init_cocoa_module(src/init_cocoa.m) [#je08c216]
#code(C){{
void init_cocoa_module(mrb_state *mrb)
{
if(cocoa_vm_count >= MAX_COCOA_MRB_STATE_COUNT - 1) {
puts("Too much open vm"); // TODO
}
if(cocoa_mrb_states==NULL) {
cocoa_mrb_states = malloc(sizeof(mrb_state *) * M...
for(int i = 0; i < MAX_COCOA_MRB_STATE_COUNT; ++i...
cocoa_mrb_states[i] = NULL;
}
}
cocoa_mrb_states[cocoa_vm_count++] = mrb;
struct RClass *ns = mrb_define_module(mrb, "Cocoa");
cocoa_state(mrb)->namespace = ns;
init_objc_hook();
init_cocoa_object(mrb, ns);
init_cocoa_block(mrb, ns);
init_cocoa_bridge_support(mrb);
init_cocoa(mrb);
}
}}
まず初めに渡されたmrb_stateをグローバル変数に設定していま...
その後、Objective-C、Cocoaとの接続の初期化が行われている...
**init_objc_hook(src/cocoa_obj_hook.m) [#yf05aeaa]
見た感じ、Objective-C的にオブジェクトが削除されるときにmr...
**init_cocoa_object(src/cocoa_object.m) [#wf68fcb9]
Cocoa::Objectの定義とメソッドの登録を行っています。各メソ...
**init_cocoa_block(src/cocoa_block.m) [#yfeb145e]
Cocoa::Blockの定義を行っています。
**init_cocoa_brigdge_support [#d52eebe7]
Cocoa::StructとCocoa::Constを定義し、const_missingをオー...
**init_cocoa(src/mrb/cocoa.rb) [#y8489beb]
Cocoa::ObjectなどについてRubyで書いた方が書きやすい、とい...
ちなみに、init_cocoa()で何をやっているかはsrc/mrb/cocoa.r...
*init_cocoa_test(test/mrb/cocoa_test.rb) [#jbac7246]
mruby-cocoaの初期化が終わったので例によってテストコードを...
**Cocoaクラスのロード [#j3c20859]
初めの疑問は
Cocoa::NSString
と書いたときにどう動いているかです。これまでにCocoa::NSSt...
答えは以下の部分です。
src/mrb/cocoa.rb
module Cocoa
def self.const_missing(name)
if ::Cocoa::Object.exists_cocoa_class?(name)
return ::Cocoa::Object.load_cocoa_class(name)
end
raise "uninitialized constant #{name}" # ToDo: N...
end
end
src/mrb/cocoa_object.m
#code(C){{
mrb_value
cocoa_class_load_cocoa_class(mrb_state *mrb, mrb_value kl...
{
mrb_value class_name_mrb;
mrb_get_args(mrb, "o", &class_name_mrb);
const char *class_name = mrb_sym2name(mrb, mrb_symbol...
if(!NSClassFromString([NSString stringWithCString:cla...
mrb_raise(mrb, E_NAME_ERROR, "Can't load %s class ...
}
struct RClass *object_class = cocoa_state(mrb)->objec...
return mrb_obj_value(mrb_define_class_under(mrb, coco...
}
}}
どう動くかというと、
-1回目のCocoa::NSString参照
-Cocoa::NSStringなどないのでCocoa::const_missingが呼び出...
-NSClassFromString()を使ってCocoaクラスをロード
-Ruby的にCocoa::NSStringを定義する
-2回目以降はCocoa::NSStringが定義されているのでそれが利用...
という動きになります。
**Cocoaメソッドの呼び出し [#ue6943bc]
次はメソッドの呼び出しです。test/mrb/cocoa_test.rbの先頭...
Cocoa::NSString._stringWithUTF8String("string")
見落としそうですが、'_'が付いてます。この_stringWithUTF8S...
class Cocoa::Object
def method_missing(name, *args, &block)
if '_' == name.to_s[0, 1]
return self.class.call_cocoa_method(:self, s...
else
raise "Unknow method #{name}"
end
end
というわけでCocoaメソッドを呼ぶときは'_'を本来のメソッド...
その後、Rubyで書かれたcall_cocoa_methodで呼び出すメソッド...
メソッド名を作成するということについて少し細くしておきま...
alert = Cocoa::MyAlertView._alloc._initWithTitle "Hello",
:message, "I am MobiRuby",
:delegate, nil,
:cancelButtonTitle, "I know!",
:otherButtonTitles, "What's?", nil
という呼び出しに対して"initWithTitle:message:delegate:can...
**プロパティの参照 [#q25f01a2]
mruby-cocoaでプロパティを参照する場合は以下のように書きま...
result = @test1[:prop1]
個人的には、
@test1.prop1
と書きたいところですが、そうするとRubyのメソッドなのかObj...
それはともかく、プロパティ参照が行われると、
+src/mrb/cocoa.rbのCocoa::Object#[]
+src/mrb/cocoa.rbのCocoa::Object#objc_property ← getter, ...
+src/cocoa_object.mのcocoa_object_objc_msgSend()
と処理が流れます。
**RubyでのCocoaメソッドの定義 [#m0703251]
mruby-cocoaでObjective-Cのメソッドを定義するにはdefではな...
define C::Void, :alertView, C::Pointer, :clickedButtonAt...
if index.to_i == 1
app = Cocoa::UIApplication._sharedApplication
url = Cocoa::NSURL._URLWithString("http://mobiru...
app._openURL url
end
end
というわけでdefineの引数は
+戻り値
+メソッド名
+第1引数の型
+第2引数の名前
+第2引数の型
+...
と記述すればいいようです。また、メソッドの処理はブロック...
Cocoa::Object#defineの中身に入っていくと、
+ブロックで渡されたメソッド本体をRubyのメソッドとして定義
+定義したRubyメソッドを呼び出すmruby-cfuncのクロージャを...
+Objective-Cにメソッドを追加
ということを行っています。
で終わろうと思ったのですが気になる点があるので続けます。...
class Cocoa::Object
def self.define(rettype_rb, *args, &block)
...
closure = CFunc::Closure.new(rettype_rb, [CFunc:...
self.new(a[0]).send(internal_method_name, *a...
end
a[0]って何が渡されるの?というのが気になる点ですが、self....
**RubyでのCocoaブロックの定義 [#ddd8ae60]
ブロックを定義するには以下のように書けばいいようです。
block = Cocoa::Block.new(CFunc::Int, [CFunc::Int]) { |i|
i.value + 1
}
Cocoa::Block.newの引数は、
+第1引数:戻り値の型
+第2引数:ブロック引数の配列
と指定するようです。
**BridgeSupport [#d21bb00e]
BridgeSupport(Cocoaで定義されている定数等の参照)は以下...
Cocoa::Const::kCFAbsoluteTimeIntervalSince1904
参照のためには下準備が必要です。test/main.mに書いてあるBr...
#code(C){{
struct BridgeSupportStructTable struct_table[] = {
{.name = "CGPoint", .definition = "x:f:y:f"},
...
{.name = NULL, .definition = NULL}
};
struct BridgeSupportConstTable const_table[] = {
{.name = "kCFAbsoluteTimeIntervalSince1904", .type = ...
...
{.name = NULL, .type=NULL, .value = NULL}
};
struct BridgeSupportEnumTable enum_table[] = {
{.name="enum1", .value=1},
{.name = NULL, .value = NULL}
};
int main(int argc, char *argv[])
{
mrb_state *mrb = mrb_open();
mrb->ud = malloc(sizeof(struct mrb_state_ud));
cfunc_state_offset = cfunc_offsetof(struct mrb_state_...
init_cfunc_module(mrb);
cocoa_state_offset = cocoa_offsetof(struct mrb_state_...
init_cocoa_module(mrb);
load_cocoa_bridgesupport(mrb, struct_table, const_tab...
}}
といった感じに利用したい構造体、定数の情報を記述し、load_...
*おわりに [#of725705]
今回はmruby-cocoaを読んできました。鍵となるのはconst_miss...
また、オブジェクト管理についてRubyでの管理とObjective-Cで...
終了行:
#contents
*はじめに [#ffe5d193]
[[mruby-cfuncを読んだ>MobiRuby/mruby-cfuncを読む]]ので次...
*test/main.m [#p04ea175]
mruby-cfuncと同様にtest/main.mからスタートします。
#code(C){{
struct mrb_state_ud {
struct cfunc_state cfunc_state;
struct cocoa_state cocoa_state;
};
int main(int argc, char *argv[])
{
mrb_state *mrb = mrb_open();
mrb->ud = malloc(sizeof(struct mrb_state_ud));
cfunc_state_offset = cfunc_offsetof(struct mrb_state_...
init_cfunc_module(mrb);
cocoa_state_offset = cocoa_offsetof(struct mrb_state_...
init_cocoa_module(mrb);
load_cocoa_bridgesupport(mrb, struct_table, const_tab...
init_unittest(mrb);
if (mrb->exc) {
mrb_p(mrb, mrb_obj_value(mrb->exc));
}
init_cocoa_test(mrb);
if (mrb->exc) {
mrb_p(mrb, mrb_obj_value(mrb->exc));
}
}
}}
mruby-cocoaはmruby-cfuncを使っているため、udにmruby-cfunc...
*init_cocoa_module(src/init_cocoa.m) [#je08c216]
#code(C){{
void init_cocoa_module(mrb_state *mrb)
{
if(cocoa_vm_count >= MAX_COCOA_MRB_STATE_COUNT - 1) {
puts("Too much open vm"); // TODO
}
if(cocoa_mrb_states==NULL) {
cocoa_mrb_states = malloc(sizeof(mrb_state *) * M...
for(int i = 0; i < MAX_COCOA_MRB_STATE_COUNT; ++i...
cocoa_mrb_states[i] = NULL;
}
}
cocoa_mrb_states[cocoa_vm_count++] = mrb;
struct RClass *ns = mrb_define_module(mrb, "Cocoa");
cocoa_state(mrb)->namespace = ns;
init_objc_hook();
init_cocoa_object(mrb, ns);
init_cocoa_block(mrb, ns);
init_cocoa_bridge_support(mrb);
init_cocoa(mrb);
}
}}
まず初めに渡されたmrb_stateをグローバル変数に設定していま...
その後、Objective-C、Cocoaとの接続の初期化が行われている...
**init_objc_hook(src/cocoa_obj_hook.m) [#yf05aeaa]
見た感じ、Objective-C的にオブジェクトが削除されるときにmr...
**init_cocoa_object(src/cocoa_object.m) [#wf68fcb9]
Cocoa::Objectの定義とメソッドの登録を行っています。各メソ...
**init_cocoa_block(src/cocoa_block.m) [#yfeb145e]
Cocoa::Blockの定義を行っています。
**init_cocoa_brigdge_support [#d52eebe7]
Cocoa::StructとCocoa::Constを定義し、const_missingをオー...
**init_cocoa(src/mrb/cocoa.rb) [#y8489beb]
Cocoa::ObjectなどについてRubyで書いた方が書きやすい、とい...
ちなみに、init_cocoa()で何をやっているかはsrc/mrb/cocoa.r...
*init_cocoa_test(test/mrb/cocoa_test.rb) [#jbac7246]
mruby-cocoaの初期化が終わったので例によってテストコードを...
**Cocoaクラスのロード [#j3c20859]
初めの疑問は
Cocoa::NSString
と書いたときにどう動いているかです。これまでにCocoa::NSSt...
答えは以下の部分です。
src/mrb/cocoa.rb
module Cocoa
def self.const_missing(name)
if ::Cocoa::Object.exists_cocoa_class?(name)
return ::Cocoa::Object.load_cocoa_class(name)
end
raise "uninitialized constant #{name}" # ToDo: N...
end
end
src/mrb/cocoa_object.m
#code(C){{
mrb_value
cocoa_class_load_cocoa_class(mrb_state *mrb, mrb_value kl...
{
mrb_value class_name_mrb;
mrb_get_args(mrb, "o", &class_name_mrb);
const char *class_name = mrb_sym2name(mrb, mrb_symbol...
if(!NSClassFromString([NSString stringWithCString:cla...
mrb_raise(mrb, E_NAME_ERROR, "Can't load %s class ...
}
struct RClass *object_class = cocoa_state(mrb)->objec...
return mrb_obj_value(mrb_define_class_under(mrb, coco...
}
}}
どう動くかというと、
-1回目のCocoa::NSString参照
-Cocoa::NSStringなどないのでCocoa::const_missingが呼び出...
-NSClassFromString()を使ってCocoaクラスをロード
-Ruby的にCocoa::NSStringを定義する
-2回目以降はCocoa::NSStringが定義されているのでそれが利用...
という動きになります。
**Cocoaメソッドの呼び出し [#ue6943bc]
次はメソッドの呼び出しです。test/mrb/cocoa_test.rbの先頭...
Cocoa::NSString._stringWithUTF8String("string")
見落としそうですが、'_'が付いてます。この_stringWithUTF8S...
class Cocoa::Object
def method_missing(name, *args, &block)
if '_' == name.to_s[0, 1]
return self.class.call_cocoa_method(:self, s...
else
raise "Unknow method #{name}"
end
end
というわけでCocoaメソッドを呼ぶときは'_'を本来のメソッド...
その後、Rubyで書かれたcall_cocoa_methodで呼び出すメソッド...
メソッド名を作成するということについて少し細くしておきま...
alert = Cocoa::MyAlertView._alloc._initWithTitle "Hello",
:message, "I am MobiRuby",
:delegate, nil,
:cancelButtonTitle, "I know!",
:otherButtonTitles, "What's?", nil
という呼び出しに対して"initWithTitle:message:delegate:can...
**プロパティの参照 [#q25f01a2]
mruby-cocoaでプロパティを参照する場合は以下のように書きま...
result = @test1[:prop1]
個人的には、
@test1.prop1
と書きたいところですが、そうするとRubyのメソッドなのかObj...
それはともかく、プロパティ参照が行われると、
+src/mrb/cocoa.rbのCocoa::Object#[]
+src/mrb/cocoa.rbのCocoa::Object#objc_property ← getter, ...
+src/cocoa_object.mのcocoa_object_objc_msgSend()
と処理が流れます。
**RubyでのCocoaメソッドの定義 [#m0703251]
mruby-cocoaでObjective-Cのメソッドを定義するにはdefではな...
define C::Void, :alertView, C::Pointer, :clickedButtonAt...
if index.to_i == 1
app = Cocoa::UIApplication._sharedApplication
url = Cocoa::NSURL._URLWithString("http://mobiru...
app._openURL url
end
end
というわけでdefineの引数は
+戻り値
+メソッド名
+第1引数の型
+第2引数の名前
+第2引数の型
+...
と記述すればいいようです。また、メソッドの処理はブロック...
Cocoa::Object#defineの中身に入っていくと、
+ブロックで渡されたメソッド本体をRubyのメソッドとして定義
+定義したRubyメソッドを呼び出すmruby-cfuncのクロージャを...
+Objective-Cにメソッドを追加
ということを行っています。
で終わろうと思ったのですが気になる点があるので続けます。...
class Cocoa::Object
def self.define(rettype_rb, *args, &block)
...
closure = CFunc::Closure.new(rettype_rb, [CFunc:...
self.new(a[0]).send(internal_method_name, *a...
end
a[0]って何が渡されるの?というのが気になる点ですが、self....
**RubyでのCocoaブロックの定義 [#ddd8ae60]
ブロックを定義するには以下のように書けばいいようです。
block = Cocoa::Block.new(CFunc::Int, [CFunc::Int]) { |i|
i.value + 1
}
Cocoa::Block.newの引数は、
+第1引数:戻り値の型
+第2引数:ブロック引数の配列
と指定するようです。
**BridgeSupport [#d21bb00e]
BridgeSupport(Cocoaで定義されている定数等の参照)は以下...
Cocoa::Const::kCFAbsoluteTimeIntervalSince1904
参照のためには下準備が必要です。test/main.mに書いてあるBr...
#code(C){{
struct BridgeSupportStructTable struct_table[] = {
{.name = "CGPoint", .definition = "x:f:y:f"},
...
{.name = NULL, .definition = NULL}
};
struct BridgeSupportConstTable const_table[] = {
{.name = "kCFAbsoluteTimeIntervalSince1904", .type = ...
...
{.name = NULL, .type=NULL, .value = NULL}
};
struct BridgeSupportEnumTable enum_table[] = {
{.name="enum1", .value=1},
{.name = NULL, .value = NULL}
};
int main(int argc, char *argv[])
{
mrb_state *mrb = mrb_open();
mrb->ud = malloc(sizeof(struct mrb_state_ud));
cfunc_state_offset = cfunc_offsetof(struct mrb_state_...
init_cfunc_module(mrb);
cocoa_state_offset = cocoa_offsetof(struct mrb_state_...
init_cocoa_module(mrb);
load_cocoa_bridgesupport(mrb, struct_table, const_tab...
}}
といった感じに利用したい構造体、定数の情報を記述し、load_...
*おわりに [#of725705]
今回はmruby-cocoaを読んできました。鍵となるのはconst_miss...
また、オブジェクト管理についてRubyでの管理とObjective-Cで...
ページ名: