高見知英の技術ログ

技術関係のログをQiitaから移行してきました。プログラミングのほか、使っているアプリの細かい仕様についてなど書いていきます。

LazarusでDelphiのプロジェクトを読み込む

このブログはLazarus(FreePascal)アドベントカレンダー18日目の記事です。

qiita.com

この機能を使えば昔Delphiで作ったあんなアプリをインポートして、Lazarusで使うことができます。

LazarusのLCLなどのライブラリにはある程度DelphiVCLと互換性があるので、運が良ければそのまま、そうでなくてもそれなりに改修を行なえばLazarusでもプロジェクトを使うことができます。

やってみた

ということで、今回インポートしてみたツールはこちら。とはいってもはるか昔まだOperaがPrestoエンジンを使っていた頃のアプリなので、もちろん今は全く使えないのですが・・・。

www.vector.co.jp

プロジェクトのインポート

とりあえずDelphiのプロジェクトを読み込みます。Delphiのプロジェクトを読み込むには、ツールメニューのDelphi変換を選びます。

f:id:TakamiChie:20211212185738p:plain
Delphi変換メニュー

ここで「DelphiプロジェクトをLazarusプロジェクトに変換」を選ぶと、*.dprのファイルを選択するダイアログが表示され、選択すると確認画面が表示されます。

f:id:TakamiChie:20211212190011p:plain
インポート詳細

このままインポートを開始すると、変換処理が開始されます。ここでやっているのは見た感じ次の通りです。

  • *.dprファイルを*.lprファイルに改名(元のファイルはConverterBackupフォルダにコピーされる)
  • ファイルのエンコードUTF-8に変更する
  • Windows APIを呼び出しているコードのうちLCLなどLazarusが使用できるライブラリで代用可能なものは、それに置き換えする(ShellExecuteOpenDocumentなど)
  • 互換性のないモジュールやプロパティの削除

いちおうこれらについては変換完了後、AutomaticConversion.logというファイルに出力されます。

エラーが起こった場合

なお、参照しようとしているモジュールが見つからなかった場合などは、次のようなダイアログが表示されます。

わたしの場合昔は参照フォルダから呼び出すクラスライブラリ集などを自分で作ってたので大変(幸い過去のライブラリは一つも捨てていないようだったので、時間をかければ復元できそうですが…)。

f:id:TakamiChie:20211212190738p:plain
インポート中のエラー表示

無事変換が終わると、通常通りプロジェクトが表示されます。F5で実行してみると・・・。

f:id:TakamiChie:20211212190834p:plain
当時のアプリが起動した。

なんとか起動しました。

ただ実際に使ってみると・・・

ただ実際にいろいろ過去のプロジェクトをいじってみたのですが、結構問題があちこちで起こります。

  • 画面上に表示されない範囲でLCLVCLの仕様が異なるところが多く*1、独自の拡張を行なったクラスなどがあった場合、かなりの手直しが必要になる。
  • ピクセル単位で描画処理を行なっている箇所などがあれば、縮尺がずれてしまい正常に表示されないことが多い。
  • dfmファイルがリソースに埋め込まれてしまっている場合などは、それらを削除せずにプログラムを読み込んでしまうため、エラーが発生する。
  • 変換時にソースコード文字コード変換を行なう・・・と思いきやときどき文字コードの変換を行なわずスキップしてしまうファイルが出る*2ため、結局すべての文字コードを確認し直す羽目になる。

このためとりあえずソースコードコンパイルして雰囲気を確認できたら、すべて閉じて一から実装し直し というほうがむしろ効率が良いような気もします。

つかいどころ

2003年頃、Delphi 6 Personalが無償提供され、それに飛びついていた というホビープログラマは、少なくないと思います(当時は無償で提供されている開発環境は貴重でしたので)。

プライベートフォルダに、GitやSVNリポジトリに、当時作っていたツールのソースコードが眠っている なんて方もいらっしゃるのではないでしょうか。

そんな人が、過去の遺産を取り出すには有用な機能ではないかと思います。

もしそんなプログラムがある方は、当時を振り返るという意味でとりあえずこの機能を使ってみる というのもよいのではないでしょうか?

ただ、実際にやる場合、プロジェクトごと変換してしまうと歪みが出るので、「DelphiユニットをLazarusユニットへ変換」メニューを使って参照ファイルを一個ずつ変換する 等というやり方が良いかもしれません・・・(だいぶ痛い目を見た)。

*1:たとえばTLabelがラベルの文字描画をDoDrawTextメソッドに分離せずPaintメソッド内で全部やっているとか、ウィジェットのサイズを自動調整するメソッドがAdjastBoundsではなくAdjastSizeになっているとか

*2:プロジェクト外のモジュールを呼んでいた場合などに起こりやすい様子