プログラミング

2011年10月21日 (金)

FireMonkeyでのショートカット(Windows)

以前の記事でWindowsのショートカットの動作にも問題があると書きましたが、解決法を上げるのを忘れてました。

私の見逃しかもしれませんが、FireMonkey/Winのコード中にはショートカットキー処理するコードがありません。
実際にショートカットを設定しても動作しないので、間違ってはいないと思います。おそらくまだ作りかけなんでしょう。
この件に関しては、そのうちアップデートで治ると思いますので正式対応を待ってもいいと思っていますが、 エンバカの公式フォーラムで困っている人がいるのを見つけたので(無理やりな)解決方法を書いておきます。

まず次のようなクラスを作ります:
interface
{$IFDEF MSWINDOWS}
uses
  System.Classes, Winapi.Windows, Winapi.Messages, FMX.Menus;

type
  TAccelkeyTable = class
  private
    var FTable : array of TMenuItem;
  protected

  public
    procedure Init;
    procedure Add(menuitem : TMenuItem);
    procedure Remove(menuitem : TMenuItem);
    function  Translate(var msg : TMsg) : Boolean;
    function  CheckShortCut(Handle : HWND; var Key: Word; var KeyChar: System.WideChar;  Shift: TShiftState): Boolean;
  end;

var
  AccelKeyTable : TAccelKeyTable = nil;


{$ENDIF}
implementation
{$IFDEF MSWINDOWS}

{ TAccelkeyTable }

procedure TAccelkeyTable.Add(menuitem: TMenuItem);
var
  i : integer;
begin
  i := Length(FTable);
  SetLength(FTable, i+1);
  FTable[i] := menuitem;
end;

procedure TAccelkeyTable.Init;
begin
  Initialize(FTable);
end;

procedure TAccelkeyTable.Remove(menuitem: TMenuItem);
var
  i, cnt : integer;
begin
  cnt := Length(FTable);
  for i := 0 to cnt-1 do
  begin
    if FTable[i] = menuitem then
    begin
      FTable[i] := nil;
      break;
    end;
  end;
end;

function TAccelkeyTable.Translate(var msg: TMsg): Boolean;
var
  Shift : TShiftState;
  Key : Word;
  KeyChar : System.WideChar;
begin
  result := false;
  if msg.message = WM_KEYDOWN then
  begin
    Shift := [];
    if (GetKeyState(VK_SHIFT) and $80) <> 0 then Shift := Shift + [ssShift]
    else if (GetKeyState(VK_CONTROL) and $80) <> 0 then Shift := Shift + [ssCtrl]
    else if (GetKeyState(VK_MENU) and $80) <> 0 then Shift := Shift + [ssAlt];

    Key := LOWORD(msg.wparam);
    KeyChar := System.WideChar(LOWORD(msg.lParam));
    result := CheckShortCut(msg.hwnd, Key, KeyChar, Shift);
  end;
end;

function TAccelkeyTable.CheckShortCut(Handle : HWND; var Key: Word; var KeyChar: System.WideChar; Shift: TShiftState) : Boolean;
var
  i, cnt : integer;
  sc : TShortCut;
begin
  result := false;

  sc := scNone;
  if ssShift in Shift then sc := sc or scShift
  else if ssCtrl in Shift then sc := sc or scCtrl
  else if ssAlt in Shift then sc := sc or scAlt;

  if Key > 32 then
  begin
    sc := sc or Key;
    //Application.MainForm.Caption := ShortCutToText(sc); // debug
    cnt := Length(FTable);
    for i := 0 to cnt-1 do
    begin
      if (FTable[i] <> nil) and (FTable[i].ShortCut = sc) then
      begin
        SendMessage(Handle, WM_COMMAND, NativeUInt( FTable[i] ), 0);
        result := true;
        break;
      end;
    end;
  end;
end;

initialization

{$ENDIF}
end.
このクラスのインスタンスを作り、ショートカットを設定したTMenuItemをすべて登録してください:
  AccelKeyTable.Add( mnuSaveAs );
  AccelKeyTable.Add( mnuCopy );
    ....
みたいな感じ
個人的にはTMainMenu/TMenuItemを派生したクラスを作って自動で登録するようにしてます。

次に、ショートカットキーが押された時にコマンドを実行するための処理を呼び出します。FireMonkeyのソースコードを見るとWM_COMMANDのwparamにTMenuItemのインスタンスを渡してメッセージを送ることでTMenuItem.Clickが実行されるようなので、キーイベントでWM_COMMANDをSendMessage()してやるようにします。

これも個人的にはFMX.Platform.Winのメッセージループを書き換えたりして実験してますが、もう少し単純にフォームのKeyDown()メソッドをoverrideして呼び出す方法を記載しておきます。


interface
  ・・・
type
  TForm1 = class(TForm)
  ・・・
 protected
  ・・・
     procedure KeyDown(var Key: Word; var KeyChar: System.WideChar; Shift: TShiftState); override;
  ・・・
  ・・・
  end;

implementation

  ・・・

procedure TForm1.KeyDown(var Key: Word; var KeyChar: System.WideChar;  Shift: TShiftState);
begin
{$ifdef MSWINDOWS}
  if not AccelKeyTable.CheckShortCut(FmxHandleToHWND(Handle), Key, KeyChar, Shift) then
    inherited;
{$else}
  inherited;
{$endif}
end;

  ・・・

| | コメント (2) | トラックバック (0)

2011年10月15日 (土)

FireMonkey小ネタ その2

昨日の記事、一つ問題が解決したので更新しました

昨日書こうと思ってたのに忘れてた小ネタを2つ追加。
調べればすぐにわかる情報ですが、FireMonkey向けの情報として一か所にまとまっていることにも意味があると思うので掲載。

6.TControl.ClientToScreen(), TControl.ScreenToClient()の代わり
FireMonkeyの場合、LocalToScreen()とScreenToLocal()が該当の機能です。・・・が、なぜかprotectedメンバーなので外部からアクセスできません。
・・・ですが、IControlのメソッドなのでコントロールをIControlでキャストすればアクセスできます。
screen := (ctrl as IControl).localToScreen(local);
や
local := (ctrl as IControl).ScreenToLocal(screen);
みたいな感じ
こういうVCLと同じ機能は名前もアクセス指定子もVCL準拠にして欲しかった。
何か意図するところがあるんでしょうけど。


7.マウスカーソル位置の取得・変更
マウス位置はPlatform.GetMousePos()で取得可能ですが、マウス位置を変更する方法が用意されていません。
マウス位置を変更するアプリは行儀が悪いってのは置いておいて、たまにやりたくなるのでこんなクラスを作りました。
unit FMXMouse;

interface
uses
  System.Types, FMX.Platform
{$ifdef MSWINDOWS}
  ,Winapi.Windows
{$endif}
{$ifdef MACOS}
  ,Macapi.CoreGraphics, Macapi.CocoaTypes
{$endif}
  ;

type
  TMouse = class
  public
    procedure SetCursorPos(const point : TPointF);
    function  GetCursorPos: TPointF;

    property CursorPos : TPointF read GetCursorPos write SetCursorPos;
  end;

var
  Mouse : TMouse = nil;

implementation


{ TMouse }

{$ifdef MACOS}
procedure TMouse.SetCursorPos(const point: TPointF);
var
  cgpoint : NSPoint;
begin
  cgpoint.x := point.X;
  cgpoint.y := point.Y;
  CGWarpMouseCursorPosition(cgpoint);
end;
{$endif}

{$ifdef MSWINDOWS}
procedure TMouse.SetCursorPos(const point: TPointF);
begin
  Winapi.Windows.SetCursorPos(round(point.X), round(point.Y));
end;
{$endif}

function TMouse.GetCursorPos: TPointF;
begin
  result := Platform.GetMousePos;
end;

initialization

  Mouse := TMouse.Create;

finalization

  Mouse.Free;

end.
ユニット名、クラス名などはお好きにどうぞ。
マウス座標なのでTPointでも良いのですが、FireMonkey内ではTPointFが使われることが多いのでTPointFで座標を返すようにしました

| | コメント (0) | トラックバック (0)

2011年10月14日 (金)

FireMonkey小ネタ5つ(未解決ネタも含む)

1.WinとOSXでMouseUpイベントの引数の値が違う
VCLやWinのFMXだとMouseUpイベントのShiftにはUpしたボタンの情報が含まれませんがOSXでは含まれます。
(例えば左ボタンのUPイベントなのにssLeftがShiftに含まれる)

なので以下のようなコードでMouseUp時に他のマウスボタンが押されていないことを確認する処理があるとWin/OSXで異なった結果になります

  if Shift*[ssLeft,ssMiddle,ssRight] = [] then
    ...

仕方ないので、こう書いて回避

  case Button of
    TMouseButton.mbLeft  : Shift := Shift - [ssLeft];
    TMouseButton.mbRight : Shift := Shift - [ssRight];
    TMouseButton.mbMiddle: Shift := Shift - [ssMiddle] ;
  end;

  if Shift * [ssLeft, ssMiddle, ssRight] = [] then
    ...


2.自作コンポーネントにTBitmap型のプロパティを持たせて、画像をシリアライズしようとすると画像がだんだんと劣化する

どうやらα値が無いBitmapの場合はjpegで格納するようです。

jpegで格納されても全然うれしくないのでTBitmapを派生した次のようなクラスのインスタンスをTBitmap型のプロパティに突っ込んで回避。必ずPNGでシリアライズされるようになります
interface
  TESXBitmap = class(TBitmap)
  protected
    procedure DefineProperties(Filer: TFiler); override;
    procedure ReadBitmap(Stream: TStream);
    procedure WriteBitmap(Stream: TStream);
  end;
  
implementation
{ TESXBitmap }

procedure TESXBitmap.DefineProperties(Filer: TFiler);
begin
  Filer.DefineBinaryProperty('PNG', ReadBitmap, WriteBitmap, Width * Height > 0);
end;

procedure TESXBitmap.ReadBitmap(Stream: TStream);
begin
  LoadFromStream(Stream);
end;

procedure TESXBitmap.WriteBitmap(Stream: TStream);
var
  Filter: TBitmapCodec;
  this : TBitmap;
begin
  filter := DefaultBitmapCodecClass.Create;
  this := self;
  filter.SaveToStream(Stream, this, 'png');
  filter.Free;
end;

3.自作コンポーネント内部で動的に生成したサブコンポーネントもシリアライズされてしまう

内部で生成したサブコンポーネントのParentに自作コンポーネントを指定すると、.fmxにシリアライズされます。シリアライズされる前提で設計すれば問題ないかもしれないですが、interface部に公開したくないワンオフのサブコンポーネントまで シリアライズしようとするので困りもの。

今の所回避方法がわかってないので、デザイン時はサブコンポーネントを生成しないようにして回避してます。
回避方法について情報をお持ちの方、教えてください。

20111015: @onimaro2010さんから情報をいただきました。サブコンポーネントを生成した後に、Storedプロパティをfalseにすれば良いようです。ありがとうございます。


4.非VisualコンポーネントはTComponentから派生しないと、TDataModuleに置けない

例えばFireMonkeyアプリでしか使わないからと、TFmxObjectを派生してコンポーネントをつくると、フォームには配置できるのにDataModuleには配置できなくなります。

20111018: @lynatanさんから情報をいただきました。DelphiQ&Aに投稿されていた記事によると、DataModuleのClassGroupプロパティを変更すればようようです。上の例だとFMX.Types.TFmxObjectにすればOK


5.自作コンポーネント用のstyleをパッケージに含ませる方法がわからない
styleファイルをrcdataにしてリソースに含ませるのかなと思いますが方法がわからない。ご存じの方教えてください。

| | コメント (0) | トラックバック (0)

2011年10月11日 (火)

FireMonkey TPopupを使いやすくする

Delphiの補完ウインドウのようなもの(親ウインドウの外観はアクティブのまま子ウインドウをポップアップする)を作りたくなりました。

VCLだとこの手のウインドウに非常に苦労したのでFireMonkeyでも苦労するかと思いきや、TPopupを使うと簡単に実現できました。(キー操作等に難があるので、要改良ですが、ちゃんとリージョン切り抜きもできるし便利です)

2011_1011_popuppanel

ただし、現状のFireMonkeyだとTPopup周りのコードはすべて手書きで書く必要があるようなので簡単にコンポーネント化してみました:(コンポーネントとして登録するだけで、ほとんど何もしてないですが)
unit FMX.ESXPopupPanel;

interface
uses
  System.Classes, System.Types, FMX.Types;

type
  TESXPopupPanel = class(TPopup)
  private
  protected
  public
    procedure Popup; override;
  end;

{$ifdef WIN32}
procedure Register;
{$endif}

implementation

{$ifdef WIN32}
procedure Register;
begin
  RegisterComponents('ESX', [TESXPopupPanel]);
end;
{$endif}


{ TESXPopupPanel }

procedure TESXPopupPanel.Popup;
begin
  Position.X := 0;
  Position.Y := 0;
  inherited;
end;

end.
上記ソースを保存し、適当なパッケージに含めてインストールしてください。
(ユニット名やクラス名はお好きにどうぞ)

インストールしたら、適当なプロジェクトを作成して、
1.フォームにTESXPopupPanelを配置
2.ボタンも配置
3.Visible=false、PlacementTarget=ボタン、Placement=plBottomCenterにする
4.PopupPanelの上に適当な部品を配置(ここではCalloutPanel&Calemdar)
5.ボタンのOnClickイベントに ESXPopupPanel1.Popup() を記述
6.実行してボタンを押すとPopupPanelが表示されます

| | コメント (0) | トラックバック (0)

2011年10月 2日 (日)

FireMonkey/OSX メニューアイテムのショートカット

FireMonkey/OSX メニューアイテムの話題その3

FireMonkeyのメニューアイテム等にもVCLと同じShortCutを設定するプロパティがあるんですが、まだ色々と未完成です。(今回はOSXの話ですが、Winでもショートカットには不具合があります回避方法はまた別の機会に)
まず、ShortCutプロパティにプロパティエディタが適切に設定されていないので、Ctrl+A 等の文字列で設定できず数値を入れる必要があります。

次に、VCLの時と同じように修飾キー(scShiftなど)のコードがd15..12ビットに割り当てられていますが、OSXの場合は特殊キーの表現まで含めるとキーコードだけで16ビット必要になるためビットが重複してしまっています。 おかげでカーソルキー等をショートカットに設定することができません。

TShortCutのフォーマット自体を変えるか、TShortCutからOSX依存のコードに変換する部分(FMX.Platform.Mac.pasのShortCutToKey())を適切なものに変える必要があると思いますが、どちらもライブラリソースコードの修正なしで対応するのは難しいです。ShortCutToKey()がTPlatformMacのメンバーならRTTIでなんとかなったかも
追記:全力わはーの@lynatan さんがShortCutToKey()を置き換える方法を編み出してくださいました。http://d.hatena.ne.jp/tales/20111002/1317525163

なのでとりあえず自前のShortCutToKey()を作って、メニューを作った後でメニューアイテムのショートカットを置き換えていく方法をとりました。

以下、コード
procedure ShortCutToKey(ShortCut: TShortCut; var Key: Char; var ModifierMask: NSUInteger);
begin
  Key := Chr(Lo(ShortCut));
  ModifierMask := 0;
  case Key of
  'A'..'Z' : Key := Char(Ord(Key)+$20);
  #$08 : Key := Char(NSBackspaceCharacter);
  #$09 : Key := Char(NSTabCharacter);
  #$0d : Key := Char(NSEnterCharacter);
  #$21 : Key := Char(NSPageUpFunctionKey);
  #$22 : Key := Char(NSPageDownFunctionKey);
  #$23 : Key := Char(NSEndFunctionKey);
  #$24 : Key := Char(NSHomeFunctionKey);
  #$25 : Key := Char(NSLeftArrowFunctionKey);
  #$26 : Key := Char(NSUpArrowFunctionKey);
  #$27 : Key := Char(NSRightArrowFunctionKey);
  #$28 : Key := Char(NSDownArrowFunctionKey);
  #$2e : Key := Char(NSDeleteCharacter);
  #$70..#$87 : Key := Char(NSF1FunctionKey+Ord(Key)-$70);
  end;

  if ShortCut and scCommand <> 0 then ModifierMask := ModifierMask or NSCommandKeyMask;
  if ShortCut and scShift <> 0 then ModifierMask := ModifierMask or NSShiftKeyMask;
  if ShortCut and scCtrl <> 0 then ModifierMask := ModifierMask or NSControlKeyMask;
  if ShortCut and scAlt <> 0 then ModifierMask := ModifierMask or NSAlternateKeyMask;
end;


class procedure TMacHelper.UpdateMenuShortCut(menuitem : TMenuItem);
var
  nsmnuitem: NSMenuItem;
  Key: Char;
  ModMask: NSUInteger;
begin
  if menuitem.Handle <> 0 then
  begin
    if not (menuitem.Parent is TMainMenu) then
    begin
      nsmnuitem := GetNSMenuItem(menuitem);

      ShortCutToKey(menuitem.ShortCut, Key, ModMask);
      nsmnuitem.setKeyEquivalent(NSSTR(Key));
      nsmnuitem.setKeyEquivalentModifierMask(ModMask);
    end;
  end;
end;
※前回の記事に書いた GetNSMenuItem()も必要です。
ショートカット設定が必要なMenuItemすべてに対してUpdateMenuShortCut()を呼び出すとショートカットが修正されます。(ただしすべてのショートカットの組み合わせが上手く行くかはテストしてません)

| | コメント (0) | トラックバック (0)

2011年10月 1日 (土)

FireMonkey/OSX メニューアイテムのEnabled制御

FireMonkey/OSXのTMainMenuについて。その2

以前、文字列の動的変更についての記事を書きましたが、あの方法を応用すればチェックマーク等も同じようにして動的変更できます。

ただし、Enabledについては上手くいきません。正確にはEnabledプロパティの変更そのものは出来るものの、Enabledをfalseにしてもメニューがグレーアウトしてくれません。

これについて検索してみるとよくある話題らしく、(XCode/ObjCでの)解決方法はすぐに見つかりました。
どうやらNSMenuItemのターゲットオブジェクトにvalidateMenuIte:というメソッドを実装してやる必要があるようです。

ただ、この方法をFireMonkey/Delphiで実現する手段がすぐには思いつかず、いったんはDelphiのUpdateを待とうかと思ってたんですが、ちょっと基本に立ち返ってAppleのObjectiveCについての資料を読み漁り、試してみたところ以外とシンプルにできました。

以下サンプルコード:

// TMenuItemからNSMenuItemを取り出す
type
  TDummyOCLocal = class(TOCLocal)
    property Super;
  end;

class function TMacHelper.GetNSMenuItem(menuitem : TMenuItem) : NSMenuItem;
var
  nsmnuitem: NSMenuItem;
  nsobj : TDummyOCLocal;
begin
  result := nil;
  if menuitem.Handle <> 0 then
  begin
    if not (menuitem.Parent is TMainMenu) then
    begin
      nsobj := TDummyOCLocal(TOCLocal(FmxHandleToObjC(menuitem.Handle)));
      result := NSMenuItem(nsobj.Super);
    end else begin
      result := NSMenuItem(FmxHandleToObjC(menuitem.Handle));
    end;
  end;
end;

// NSMenuItemのターゲットオブジェクトに追加実装するメソッドの本体
// とりあえず NSMenuItemのisEnabledをそのまま返す。
// これで一応目的は果たせる。
function validateMenuItem(this : Pointer; cmd : SEL; sender : Pointer) : Byte; cdecl;
var
  menuitem : NSMenuItem;
begin
  menuitem := TNSMenuItem.Wrap(sender);
  if menuitem.isEnabled then
  begin
    result := 1;
  end else begin
    result := 0;
  end;
end;

// (1)TMainMenuが生成された後、適当なTMenuItem(トップ項目以外)をこの手続きに渡すと
// NSMenuItemのターゲットオブジェクトに validateMenuItem が実装される
class procedure TMacHelper.AddMenuValidator(sample_menuitem : TMenuItem);
var
  nsmnuitem: NSMenuItem;
  objid : Pointer;
  cls : Pointer;
begin
  nsmnuitem := GetNSMenuItem(sample_menuitem);
  if nsmnuitem <> nil then
  begin
    objid := nsmnuitem.target;
    cls := object_getClass(objid);
    // Appleの"ObjCRuntimeRef.pdf" "ObhCRuntimeGuide.pdf" 参照
    class_addMethod(cls, sel_getUid(PAnsiChar('validateMenuItem:')), Pointer(@validateMenuItem), 'C@:@');
  end;
end;
// (2) TMenuItemのEnabledプロパティをNSMenuItemのEnabledに反映させる
class procedure TMacHelper.UpdateMenuEnabled(menuitem : TMenuItem);
var
  nsmnuitem: NSMenuItem;
begin
  if menuitem.Handle <> 0 then
  begin
    if not (menuitem.Parent is TMainMenu) then
    begin
      nsmnuitem := GetNSMenuItem(menuitem);

      nsmnuitem.setEnabled(menuitem.Enabled);
    end;
  end;
end;

(1)TMainMenuが生成された後、適当なTMenuItem(トップ項目以外ならなんでもOK)を.AddMenuValidator(sample_menuitem : TMenuItem) に渡す

(2)TMenuItemのEnabledプロパティが変更されたらUpdateMenuEnabled()でNSMenuItemのEnabledプロパティに反映させる。(個人的にはTMenuItemを継承したクラスを作って連動させてます)

(3)対応するメニュー項目がEnabledに応じてグレイアウトします

| | コメント (0) | トラックバック (0)

2011年2月25日 (金)

NativeClient on Chrome10

以前投稿したNaClのテストデモがChrome10で動作しなくなっていたので修正しました。

NativeClientを有効にしていない場合は、事前にChrome10のバーに”about:flags”を開き、"Native Client"を有効にしてChoromeを再起動しておいてください。


ソース一式も上げておきます:download

| | コメント (0) | トラックバック (0)

2010年3月24日 (水)

Flash

友人がT01aを買ったのをきっかけにFlashで遊んでます。
まずはT01aやN01aで動かそうと思い、ライフゲームをActionScript2で組んでみたのですが、中々の低速度。でも少しチューニングするとかなり速度が改善したりして非常に楽しい。(N01aのFlashLiteは制限が多すぎて早々にあきらめましたが)

今はActionScript3でゲームを作ってます。六角大王を触り始めたりMarbleCLAYを作り出したのも元々はゲーム用のキャラクター作りが主目的(SFC用のスーパードンキーコングみたいにプリレンダでキャラを作りたかった。)なので、脱線というよりはこちらが本線なんですが。

ゲームのほうはまだまだ処理が重くて公開できるようなものではないのですが、ActionScript3はDelphiと同じように静的型付けが強く、非常にしっくりくる言語でパフォーマンスもそこそこ高いと思います。Flashでここまでできるとは思ってませんでした。(同時に携帯機でのFlashの重さもここまでとは思ってませんでしたが、これはこちらの作りの問題が大きいんだと思います)

ソースが無いのであまり価値は無いですが一月前に作ったライフゲームを貼っておきます:

AS3版ライフゲーム改

※Flash/ActionScriptの編集はFlashDevelopで行ってます。これとfdb plugin( 最新版用パッチ)があればほぼストレスなく開発できます。すばらしい環境を無償で提供してくれている開発者の方々に感謝。

※FlashDevelopの不満点が1点あったのを思い出した。コードの折りたたみ機能が完全に無効にできないようでそこが少し不便。(ProgramSettingで一見無効にできたように見えても、クリックのしどころが悪いと折りたたみが発動してしまう)

| | コメント (0) | トラックバック (0)

2010年2月 2日 (火)

OCamlでパース

実家にPCを持って帰ってOcamlでのパースの続きをしようとしたところ、
ACアダプターを忘れて手をつけられず。ちょっと勢いが落ちた・・・

軽く調べた限りではOcamlではCamlp4というプリプロセッサを使って自分自身の構文を拡張する?機能があるらしく、その機能を使うとパーサーを作れるのかな?
http://www.jmuk.org/~mukai/camlp4tut.html (Campl4チュートリアル)

を見ながら試したところ以下の感じでパースしていけそう・・・

#load "dynlink.cma";;
#load "camlp4o.cma";;
open Genlex

let lexer = make_lexer [ "#"; "("; ")";  ";" ]

let h_file = open_in "glext.h"

let h_stream = Stream.of_channel h_file

let tok_stream = lexer h_stream

let directive = parser
    [< 'Ident "ifdef"; 'Ident x >] -> "#ifdef" ^ " " ^ x
  | [< 'Ident "ifndef"; 'Ident x >] -> "#ifndef" ^ " " ^ x
・・・・・

う~ん。このままやっていくと結局yaccとかを使うのと同じくらいの手間がかかりそう。
もちろん、ソース内に構文定義も書けるから1ファイルですむので今回の書き捨てプログラムのような目的には適しているけど、まっとうにCのヘッダーを解析しようとすると結構本気で構文ツリーを組み立てないといけないと思うので、さすがにそれは脱線しすぎ。

Delphiで作った自前の関数で必要なところだけ解析するほうが圧倒的に早いから今回の目的でOCamlを使うのはやめておこう。

でも、強い静的型付けは非常に好みだし、まだしっくり手にはなじんでないけど、型推論とか多相バリアント、強力なパターンマッチング等は非常に面白い。複数引数の関数は1引数の関数を返す関数を多層化したもの(カリー化?)をという考え方も新鮮です。

前に書いたVHDLの構文解析の作り直し時にはぜひ使いたい。

| | コメント (0) | トラックバック (0)

2010年1月27日 (水)

Ocaml

前回、OpenGL3.2用のヘッダーをDelphiに移植中と書きました。
いつもどおり、手作業でちまちまと必要なAPI宣言だけを移植してもよかったんですが、
今後の事も考えて、glext.hファイル等からAPI宣言と定数定義を抜き出すPythonスクリプトを書こうと思い立ちました。
数年に1回程度しか使わないPythonスクリプトを苦労して書きながら、定数定義とAPI名及び、引数の型一覧を取得できたところで、いつもの悪い癖が出てしまいました。

続きを読む "Ocaml"

| | コメント (0) | トラックバック (0)