60
どう考えてもdisconなものを iPhoneに移植してみた Taro Matsuzawa aka btm (@smellman) at sumaben kanto #11

スマートフォン勉強会@関東 #11 どう考えてもdisconなものをiPhoneに移植してみた

Embed Size (px)

DESCRIPTION

 

Citation preview

Page 1: スマートフォン勉強会@関東 #11 どう考えてもdisconなものをiPhoneに移植してみた

どう考えてもdisconなものをiPhoneに移植してみた

Taro Matsuzawa aka btm (@smellman)at sumaben kanto #11

Page 2: スマートフォン勉強会@関東 #11 どう考えてもdisconなものをiPhoneに移植してみた

自己紹介的年表

Page 3: スマートフォン勉強会@関東 #11 どう考えてもdisconなものをiPhoneに移植してみた

1981

• 千葉県千葉市に生まれる

Page 4: スマートフォン勉強会@関東 #11 どう考えてもdisconなものをiPhoneに移植してみた

1988

• 白髪が生える

Page 5: スマートフォン勉強会@関東 #11 どう考えてもdisconなものをiPhoneに移植してみた

1989

• フライデーのヌード写真を強制的に見せられ女性恐怖症に

Page 6: スマートフォン勉強会@関東 #11 どう考えてもdisconなものをiPhoneに移植してみた

1991

• BL本鑑賞

Page 7: スマートフォン勉強会@関東 #11 どう考えてもdisconなものをiPhoneに移植してみた

1997

• 初めてのパソコン

• Windows 95 OSR2

• MMX Pentium 200Mhz

Page 8: スマートフォン勉強会@関東 #11 どう考えてもdisconなものをiPhoneに移植してみた

1999

• 東京電機大学理工学部入学

• English Speaking Society (E.S.S.)に入部

• 初恋

Page 9: スマートフォン勉強会@関東 #11 どう考えてもdisconなものをiPhoneに移植してみた

2000• デ・ジ・キャラットで萌えに目覚める

• 初恋の相手を秋葉に誘う

• Mozilla Party JP 1.0参加(初のOSSイベント参加)

• 彼女ができる

• コンピュータクラブ入部

• 埼玉西地区Linux研究会参加

• 彼女と別れる

• 腹いせにE.S.S.の部長に就任

Page 10: スマートフォン勉強会@関東 #11 どう考えてもdisconなものをiPhoneに移植してみた

2001

• オープンソース祭り参加

• アイスランド日本大使館設立に伴う留学生の招待を担当

• 鬱病

• Tokyo Linux Entertainment Community(TLEC)に参加

• WEB標準プロジェクト参加

Page 11: スマートフォン勉強会@関東 #11 どう考えてもdisconなものをiPhoneに移植してみた

2002• 二度目の恋を見つける

• 留年発覚、半年休学

• アルバイトでVBプログラマ(休学期間のみ)

• Mozilla Party 3.0 JPスタッフ参加

• もじら組スタッフに

• 復学

• 二人目の彼女ができる

Page 12: スマートフォン勉強会@関東 #11 どう考えてもdisconなものをiPhoneに移植してみた

2003

• 前就職先にアルバイト入社、入って二週間目でデスマ

• はめられてもじら組組長になる

• デスマで就活できなかったら勝手に内定がでる

• Mozilla Party JP 4.0 スタッフ参加

• 彼女と別れる

• デスマで時給1000円で月給40万

Page 13: スマートフォン勉強会@関東 #11 どう考えてもdisconなものをiPhoneに移植してみた

2004

• 東京電機大学理工学部情報科学科卒業(5回生)

• 神奈川県川崎市宮前区に引っ越す

• 借金する方法を覚える

• 日経ビジネスの取材をうけるも酷い扱いを受ける

• 「日経ビジネス買うぐらいならばんがいち買ったほうがいい」

• 某オラ○リーの本の翻訳の影武者をやるも出版されなかった

Page 14: スマートフォン勉強会@関東 #11 どう考えてもdisconなものをiPhoneに移植してみた

2005

• C Magazine 2005/10 ブラウザプログラミング特集2 「Firefoxのすべて」をPiroさんと共同執筆、執筆に伴いC++を初めてちゃんと勉強してコードを読む

• 仕事に限界を感じて退職を決意するも阻止される

Page 15: スマートフォン勉強会@関東 #11 どう考えてもdisconなものをiPhoneに移植してみた

2006

• 仕事に限界を感じるキッカケとなった上司が逃亡

• ほとんどの仕事がおれのところに

• 仕事に本当に限界を感じる

Page 16: スマートフォン勉強会@関東 #11 どう考えてもdisconなものをiPhoneに移植してみた

2007

• Software Design 2007/04 Firefox拡張機能開発チュートリアル(共著)

• 鬱病

• ゆ○○事件

• 辞めることを決意

• ヘッドハントの人と会うもその後連絡なし、まじむかつく

• 辞表提出

Page 17: スマートフォン勉強会@関東 #11 どう考えてもdisconなものをiPhoneに移植してみた

2008

• 最後の仕事が停電対応なので一人しか労を労ってくれない><

• 株式会社KBMJ入社

• オライリー・ジャパン「Firefox 3 Hacks」(共著) 執筆

• 実家へ引っ越す

• 寝取られ発覚

Page 18: スマートフォン勉強会@関東 #11 どう考えてもdisconなものをiPhoneに移植してみた

2009

• もじら組脱退

• 鬱病から復帰

• Software Design 「Firefoxステップアップ講座」2009.11 ~ 2010.04 まで半年間連載執筆

• OSS ECパッケージ「エレコマ」開発

Page 19: スマートフォン勉強会@関東 #11 どう考えてもdisconなものをiPhoneに移植してみた

2010

• iPhone開発の手伝い、In App Purchase 関係で2週間

• 副社長から「ちょっとベトナム行ってきて」と言われる

• ベトナム出張(一回目)

Page 20: スマートフォン勉強会@関東 #11 どう考えてもdisconなものをiPhoneに移植してみた

2011

• ベトナム出張(二回目)

• デング熱感染

• 二度と東南アジアに行けない体に

Page 21: スマートフォン勉強会@関東 #11 どう考えてもdisconなものをiPhoneに移植してみた

ベトナム出張前• 第一回目はiPhoneプログラミングの教育

• 以下副社長との会話

• 副社長「iPhoneプログラミングできるよね?」

• 俺「二週間しかやったことない上に、GUIほとんどわからないんですよ」

• 副社長「大丈夫だよ、出張まであと一週間ある」

• 俺「え?」

Page 22: スマートフォン勉強会@関東 #11 どう考えてもdisconなものをiPhoneに移植してみた

ベトナム出張前• 以下部長との会話

• 俺「ベトナムでiPhoneプログラミングっていうけど、今回のは業務持ち込みなんですよね?」

• 部長「そうそう、業務として仕事渡すからそれをこなしながらやってほしい」

• 俺「わかりました、で、何を実装するんでしょうか?」

• 部長「IMAPとかどうかな?」

• 俺「え?」

Page 23: スマートフォン勉強会@関東 #11 どう考えてもdisconなものをiPhoneに移植してみた

IMAP?

Page 24: スマートフォン勉強会@関東 #11 どう考えてもdisconなものをiPhoneに移植してみた

IMAP

• メールの受信箱に相当するプロトコル

• i.softbank.jpとかで標準

• 部長「まだメール受信機能ないじゃん」

• 俺「ちょっと無謀じゃないですか?」

• 部長「太郎ちゃんならできるよ」

• 俺「えー」

Page 25: スマートフォン勉強会@関東 #11 どう考えてもdisconなものをiPhoneに移植してみた

挫折

• ベトナムに来てしまったのでとりあえずわからないなりにやってみる

• ログインまではなんとかなる

• SSLとかちょっと無理すぎる

• とてもじゃないけど二週間の量じゃない

Page 26: スマートフォン勉強会@関東 #11 どう考えてもdisconなものをiPhoneに移植してみた

転換

• 相談してみる

• 俺「無理すぎるんだけど...」

• 同僚「他のライブラリとか見つからないの?」

• 俺「(見つからないから俺に話が来たんじゃ)えっと、探してみます」

Page 27: スマートフォン勉強会@関東 #11 どう考えてもdisconなものをiPhoneに移植してみた

なんかある• PantomimeというMac OS X/GNUStep向けのライブラリを発見、ライセンスはLGPL2

• 俺「2007年ぐらいから開発止まってるんだけど」

• 同僚「でも、ソースはあるんだよね」

• 俺「ライセンス的に問題が無いか調べる必要あるけど...」

• 同僚「じゃ調べて」

• 俺「えー」

Page 28: スマートフォン勉強会@関東 #11 どう考えてもdisconなものをiPhoneに移植してみた

LGPL2とiPhone• LGPL2自体は基本使うのは問題ない(ex. 昔のcocos2d-iphoneとか)

• 静的リンクすればいい

• ライブラリ自体のソースを添付するもしくは入手方法を明記

• リバースエンジニアリングを許可しないといけない

• 俺「リバースエンジニアリングってOKかな?」

• 同僚「一部のお客さんは嫌がったり組み込めないかもね」

• 俺「で、やるの?」

• 同僚「やって(はぁと」

• 俺「Σ(゚д゚lll)」

Page 29: スマートフォン勉強会@関東 #11 どう考えてもdisconなものをiPhoneに移植してみた

というわけで移植してみた話です

Page 30: スマートフォン勉強会@関東 #11 どう考えてもdisconなものをiPhoneに移植してみた

Pantomime

• Objective-Cで記述されたIMAP/POP/SMTPのライブラリ

• ターゲットはMac OS XとGNUStep

• 多くのソフトで動かされているという記述がサイトにある

• 最終リリースは 2007 / 2 / 5

• どう見てもdisconです。本当に(ry

Page 31: スマートフォン勉強会@関東 #11 どう考えてもdisconなものをiPhoneに移植してみた

移植のポイント 1

• 非推奨メソッドを通常のメソッドへ変更

• Mac OS X 10.2とかがターゲットのため非推奨メソッドだらけなので一つ一つ新しくしていく

• いらなそうな部分のコメントアウト

• NSDebugとかもういらないだろ

• 依存するライブラリへの対応

• がんばって依存するライブラリを動かせるようにする

Page 32: スマートフォン勉強会@関東 #11 どう考えてもdisconなものをiPhoneに移植してみた

移植のポイント 2

• GNUStepに依存するコード

• いらないので削除する

• SMTPのコード

• 今回のプロジェクトでは実装しなくていいのでコメントアウト(ひどい

• iOSに存在しないメソッドの代替案を探す

• 代替案がAppleが提供している場合はそれを利用

• 代替案がAppleが提供してない場合は自作する

Page 33: スマートフォン勉強会@関東 #11 どう考えてもdisconなものをiPhoneに移植してみた

非推奨メソッド

• 分かりやすい例だと以下のものが該当

• NSString cString

• NSFileManager fileAttributesAtPath:traverseLink:

• 非推奨メソッドはxcodeで警告が出ている

• デベロッパドキュメントで非推奨メソッドを検索すると推奨されるメソッドの情報が必ず載っている

Page 34: スマートフォン勉強会@関東 #11 どう考えてもdisconなものをiPhoneに移植してみた

NSFileManager

fileAttributesAtPath:traverseLink:

Page 35: スマートフォン勉強会@関東 #11 どう考えてもdisconなものをiPhoneに移植してみた

attributesOfItemAtPath:error:

- attributes = [[NSFileManager defaultManager] fileAttributesAtPath: thePath traverseLink: NO];+ NSError *error = nil;+ attributes = [[NSFileManager defaultManager] attributesOfItemAtPath: thePath error: &error];

大体ドキュメント読めばわかる

Page 36: スマートフォン勉強会@関東 #11 どう考えてもdisconなものをiPhoneに移植してみた

依存するライブラリ

• Pantomimeではopensslが利用されている。当然無いとビルドできない。

• openssl-xcodeというopensslを静的ライブラリにするものを使うとそのままiPhoneで利用できる

• https://github.com/sjlombardo/openssl-xcode

• ただし、ビルド対象が libcrypt.a のみなのでこれだけだとlibssl.aがないのでコンパイルが通りませんorz

Page 37: スマートフォン勉強会@関東 #11 どう考えてもdisconなものをiPhoneに移植してみた

無いなら作る

• libssl.aをビルドできるopenssl-xcodeを作ってしまう

• https://github.com/smellman/openssl-xcode

• 作った!

• libssl.a と libcrypt.a の両方が生成されるので多い日も安心

Page 38: スマートフォン勉強会@関東 #11 どう考えてもdisconなものをiPhoneに移植してみた

GNUStep対応のコード

• GNUStepに対応させるためのコードは今回は明らかに邪魔になっている

• そのせいで #ifdef MACOSX とかがあるけどそんなマクロ用意したくない(iOSだから)

• GNUStepとMac OS Xの実装を分離している部分を見つけたらMac OS

Xの方だけ残して削除するようにする。

• 見つけ次第削除していくだけでOK (Search and Destroy)

Page 39: スマートフォン勉強会@関東 #11 どう考えてもdisconなものをiPhoneに移植してみた

-#ifdef MACOSX #include <Pantomime/CWMacOSXGlue.h>-#endif

Mac OS X一択という考え方をする

Page 40: スマートフォン勉強会@関東 #11 どう考えてもdisconなものをiPhoneに移植してみた

例-#ifdef MACOSX #include <CoreFoundation/CFString.h> #include <CoreFoundation/CFStringEncodingExt.h>-#else-#include <GNUstepBase/GSCategories.h>-#endif

elseで処理されるのはGNUStepのコードとなる

Page 41: スマートフォン勉強会@関東 #11 どう考えてもdisconなものをiPhoneに移植してみた

iOSに存在しないもの

• iOSではそもそも存在しないものがある

• デバイス上の制限によるものが中心

• 代替案をとにかく探さないといけない

• 似たような機能があるかどうか?

• あればそれを採用

• 無ければ作る

Page 42: スマートフォン勉強会@関東 #11 どう考えてもdisconなものをiPhoneに移植してみた

NSHost

• 今回使われていたのは [[NSHost currentHost] name]

• 自分のホスト名を返すだけ

• gethostname で代用できる

• 返り値がNSStringなのでそれに合わせる必要がある

Page 43: スマートフォン勉強会@関東 #11 どう考えてもdisconなものをiPhoneに移植してみた

gethostname+ char s[65];+ memset(s, 0, sizeof(s));+ gethostname(s, sizeof(s)-1);+ NSString *hostName = [NSString stringWithCString:s encoding:NSUTF8StringEncoding]; aMailFile = [NSString stringWithFormat: @"%@:%@", [NSString stringWithFormat: @"%d.%d%d%d.%@", time(NULL), getpid(), rand(), [_cacheManager count],- [[NSHost currentHost] name]],+ hostName], ((id)theFlags ? (id)[theFlags maildirString] : (id)@"2,")];

よくあるパターンですね

Page 44: スマートフォン勉強会@関東 #11 どう考えてもdisconなものをiPhoneに移植してみた

NSCalendarDate

• iOSで存在しない上に、Mac OS XでもLegacy API扱いされている要らない子

• Pantomimeでは広範囲に使われていてかなり面倒

• パターンを分けて対処する

Page 45: スマートフォン勉強会@関東 #11 どう考えてもdisconなものをiPhoneに移植してみた

NSCalendarDateのパターン

• NSCalendarDateのインスタンスを保持しているケース

• NSDateを使うようにする

• descriptionWithCalendarFormatを使っているケース

• NSDateFormatterを使うようにする

• 時間の比較をしているケース

• NSCalendarとNSDateCompomentsを使うようにする

• timeIntervalSince1970 を使っているケース

• NSDateに同じメソッドがあるのでそれを使う

Page 46: スマートフォン勉強会@関東 #11 どう考えてもdisconなものをiPhoneに移植してみた

時間を比較- NSCalendarDate *aCalendarDate;+ NSCalendar *calendar = [NSCalendar currentCalendar];+ NSDate *aCurrentDate = [[NSData alloc] init]; int days; // We get the days interval between our two dates- aCalendarDate = [NSCalendarDate calendarDate];- [aCalendarDate years: NULL- months: NULL- days: &days- hours: NULL- minutes: NULL- seconds: NULL- sinceDate: aDate];- + NSDateComponents *comps;+ NSUInteger flags = NSDayCalendarUnit;+ comps = [calendar components:flags + fromDate:aDate+ toDate:aCurrentDate+ options:0];+ days = (int) [comps day];

あれ?w

Page 47: スマートフォン勉強会@関東 #11 どう考えてもdisconなものをiPhoneに移植してみた

NSMapTable

• NSMapTableというクラスではなく、typedef struct _NSMapTable NSMapTable;

• Mac OS X 10.0 ~ 10.4 までに使われていたもの

• 格納する型を指定できる

• オブジェクトのみとか、int型のみとかができる

• NSMapTable クラスで代用できるかと思ったら iOS にない。

Page 48: スマートフォン勉強会@関東 #11 どう考えてもdisconなものをiPhoneに移植してみた

オブジェクトの格納

• NSCreateMapTableでオブジェクトを格納するケース

• NSCreateMapTable(NSObjectMapKeyCallBacks, NSObjectMapValueCallBacks, 128);

• オブジェクトを格納してMapインターフェイスを使うには、NSMutableDictionaryが使える

Page 49: スマートフォン勉強会@関東 #11 どう考えてもdisconなものをiPhoneに移植してみた

NSMutableDictionary

//宣言- NSMapTable *_table;+ NSMutableDictionary *_table;

//初期化- _table = NSCreateMapTable(NSObjectMapKeyCallBacks, NSObjectMapValueCallBacks, 128);+ _table = [[NSMutableDictionary alloc] initWithCapacity:128];

//値挿入- NSMapInsert(_table, aUID, aDate);+ [_table setObject:aDate forKey:aUID];

Page 50: スマートフォン勉強会@関東 #11 どう考えてもdisconなものをiPhoneに移植してみた

int型の格納

• NSCreateMapTableでint型を格納するケース

• NSCreateMapTable(NSIntMapKeyCallBacks, NSObjectMapValueCallBacks, 128);

• NSMutableDictionaryはオブジェクト専門

• |←樹海|     ┗(^o^ )┓三

Page 51: スマートフォン勉強会@関東 #11 どう考えてもdisconなものをiPhoneに移植してみた

よく考えよう

• 必要なのはMap的な何か

• Javaとかも型強制(Generic)するやつあるよね

• Genericってなんかの機能に似てるとかいう話を聞いたことがある

• 記憶をたどる

• std::map

• C++ !!!!!!

Page 52: スマートフォン勉強会@関東 #11 どう考えてもdisconなものをiPhoneに移植してみた

C++とiPhone

• iPhoneではC++でも書ける

• ただし、Objective-Cから叩きたい

• Objective-C++ というものがある

• ( ; ゚д)ザワ(;゚д゚;)ザワ(д゚; )

• 実装してみる

• なんか動いた

• 初めて自分で考えて書いたC++のコードがObjective-C++とか...

Page 53: スマートフォン勉強会@関東 #11 どう考えてもdisconなものをiPhoneに移植してみた

Objective-C++でMap (1)

#ifndef _Pantomime_H_StdMapIntWrapper#define _Pantomime_H_StdMapIntWrapper

#import <Foundation/Foundation.h>

#ifdef __cplusplus#include <map>@interface StdMapIntWrapper : NSObject {@private std::map<int, int> *wrapper_map;}#else@interface StdMapIntWrapper : NSObject {@private void *wrapper_map;}#endif

- (int) valueForKey:(int)aKey;- (void) setValue:(int)aValue forKey:(int)aKey;- (void) removeValueForKey:(int)aKey;

@end

#endif // _Pantomime_H_StdMapIntWrapper

Page 54: スマートフォン勉強会@関東 #11 どう考えてもdisconなものをiPhoneに移植してみた

Objective-C++でMap (2)

#import <Pantomime/StdMapIntWrapper.h>

@implementation StdMapIntWrapper

- (id) init { self = [super init]; if (self) { wrapper_map = new std::map<int, int>; } return self;}

- (int) valueForKey:(int)aKey{ return (* wrapper_map)[aKey];}

- (void) setValue:(int)aValue forKey:(int)aKey{ (* wrapper_map)[aKey] = aValue;}

- (void) removeValueForKey:(int)aKey{ std::map<int, int>::iterator it; it = (* wrapper_map).find(aKey); if (it != (* wrapper_map).end()) { (* wrapper_map).erase(it); }}

- (void) dealloc{ wrapper_map = NULL; [super dealloc];}

@end

そんなに大変なものでもない

Page 55: スマートフォン勉強会@関東 #11 どう考えてもdisconなものをiPhoneに移植してみた

こんな風に//include+#include <Pantomime/StdMapIntWrapper.h>

//宣言-static NSMapTable *fd_to_cfsocket;+static StdMapIntWrapper *fd_to_cfsocket;

//初期化- fd_to_cfsocket = NSCreateMapTable(NSIntMapKeyCallBacks, NSIntMapValueCallBacks, 16); + fd_to_cfsocket = [[StdMapIntWrapper alloc] init];

//値挿入- NSMapInsert(fd_to_cfsocket, (void *)[_connection fd], (void *)_socket);+ [fd_to_cfsocket setValue:(void *)_socket forKey:(void *)[_connection fd]];

//値取得- socket = (CFSocketRef)NSMapGet(fd_to_cfsocket, (void*)fd);+ socket = (CFSocketRef)[fd_to_cfsocket valueForKey:(void*)fd];

Page 56: スマートフォン勉強会@関東 #11 どう考えてもdisconなものをiPhoneに移植してみた

おまけ: Modified UTF-7

• Pantomimeの本体では Modified UTF-7 の処理空っぽ

• メソッドだけある状態

• とりあえず実装してみた

Page 57: スマートフォン勉強会@関東 #11 どう考えてもdisconなものをiPhoneに移植してみた

こんな感じ- (NSString *) modifiedUTF7String{ NSString *str = self; unichar c; uint index = 0; BOOL nowBase64 = NO; NSMutableString *toBase64String = [[NSMutableString alloc] initWithString:@""]; NSMutableString *result = [[NSMutableString alloc] initWithString:@""]; for (; index < [str length]; index++){ c = [str characterAtIndex:index]; if ((0x20 <= c && c <= 0x7e)) { if (nowBase64) { NSString *base64edstr = [self getUTF7Parts:toBase64String]; toBase64String = [[NSMutableString alloc] initWithString:@""]; [result appendString:base64edstr]; [result appendString:@"-"]; nowBase64 = NO; } if (c == 0x26) { [result appendString:@"&-"]; } else { [result appendString:[NSString stringWithCharacters:&c length:1]]; } } else { if (!nowBase64) { nowBase64 = YES; [result appendString:@"&"]; } [toBase64String appendString:[NSString stringWithCharacters:&c length:1]]; } } if (nowBase64) { NSString *base64edstr = [self getUTF7Parts:toBase64String]; [result appendString:base64edstr]; [result appendString:@"-"]; nowBase64 = NO; } return result;}

Page 58: スマートフォン勉強会@関東 #11 どう考えてもdisconなものをiPhoneに移植してみた

まとめ

• Mac OS X用のライブラリを移植するのはわりとなんとかなる

• Appleのデベロッパードキュメントは情報の宝庫

• 使えるものはなんだって使う根性があるとよい

• Objective-C++とか恐れないで!

Page 59: スマートフォン勉強会@関東 #11 どう考えてもdisconなものをiPhoneに移植してみた

URLとか

• Pantomime本家

• http://www.collaboration-world.com/pantomime

• Pantomime iOS fork 版

• https://github.com/smellman/Pantomime

Page 60: スマートフォン勉強会@関東 #11 どう考えてもdisconなものをiPhoneに移植してみた

質問など(スリーサイズ以外)