きりかノート 3冊め

おあそびプログラミング

BUG:39 なにがなにやら

ここ3日くらい、先日の [BUG:39] の調査を続けてるんだけど、さっぱりわからねえ。とりあえず状況だけ整理すると、ruby 側で ns_override または addRubyMethod_withType で定義した ruby のメソッドを Objective-C から呼び出ししたときに、以下の3点の問題があるようだ。

  1. 引数の型が float または double のとき、Objective-C から渡された値が Ruby で正しくとれない
  2. 返値の型が float のとき、Ruby から返された値が Objective-C で正しくとれない
  3. 返値の型が double のとき、Objective-C から呼び出すと、methodSignature の取得のところで落ちる

1. と 2. は同じような理由かもしんないけど、2. にまず焦点を当てて調査。つーか、stuffForwardResult:(RBObject.m) の setReturnValue: した値が正しいところまで確認はしたので、これ以上なす術がないよ。行き詰まってしまったので、とりあえず他のことをしよう。

実験に使ったコードを、いちおうさらしておく。

 #import <objc/objc.h>
#import <Foundation/Foundation.h>

// dummy class for methodSignature
@interface FloatX : NSObject
- (float)testFloat:(float)fl;
@end
@implementation FloatX
- (float)testFloat:(float)fl
{
return fl + 1.0;
}
@end

@interface Float : NSObject
//- (float)testFloat:(float)fl;
@end

@implementation Float
/*
- (float)testFloat:(float)fl
{
NSLog(@"%@ %s - %e", self, _cmd, fl);
return fl + 1.0;
}
*/
- (void)forwardInvocation:(NSInvocation *)inv
{
if (strcmp((char*)[inv selector], "testFloat:") == 0) {
//void* arg1;
//unsigned int buflen = [[inv methodSignature] methodReturnLength];
//NSLog(@"size of %s %d <=> %d", [inv selector], buflen, sizeof(float));
//arg1 = malloc(buflen);
void *arg1 = malloc(sizeof(float));
[inv getArgument:arg1 atIndex:2];
NSLog(@"%@ %s -(in) %e", inv, _cmd, *(float*)arg1);
float ret = *(float*)arg1 + 3.45;
[inv setReturnValue:&ret];
} else {
[super forwardInvocation:inv];
}
}

- (NSMethodSignature*)methodSignatureForSelector:(SEL)a_sel
{
if (strcmp((char*)a_sel, "testFloat:") == 0) {
return [FloatX instanceMethodSignatureForSelector:a_sel];
} else {
return [super methodSignatureForSelector:a_sel];
}
}
@end


int
main(int argc, const char* argv[])
{
id flt;

id pool = [[NSAutoreleasePool alloc] init];
flt = [[Float alloc] init];
float f = [flt testFloat:1.23];
NSLog(@"main - %e", f);

[pool release];
return 0;
}

NSInvocation で転送されたメソッドについて、引数および返値が float のとき、NSInvocation で正しく取り扱えていることを確認した。実際には RubyCocoa では、handle_ruby_method_id/stret により 可変引数の形で受け取っているので、引数についてはその形式のメソッドとして va_list からとれるかってことを確認しないとやり方としては正しくないかも。