iOS

2013年12月 1日 (日)

DelphiでObjective-Cのブロック

まず、最初に正規表現パックの方をちょっと更新しておきましたdashdash


更新内容はDelphiで正規表現(NSRegularExpression)で書きましたが、Delphiの文字列からNSStringオブジェクトを作成する時に、NSStringクラスのstringWithCharacters:length:クラスメソッドなどで作成すると、Delphiの文字列がコピーされる事になると思うのですが、文字列が巨大になるとオーバーヘッドになると思うので、コピーが発生しないinitWithCharactersNoCopy:length:freeWhenDone:インスタンスメソッドを使ってDelphi側とメモリを共有するようにしました(まぁ、これを気にするのは、テキストエディタとか作る時ぐらいだろうし、どうでもいいな・・・)。

ということで、タイトルのObjective-Cのブロック についてです。ブロックというのは、他の言語ではクロージャーとか呼ばれたりするものらしいですが、詳しくは、各自調べて下さいdashdash。ここでは、このブロックを引数に取るObjective-CのメソッドをDelphi側からどう呼ぶのか調べました。

例として、NSRegularExpressionクラスのenumerateMatchesInString:options:range:usingBlock:インスタンスメソッドを見てみます。

最初見た時、面食らいましたが、第4引数がブロックです。で、Delphi-ObjectiveCブリッジのソースコード(Macapi.ObjectiveC.pas)を読むかぎり、Objective-Cのブロックは、Delphi側ではメソッドポインタ型として宣言すればいいようです。ということで、上記の例をDelphi側にインポートすると、


こんな感じでしょうか。簡単ですねup。ただし、更にソースを追っていくと、Macapi.OCBlocks.pasにGetObjCBlockという関数があるのですが、この実装を見ると、

OSXプラットフォームでは空になります。ということで、Delphi XE4では、iOSプラットフォームでは呼べるようですが、OSXプラットフォームではブロックを引数に取るメソッドを簡単に呼べません。ぬぅぅぅぅ weep

注意:ソースコードをちょっと読んで勝手に判断したので、間違ってるかもしれませんsweat02

というか、自分で思ってたが、中身薄いブログばっか書いてるな・・・

2013年11月 9日 (土)

Delphiで正規表現(NSRegularExpression)

前回のDelphiで正規表現(VBScript) で書いたように、CocoaのNSRegularExpressionを使ってラップしたSystem.RegularExpressions.NSRegularExpressesion.pasを完成させましたdashdashdash

ということで、RegExPackの方を更新しておきました。詳しくはreadme.txtを。


Delphi XE4以降が必要です。

ところで、Cocoa APIを使って初めて本格的にプログラミングしたのですが、Cocoaで文字列を扱う場合は、NSStringクラスを使うことは知っていて、NSRegularExpressionクラスでもパターン、検索対象の文字列をNSStringクラスとしてやりとりするのですが、最後まで壮大な勘違いをしてましたdashdash

NSStringクラスというはUTF-16が基本sign02なんですね・・・・ずっと、UTF-8だと思ってましたsweat02sweat02。だから、NSStringのlengthプロパティはバイト(UTF-8のコードユニット)数ではなく、ワード(UTF-16のコードユニット)数を返す・・dashdashdash。ということで、Delphiのstring型と相性いいじゃんupupSystem.RegularExpressions.NSRegularExpressesion.pasの実装で、気付くまで、UTF16->UTF8へ変換したり、インデックスを調整するコードをごりごり書いていた・・・・

ということで、Delphi標準のMacapi.Foundation.pasに、Delphiのstring型をNSStringに変換するNSSTR関数がありますが、

思いっきりUTF-16<->UTF-8の変換のオーバーヘッドが発生してるようーーなsweat02sweat02。NSTR関数は使わないで、やるなら、NSStringクラスのstringWithCharacters:length:クラスメソッドと、getCharacters:range:インスタンスメソッドを使って、

ちなみに、stringWithCharacters:length:だと、指定した文字列がコピーされてメモリ上に重複してに持つことになるので、initWithCharactersNoCopy:length:freeWhenDone:インスタンスメソッドを使えば、Delphi側とメモリを共有できるっぽいup

このまま、調子に乗って、モチベーションが続く限り、次はUTF-16のPCRE版か、Oniguruma(Onigumo)版かな????

元々は、RFC 6265のクッキー仕様を実装しようとしてて、そこで正規表現使おうかなと思って、今は、クッキー仕様の実装ほったらかしで脱線しすぎ・・

自作ソフトウェア

無料ブログはココログ

メモ