Borland® Delphi® 2005 Migration to .NET using VCL for .NET
by Bob Swart, Bob Swart Training & Consultancy
入門
在這個教程, 我們將使用Delphi 2005移植一個真正的Win32應用程序到Microsoft .NET Framework, 并使用Borland VCL(Visual Component Library)作為框架. 幾個現存的VCL for Win32應用程序—從Delphi 7的示例目錄中找到—將用Delphi 2005 打開, 并且移植到.NET并轉為VCL for .NET.
These exercises will demonstrate several migration issues, small and more significant alike.
這個課程將演示几個移植例子,程序小但有代表性.
VCL 和 VCL for .NET
VCL已經可以在.NET Framework下使用, 這讓我們可以更容易的移植Win32 VCL 應用程序到.NET(同樣可能將VCL項目轉為WinForms)
Delphi 2005 在BDS/3.0/Demos目錄中帶了很多應用程序範例, 同時包含了—除了個別外—Delphi.Net 和 Delphi Win32的子目錄. 在BDS/3.0/DelphiWin32/VCLWin32/目錄下包含了幾個Win32 VCL 例子, 其中一些已經移植到.NET, 可以在BDS/3.0/Delphi.NET/VCL目錄中找到.
其中一個還沒移植到.NET的範例Threads, 演示了在多線程中實現QuickSort, SelectionSort 和 BubbleSort算法. Threads 項目是一個Win32 VCL 應用程序, 現在我們將要復印機它到.NET下并使用VCL for .NET
首先, 我們為重要的文件創建一個備份.
現在我們已經準備好要在一個新的Threads項目上工作, 并將其移植到.NET
因為這個項目沒有存在bdsproj文件, Delphi 2005 IDE 會詢問你是要陞級到Win32還是.NET項目. 將會出現一個項目陞級對話框, 如下圖
陞級thrddemo項目到.NET
這樣, 將會生成一個thrddemo.bdsproj文件給我們, 裹面有相應的.NET personality標識,.現在我們保存項目, 新的相關屬性信息就會保存到文件thrddemo.bdsproj裹.
你將會得到大概11條警告和5個氏誤信息, 如下面:
[Warning] thrddemo.dpr(8): W1005 Unit 'Borland.Vcl.Forms' is specific to a platform
[Warning] ThSort.pas(6): W1005 Unit 'Borland.Vcl.Windows' is specific to a platform
[Warning] ThSort.pas(6): W1005 Unit 'Borland.Vcl.Messages' is specific to a platform
[Warning] ThSort.pas(6): W1005 Unit 'Borland.Vcl.Graphics' is specific to a platform
[Warning] ThSort.pas(6): W1005 Unit 'Borland.Vcl.Controls' is specific to a platform
[Warning] ThSort.pas(6): W1005 Unit 'Borland.Vcl.Forms' is specific to a platform
[Warning] ThSort.pas(6): W1005 Unit 'Borland.Vcl.Dialogs' is specific to a platform
[Warning] ThSort.pas(7): W1005 Unit 'Borland.Vcl.ExtCtrls' is specific to a platform
[Warning] ThSort.pas(7): W1005 Unit 'Borland.Vcl.StdCtrls' is specific to a platform
[Warning] SortThds.pas(6): W1005 Unit 'Borland.Vcl.Graphics' is specific to a platform
[Warning] SortThds.pas(6): W1005 Unit 'Borland.Vcl.ExtCtrls' is specific to a platform
[Error] SortThds.pas(18): E2397 Unsafe pointer only allowed if compiling with {$UNSAFECODE ON}
[Error] SortThds.pas(57): E2003 Undeclared identifier: 'Point'
[Error] SortThds.pas(65): E2396 Unsafe code only allowed in unsafe procedure
[Error] SortThds.pas(107): E2396 Unsafe code only allowed in unsafe procedure
[Fatal Error] ThSort.pas(39): F2063 Could not compile used unit 'SortThds.pas'
我們現在可以忽略所有的警告信息, 等一會我們再回頭來處理. 首先, 我們先改正那些編繹錯誤
第一個錯誤是在SortThds.pas文件的第18行, 提示是: t "unsafe pointer only allowed if compiling with {$UNSAFECODE ON}".(不安全的指針只有在使用{$UNSAFECODE ON}才能編繹).引起錯誤的代碼是在TSortThread類中聲明了指向FSortArray的類型PSortArray:
type
PSortArray = ^TSortArray;
TSortArray = array[0..MaxInt div SizeOf(Integer) - 1] of Integer;
TSortThread = class(TThread)
private
FBox: TPaintBox;
FSortArray: PSortArray;
PSortArray是指向TSortArray的指針, 而指針不是”安全”類型, 因此,會引發警告提示.後面還有一些其它不安全聲明的警告, 只要是使用了這個不安全的指針類型.
雖然最後的版本將不會使用到不安全的類型或代碼, 但首先, 將代碼標記為不安全的方式來解決編繹錯誤比較容易—先使項目順利編繹, 然後再將不安全的部分用安全的代碼代替.
忽略相關的警告信息, 還有4個錯誤剩下.
[Error] SortThds.pas(59): E2003 Undeclared identifier: 'Point'
[Error] SortThds.pas(67): E2396 Unsafe code only allowed in unsafe procedure
[Error] SortThds.pas(109): E2396 Unsafe code only allowed in unsafe procedure
[Fatal Error] ThSort.pas(39): F2063 Could not compile used unit 'SortThds.pas'
現在有一個聲明為Point未知類型變量.這行令人不快的代碼如下:
procedure PaintLine(Canvas: TCanvas; I, Len: Integer);
begin
Canvas.PolyLine([Point(0, I * 2 + 1), Point(Len, I * 2 + 1)]);
end;
看上去它呼叫了(兩次)一個函數Point, 但不知為什麼, .NET的編繹器無法找到函數Point. 這是一個使用重構(Refactor)--- Find Unit functionality(查找單元函數)的好機會, 它會幫我們定位的缺少的單元(定義函數Point的), 并且增加到單元的uses子句中.
這樣將會調用Find Unit對話框, 裹面包含查找到所有定義Point的標準單元. 許多單元被查找到, 包含Borland.Vcl.Types.Point, 一個看起來最適合這裹代碼的定義.


現在項目以可執行的本地.NET方式運行, 它帶有三個并發的線程.
然而, 這個項目還不是100%的安全代碼程序, 現在, 我們繼續工作來修改它.
“安全”代碼
包含不安全代碼的應用程序, 當你用PEVerify檢查時會不能通過. 現在的情況是你能接受一個移植了可運行的結果, 但你的最後目標, 可能還想為你的應用程序實現一個100%安全代碼的版本
第一個問題—引起所有其它錯誤信息—是指針的聲明. 我們可以將TSortArray聲明為一個只是”整數的數組(array of integer)”. 如果你想保持代碼能同時在Win32和.NET下編繹, 你可以使用編繹指示符來區別原有的代碼和新的代碼.
· {$IFDEF WIN32}
· PSortArray = ^TSortArray;
· TSortArray = array[0..MaxInt div SizeOf(Integer) - 1] of Integer;
· {$ELSE}
· TSortArray = array of Integer;
· {$ENDIF}
現在, 你將得到一個關于FSortArray定義的錯誤提示信息, 因為PSortArray現在是一個未知的類型. 使用.NET編繹器, 我們能簡單的定義一個FSortArray, 類型為TSortArray.
· TSortThread = class(TThread)
· private
· FBox: TPaintBox;
· FSortArray: {IFDEF WIN32}PSortArray{ IFDEF WIN32}PSortArray{ IFDEF WIN32}PSortArray{ELSE}TSortArray{$ENDIF};
現在, 你將得到一個錯誤的提示信息, 提示在create構造器中使用@操作符, 現在這個已經不用在這裹使用了
· constructor TSortThread.Create(Box: TPaintBox; var SortArray: array of Integer);
· begin
· inherited Create(False);
· FBox := Box;
· FSortArray := {IFDEF WIN32}@{ IFDEF WIN32}@{ IFDEF WIN32}@{ENDIF}SortArray;
· FSize := High(SortArray) - Low(SortArray) + 1;
· FreeOnTerminate := True;
· end;
最後的錯誤提示是關于在Execute方法中使用^操作符. 顯而易見, 你能再次將它處理成在.NET編繹器中不使用, 修改如下:
procedure TSortThread.Execute;
begin
// Sort(Slice(FSortArray^, FSize));
Sort(FSortArray{IFDEF WIN32}^{ IFDEF WIN32}^{ IFDEF WIN32}^{ENDIF});
end;
*注意函數Sort帶有一個var參數, 所以, 不用擔心這裹傳送整個interger 數組會被當成值傳遞參數(另外, 你要注意檢查是否需要增加一個const關鍵字)
我們現在沒有了不安全代碼的錯誤的提示, 只剩下指定平台(platform specific)的警告了. 現在已經是一個本地的, 安全受控的.NET可執行程序, 使用了VCL for .NET. 這個Threads演示了將指針快速但不完美(不安全)的移植, 然後, 再將其從Win32移植到安全的, 完全受控的.NET for Delphi VCL應用程序的方法.
免责声明:本文系网络转载或改编,未找到原创作者,版权归原作者所有。如涉及版权,请联系删