2010年01月30日
Posted at 3:04:23 PM JST | Category: ROOT
世間ではiPadの話題が沸騰しているようですが、うちでは7年ぶりにMacを買い替えました。
今まではPowerMac G5(2.0GHz dual)でしたが、今回買ったのはMac mini(2.53GHzモデル)です。
以前はパフォーマンスが欲しくて、ハイスペックなPowerMacを買い続けてきましたが、最近のMac Proだとスペックが高すぎて持て余しそうな感じだったので、安くて、小さくて、静かなMac miniにしました。

しかも今回は、内蔵HDDを東芝製SSD(256GB)に交換したので、通常のMac miniよりも高速です。電源ボタンを押した瞬間から自動ログインでFinderが起動するまでの時間が、わずか24秒です。
買ってきて、一度も起動することなく、いきなりSSDに交換したので、元々の起動速度と比較してどの程度高速になったのか分かりませんが、とにかく速いです。
それから、キーボードとマウスも買い替えました。両方ともBluetoothです。
いままで、MacとWindows機で同じキーボード&マウスを使うのに、ホスト切替機を使っていましたが、MacとWindowsを同時に起動させることはないので、Windows機にもBluetoothを装備させてキーボードとマウスを共有する構成にしました。
テーブルの上からホスト切替機とUSBケーブルが無くなって、とってもスッキリしました。
Comments [0] | Trackbacks [0]
2009年12月12日
Posted at 11:41:55 PM JST | Category: サイト更新情報
Xcodeのテキストエディタには、多くの言語に対応した構文色付け機能があって、予約語などがカラーリングされる。
でも、この構文色付けは、全ての言語を網羅している訳ではないし、実装されているJava言語がJava1.5からの新しい構文に対応していないなど、既存のものも完璧という訳ではない。
そんなわけで、Xcodeで構文色付け定義が書かれている.xclangspecファイルを編集して見ようと思ったのだが、、、どこを探しても.xclangspecファイルに関する情報がない。
まあ、Xcodeのプライベートフレームワーク関係のものなので、Appleが情報を公開していないのも無理はない話なのだが。。。
それで、しかたがないので、自分でXcodeでの構文色付け定義の資料を作ってみた。
.xclangspecは、Xcode3.0以降で使用可能なファイルで、ここに言語の構文定義を書くと、構文色付けだけでなく、コードフォーカスや関数ポップアップまで定義できるようになります。
ただ、なにぶん情報が少なく、手探りの状態で書いた資料なので、全てを網羅している訳でもないし、説明が足りない所や間違っている所も多々あるかも知れない上に、プライベートフレームワーク関係のものなので、いつ内容が変更されるかも分からない状態です。
でも、Xcodeに新たな言語を追加しようとしている人や、構文の色付けなどを自由にカスタマイズしたい人には一読の価値があると思います。
Comments [0] | Trackbacks [0]
2009年11月12日
Posted at 12:32:37 AM JST | Category: プログラミング
Objective-Cは、C言語にマクロによってオブジェクト指向の機能を追加した言語である。Objective-Cのソースコードは、マクロ展開されてC言語のソースコードになったあと、普通にCコンパイラによってコンパイルするというのが基本原理だ。
そして、このとき、Cコンパイラの代わりにC++コンパイラでコンパイルするものを、Objective-C++と呼んでいる。
Objective-C++によって、1つのソースコード内に2つ言語を混在させることができるようになる。Objective-CのインスタンスもC++のインスタンスも、ただのポインタとして扱えば相互に利用し合う事が可能だ。
しかし、C++コンパイラを使うことによって、Objective-Cのマクロな部分がパワーアップする訳ではないので、ハイブリッドな機能をもったクラスや、ハイブリッドなインスタンスを作ることはできない。あくまで、Objective-C言語 & C++言語なのである。
と、いうのが通説だったが、ハイブリッドな機能をもったクラスや、ハイブリッドなインスタンスは、ある程度までなら実現可能なようだ。それも今まで気づかなかったのが不思議なくらい簡単な方法で。
@interface Hyblid : NSObject {
int number;
}
- (void)setValue:(int)value;
class Hyblid_ {
@defs(Hyblid)
public:
int getValue();
};
@end
@implementation Hyblid
- (void)setValue:(int)value {
number = value;
}
int Hyblid_::getValue() {
return number;
}
@end
まず、ハイブリッドなクラスのインスタンス変数は、全てObjective-C側で定義する。そして、Objective-Cのメソッド定義の中に、C++のメンバ関数定義を混在させるような形でクラスを作って行く。このときC++のクラス定義のなかに@defs(Hyblid)と書くのがポイントだ。
こうすると、Objective-CのメソッドとC++メンバ関数の双方で、同じインスタンス変数が参照できるようになる。
Hyblid* obj = [[Hyblid alloc] init];
[obj setValue:123];
NSLog(@"value: %i", ((Hyblid_*)obj)->getValue());
// [出力] value: 123
allocで生成したインスタンスは、型をキャストさえすれば、Objective-CとC++のどちらでもアクセスできる。まさにハイブリッド。
このような事が可能なのは、ようするに、これがC++版のToll-Free Bridgeだからだ。
そういう訳なので、例えば、C++のコンストラクタで、
Hyblid_() {
isa = NSClassFromString(@"Hyblid");
[(id)this init];
}
このように実装すると、newでもインスタンスが生成できるようになる。ただし、インスタンス変数が0で初期化されないなど、多少動作は異なる。
Hyblid_* obj = new Hyblid_();
[(id)obj setValue:123];
NSLog(@"value: %i", obj->getValue());
// [出力] value: 123
また、面白いことに、newで生成したインスタンスも、retain countが有効なようで、C++のインスタンスでありながら、Objective-Cと同じ方法でインスタンスの破棄ができる。deleteを使う必要はない。
Hyblid_* obj = new Hyblid_();
NSLog(@"%i", [(id)obj retainCount]); // [出力] 1
[(id)obj retain];
NSLog(@"%i", [(id)obj retainCount]); // [出力] 2
[(id)obj release];
NSLog(@"%i", [(id)obj retainCount]); // [出力] 1
[(id)obj release];
NSLog(@"%i", [(id)obj retainCount]); // エラー!
でも、これで何もかもうまく行くわけではない、ADCのドキュメントにあるように、制約事項は多い。まず、インスタンス生成時の初期化や破棄時の後始末の仕組みが、Objective-CとC++で違う。allocやrelease使ったときは、C++のコンストラクタやデストラクタは呼ばれない。逆に、newやdeleteを使ったときは、Objective-Cのinitやdeallocは呼ばれない。それから、ハイブリッドなクラスから、ハイブリッドなサブクラスを作ることも、ちょっと難しいだろう。
Cocoaは、Objective-Cが持つ動的な特性を最大限に活用したフレームワークであるが、実際のところ、そういった動的なものが必要とされるのは、プログラム全体から見れば、ほんの一部でしかない。プログラムの大部分は、静的な言語のニーズの方が強いのだ。つまり、静的型付を基本とし、ピンポイントで動的型付が使える言語が理想的ということになる。Objective-C++は、そのようなニーズに対応できるのかもしれない。
Comments [0] | Trackbacks [0]
2009年10月14日
Posted at 11:39:22 PM JST | Category: プログラミング
プロダクティブ・プログラマという本を読んでみた。
プログラムの生産性を向上させる本。ようするにプログラムを早く作るコツが書かれている。
プログラムを早く作るコツには、いろいろあるが、ソースコードを速く書くにはテキストエディタのショートカットを活用せよと、この本の最初に書いてある。著者はテキストエディタに拘りがあるようで、UNIXのviエディタなどと比べると最近のエディタはコピー&ペーストの機能が弱いとも書いてあった。
よく考えて見ると、XCodeにはカスタマイズ可能なショートカットが沢山あるし、Objective-Cのような言語では、ヘッダーファイルの内容を実装ファイルに頻繁に書き写さなければならないので、コピー&ペーストは重要な機能の一つだ。
そこで、XCodeのユーザースクリプトを使って、ヘッダーファイル内の@propertyからインスタンス変数定義と実装ファイル内の@synthesizeを自動生成するショートカットを作ってみた。
まず、ここからスクリプトコードをダウンロードする。
つぎに、新規シェルスクリプトを作って、そこにダウンロードしてきたコードをコピーし、出力を「書類の内容を置き換える」にする。

これで準備完了。
あとは、ヘッダーファイルに@propertyを書いて、それを選択し、スクリプトを起動するだけ。一気に複数行選択することも可能だ。

スクリプトを実行すると、ヘッダーファイル内にインスタンス変数定義が追加される。

そして、さらに実装ファイル内には、それらに対応する@synthesize文まで追加される。

このスクリプトにショートカットを設定しておけば、ソースコードの記述がスピードアップすること間違いなしだ。ただ、XCodeはソースファイルの内容をメモリにキャッシュしてるらしく、実装ファイルを自動的に書き換えても、それがすぐに反映されないのが難点だ。。。
Comments [0] | Trackbacks [0]
2009年09月03日
Posted at 11:28:30 PM JST | Category: プログラミング
Snow Leopardになって、いままでDeprecatedとなっていたCocoa-JavaがJavaブリッジを含めて、綺麗さっぱり消滅しました。
そのおかげで、MIDIWindが動作しなくなりました;;
思えば、OSがバージョンアップする度に、動かなくなってるなぁ〜。MIDIWindは。
今後、JavaからObjective-Cのコードを呼びたいときは、JNIを使えと言うことらしく、JavaNativeFoundationと言ったものが用意されています。
逆にObjective-CからJavaを使う手段はないようです。
そんな訳でCocoa-Javaは消滅しましたが、その他のDeprecatedなAPIは、全部試した訳じゃないけど生き残ってるAPIも多いようで、それなりに下位互換は保たれているようだ。
それと、消滅すると思っていたPowerPCのコードは残ってるようで、オプションでRosettaをインストールすれば、PowerPCのソフトが動きます。どうせ残すなら、もう少しサポートを続けても良かった気もしますが。。。
ただし、MacOSX10.5はPowerPC32bit + PowerPC64bit + Intel32bit + Intel64bitのユニバーサルバイナリだったのが、MacOSX10.6になってPowerPC64bitのコードが削除されました。一応PowerPCは縮小方向にあるようです。
単純に考えると、これで実行ファイルの容量が25%削減されます。OSの容量が減った理由の一つがこれのようですね。
あと、なぜか、XCode3.2では、プロジェクトテンプレートから、Carbon、Ruby-Cocoa、Python-Cocoaが無くなってます。
Carbonはまだしも、Ruby-CocoaとPython-Cocoaは削除するには、少々早すぎますよね。
Comments [0] | Trackbacks [0]
2009年06月12日
Posted at 12:57:11 AM JST | Category: ROOT
ついにSnow Leopardが発表されましたね。
噂にあったとおり、Snow LeopardではIntel Macのみがサポートされるようで、これでPowerPC Macの歴史に幕がおりる形になります。
Rosettaも以外と短命でしたね。たしか、Rosettaで実行したアプリケーションは依存関係のあるライブラリも含めてPowerPCでなければならないため、OS全体からPowerPCコードが排除されたなら、もうRosettaは動作しないはずです。
ユニバーサルバイナリーは、32bitと64bitコードを混在させるために今後も残るでしょうが、以前と比べるとあまり必要性がないような気がします。
OS全体がスリムになってインストール容量も減ったようですが、何が削られたのかが気になります。
もしも、今までDeprecatedだったAPIが全て抹消されたりしたら、動かなくなるソフトが大量に出てきそう。
ちなみに、Snow Leopard serverからは、WebObjectsが削除されたようで、こちらももう終わりのようですね。
Comments [0] | Trackbacks [0]
2009年04月19日
Posted at 8:52:16 PM JST | Category: プログラミング
なんとなくLogic Expressを買ってみたら、なんとなくAudio Unitを作りたくなってしまいました。
Audio Unitの実態は、Carbonコンポーネントっていうやつで、Cocoaバンドルとは異なる構造になっています。
Cocoaバンドルでは、主要クラスのオブジェクトを入り口として、ObjCの動的なメソッド呼び出しによりバンドルを操作します。
Carbonコンポーネントでは、ComponentRoutineProcPtr型のコールバック関数を入り口として、コンポーネントを操作します。
ComponentRoutineProcPtrには、ComponentParameters構造体*cpとcomponentStorageの2つの引数があり、cp->whatがコマンドを表し、cp->paramsがコマンドに対するパラメータになっているので、switch - caseで処理を分岐させるのがオーソドックスなやり方です。
ComponentResult entryPoint(ComponentParameters *cp, Handle componentStorage)
{
switch(cp->what)
{
case kAudioUnitGetPropertySelect:
return function1(componentStorage,
cp->params[4],
cp->params[3],
cp->params[2],
cp->params[1],
cp->params[0]);
case kAudioUnitSetPropertySelect:
return function2(componentStorage,
cp->params[4],
cp->params[3],
cp->params[2],
cp->params[1],
cp->params[0]);
case ...
}
return badComponentSelector;
}
しかし、AudioUnitの場合コマンドは20個ぐらいあり、コマンドの数だけcase文を並べると、少々ソースコードが見づらくなります。また、あるコマンドが実装されているかどうかを要求してくるコマンドもあるので、重複したコードを書くことにもなってしまいます。
そこで、コマンドとそれに対応する関数ポインタのテーブルを予め作っておき、そこから動的に関数を呼び出す方法を考えてみた。
ComponentResult entryPoint(ComponentParameters *cp, Handle componentStorage)
{
void* function = findFunction(cp->what);
if(function == NULL)
{
return badComponentSelector;
}
register int result asm("eax");
int paramSize = (int)cp->paramSize;
int param = (int)cp->params;
asm
{
mov eax, paramSize
test eax, eax
jz L2
mov ecx, eax
mov edx, param
L1:
sub esp, 4
mov eax, [edx]
mov [esp], eax
add edx, 4
sub ecx, 4
ja L1
L2:
push componentStorage
call function;
pop ecx
add esp, paramSize
}
return result;
}
まず、findFunction()が、テーブルを参照してコマンド番号から関数ポインタを返す関数です。
そして、その次に来るのが、関数を動的に呼び出すアセンブラコードです。このように、C言語のソース内にアセンブラのソースを埋め込むことをインライン・アセンブラと言います。
変数の宣言で、registerと書くとその変数をCPUのレジスタに割り当てることをコンパイラに要求することができます。ここで、さらにasm("eax")などと書くと、割り当てるレジスタを指定することもできます。
asm{ ... }内には生のアセンブラを書く事ができますが、見てのとおりC言語の変数や引数を直接指定できるので、C言語とアセンブラ間での値のやり取りが簡単にできるようになっています。
それで、なぜここでいきなりアセンブラが出てきたかと言うと、C言語で上記のような処理を書くことが不可能だからです。
C言語でも関数ポインタを使って動的な関数の呼び出しはできますが、その際にはtypedefを使って呼び出し先の関数のシグネチャを定義しておく必要があります。シグネチャが不確定な関数は呼び出せません。また、どんなシグネチャにも対応できるように、func(...)などと可変長引数を使った場合でも、C言語には可変長引数を参照することはできても、設定することができないため、どうにもならないのです。
ちなみに、Objective-Cでメソッドを動的に呼出すobjc_msgSend()関数も、同じような理由からアセンブラで書かれています。
Comments [0] | Trackbacks [0]
2009年03月20日
Posted at 12:06:02 AM JST | Category: ソフトウエア
DIコンテナであるCocoaDIをバージョンアップしました。
今回の目玉は、プールオブジェクトです。
これは、同じオブジェクトを何度も再利用したり、複数の箇所で共有したりする場合に使います。
プールオブジェクトを使えば、必要なときにobjectForName:でコンテナからオブジェクトを取り出し、不要になったらreturnObject:でコンテナにオブジェクトを返すことで、同じオブジェクトを何度も再利用することができます。オブジェクトを新規に生成するか、プールしてあるオブジェクトを使うかは、objectForName:が判断します。
プールオブジェクトのもう一つの活用法は、オブジェクトの共有です。
生成されるプールオブジェクトには、数量を制限することができ、たとえば5つのオブジェクトを10個のスレッド間で使い回すようなことができます。オブジェクトの取得にlimitPoolObjectForName:を使えば、上限に達してオブジェクトが取得できないスレッドをロックし、他のスレッドがreturnObject:したときにロックが解除されます。
その他の新機能として、これまで未実装だったlong long、double、NSInteger、Class、SEL、NSData、NSDateの各パラメタータイプが実装されました。
ただし、SEL型については、プロパティーインジェクションに使えません。Key Value CodingがSEL型をサポートしていないためです。以前は、Class型もサポートされていなかったのですが、MacOSX10.5からサポートされました。
その他の変更点として、GCのサポートを必須から有効に変更しました。当初は「これからは、Objective-CもGCが標準の時代だぜー」とか思ってたのですが、やっぱりもとの参照カウント方式に戻して、GCを使うかどうかは、CocoaDIを使う人の自由にすることにしました。
Comments [0] | Trackbacks [0]
2009年02月08日
Posted at 10:14:20 PM JST | Category: ソフトウエア
以前、「フレームワークのテストとデバッグ」ということで、SenTestingKitフレームワークを使ったテキスト版TestRunnerについて紹介した訳だが、これがMacOSX10.5から使えなくなっていることが分かった。
調べて見ると、SenTestingKitフレームワークが/System/Library/Frameworksから無くなって、/Developer/Library/Frameworksに移動している。
フレームワークが消滅した訳ではないが、/Developer/Library/Frameworksは、実行時のライブラリ検索パスに入ってないらしく、ビルドはできても実行できない。
そして、XCodeのテスト機能は、依然としてビルド時に実行されてしまうため、そこからデバックに繋げることができない。
そういう訳で、テキスト版TestRunnerを自前で作って見ました。
特別なフレームワークは使っていませんが、作ってみると以外と簡単でした。
CocoaのNSAssertを拡張する形で作っており、Objective-Cのruntime APIを使って、テストケースを自動的に検索するため、テストは[TestRunner run];の1文で実行できます。
また、Objective-C++の関数オーバーロードを利用しているため、assertEquals()一つで、id, int, floatなど複数の型に対応し、テストが書きやすくなっています。
それと、テスト時間の計測に最初は、mach_time APIを利用していたのだけど、これが PowerPC Macでは使えるのに、Intel Macだと何故か使えないんですよね。同じバージョンのOSなのに、困ったものです。
しかたがないので、CoreServicesのAbsoluteTime APIに変更しました。ADCのドキュメントの方でも、mach_time APIよりもAbsoluteTime APIの方を優先して使うような感じのことが書かれていました。
でも、AbsoluteTime APIは、64bitをサポートしてない感じで、微妙に使いづらい。
Comments [0] | Trackbacks [0]
2008年12月20日
Posted at 9:25:41 PM JST | Category: サイト更新情報
Cocoaの記事「テキストの入力と描画」を掲載しました。以前書いたCocoa-Javaの記事をObjective-C用に書き直したものです。
今回、記事を書き直すにあたって、フィールドエディター周りの処理を調べ直しましたので、その辺の情報が充実した内容となっています。
それにしても、NSCellって、いろいろな応用ができて、使い方を覚えるととっても便利なオブジェクトですね。今回の記事の中でもNSTextFieldCellが活躍します。
Comments [0] | Trackbacks [0]