Переносим программы с Turbo Pascal на Delphi

Переносим программы с Turbo Pascal на Delphi


Данная статья призвана ответить не только на вопрос «Как перенести программу, написанную на TurboPascal в среду Delphi», но и «Как комфортно писать консольные приложения ». Под словом комфортно я понимаю присутствие схожего депозитария процедур и функций как в TP.

Использовались TP7, Delphi 10 lite, (Delphi 7)

Шаг первый — О файлах

В TP у нас есть pas файл, который мы компилируем и получаем приложение. В Delphi же у нас несколько файлов проекта, во главе с Project1.dpr. Берем нашу программу и меняем у нее расширение.

MyProg.pas -> MyProg.dpr

Теперь откроем его и приступим к редактированию.

Шаг второй — Сначала самое простое.

Консольные программы на Delphi содержат директиву {$APPTYPE CONSOLE}. Она показывает компилятору, что следует генерировать консольное Win32 приложение. При запуске будет создана текстовая консоль, через которую можно взаимодействовать c вашей программой. Ввод и вывод будут автоматически ассоциированы с этим черным окошечком.

(Отсутствие этой директивы эквивалентно {$APPTYPE GUI}. В этом режиме Delphi генерирует оконные приложения)

Определять эту директиву можно только в главной программе, определение в модулях, библиотеках и пакетах недопустимо.

Пример:

program pc;
begin
writeln('Hello world');
readln;
end.
program pc;
{$APPTYPE CONSOLE}
begin
  writeln('Hello world');
  readln;
end.

Пример простой, но чего-то большего для пояснения, думаю не нужно.

Шаг третий – Модуль CRT

Рассмотрим только один модуль, по причине его популярности и необходимости. Остальные, например Graph и TurboVision, уже архаика и сложно представить, где их можно использовать.

Итак, CRT: чрезвычайно полезный модуль из TP и отсутствующий в Delphi. Так как это Win32 приложение то мы имеем доступ к куче WinAPI, все их можно найти в справке, прилагающейся к Delphi. Для работы с ними необходимо подключить модуль Windows.

(Если ваше приложение не использует этот модуль, то этот шаг можно пропустить.)

Пример функции очистки экрана c использованием API:

procedure Clrscr;
Var Max, Coord : TCoord;
ConHandle : THandle;
tmp : cardinal;
begin
// Получаем хендл(ссылку) на стандартный вывод - это наша консоль
ConHandle := GetStdHandle(STD_OUTPUT_HANDLE);
// координаты ячейки, от которой будем писать символы
Coord.X := 0;
Coord.Y := 0;
// получаем размеры нашей консоли
Max := GetLargestConsoleWindowSize(ConHandle);
// Заполняем консоль пробелами
FillConsoleOutputCharacter(ConHandle, '  ', Max.X * Max.Y, Coord, tmp);
// устанавливаем каретку в начало
SetConsoleCursorPosition(ConHandle, Coord);
end;

Процедура получилась громоздкой. Для сокращения кода и увеличения быстродействия можно вынести инициализацию хендла и размеров консоли из подрограмм.

Unit OurCrt;
...
interface

Var Max, Coord : TCoord;
ConHandle : THandle;
tmp : cardinal;
...
procedure Clrscr;
...

implementation

procedure Clrscr;
begin
Coord.X := 0;
Coord.Y := 0;
FillConsoleOutputCharacter(ConHandle, ' ', Max.X * Max.Y, Coord, tmp);
SetConsoleCursorPosition(ConHandle, Coord);
end;

...

initialization
ConHandle := GetStdHandle(STD_OUTPUT_HANDLE);
Max := GetLargestConsoleWindowSize(ConHandle);

end.

Но не будем изобретать велосипеды. Вот (линк) найденный мной модуль на просторах Интернета. Примечателен он тем, что кроме оригинальных функций, содержит и дополнительные для работы с мышью. При переносе программы, конечно, от них никакого толку, а вот при написании приложения с нуля могут пригодиться.

(На 64 разрядной платформе компилироваться будет, если убрать {$IfDef Win32}, но работоспособность мной не проверена.)

Шаг четвертый – Кодировка

Если мы использовали русские буквы при разработке программы на TP, то, открыв файл в Delphi, мы будем лицезреть вместо них иероглифы, которые обретают вид только в приложении, после компиляции. Для удобной работы необходимо открыть файл в 866 кодировке и сохранить в 1251. Редактирование программы теперь удобней, а иероглифы перебежали в консольное окошко. Каждый раз сохранять файлы в разных кодировках очень неудобно, поэтому рассмотрим еще варианты.

Конвертирование:

WinAPI предоставляет возможность конвертировать символы кодировок OEM и ANSI: OemToChar() , CharToOem().

Пример:

program Project1;
{$APPTYPE CONSOLE}
uses
windows
//,SysUtils
;
function PR(Const a : string) : string;
begin
SetLength(result, length(a));
CharToOem(PChar(a), Pchar(result));
end;
begin
//setconsoleCp(866); //установка кодовой страницы
Writeln(PR('Привет');
readln;
end.

Использование этого способа вызывает необходимость редактирование всего текста программы, и чем больше мы выводили в консоль, тем больше дополнительных вызовов процедур.

Еще один вариант это переопределение процедур вывода. Как и в случае с модулем crt уже имеется готовая реализация — esconsole.

(Что бы работало с CRT32 нужно подключать в таком порядке

uses
CRT32 in 'CRT32.pas',
EsConsole in 'EsConsole.pas';

)

Шаг пятый – Типы данных

Среди целочисленных и вещественных типов разницы фактически нет, исключение является тип Integer, он увеличился в два раза(32 разрядная версия компилятора Delphi).

Со строками немного сложней в Delphi их несколько (в моей 3).

ShortString – аналог строк в ТП

AnsiString – длинные строки 8 разрядных символов

WideString – длинные строки 16 разрядных символов

(В новых версиях есть еще UnicodeString и UTF8String.)

Размер длинных строк может достигать до 2 гигабайт, и по умолчанию используются именно они (В моей AnsiString, в более новых одна из Unicode). Между строками большая разница, но работают они с одними и теми же процедурами, что позволяет компилировать TP код без модификаций. Во избежание появления артефактов необходимо компилировать код с директивой {$H-}. В этом случае все переменные, описанные как String, будут ShortString.

Пример:

program Project1;
{$APPTYPE CONSOLE}
uses
//SysUtils,
CRT32 in 'CRT32.pas',
EsConsole in 'EsConsole.pas';
{$H-}
Var s : string
begin
Clrscr;
s := 'Привет Мир!!!';
Writeln(s);
Readkey;
end.

Шаг шестой – обратно к паскалю

(Это делается в учебных целях, на практике в этом нет необходимости.)

Наш код подвергся добавлению некоторых директив, которые мы спрячем в другие директивы от TP.

Пример:

program Project1;
{$IFDEF MSWINDOWS}
{$APPTYPE CONSOLE}
{$ENDIF}
uses
{$IFDEF MSWINDOWS}
CRT32 in 'CRT32.pas', EsConsole in 'EsConsole.pas';
{$H-}
{$ELSE}
crt;
{$ENDIF}
begin
Clrscr;
Writeln('Hello world!!!');
readkey;
end

Теперь приложение работает под Delphi и TP

The end.

Вернуться к оглавлению

5 комментариев к “Переносим программы с Turbo Pascal на Delphi”

Комментарии

  1. Отличная статейка. Много раз такое делал но немного по другому. У вас это более эффективно код компактнее выглядит.

  2. AlexR

    Можно и реализовать, за небольшую плату…
    =)

  3. VlaDoS

    Ребят, кто может такой модуль реализовать..?

    Реализовать в виде модуля набор подпрограмм для выполнения следующих операций со строками
    1)Процедура удаления из строки всех символов* и подсчёта количества удалений
    2)Процедура замены в строке символа* на символ+
    3)Функция определения сколько раз в строке встречается заданное слово

  4. Eek

    Отличная статья! Спасиб, скачал прям готовый модуль!

  5. Vbif!!!!

    \На 64 разрядной платформе компилироваться будет, если убрать {$IfDef Win32}, но работоспособность мной не проверена.\

    Delphi ВООБЩЕ не может компилировать для WIN64, не проверил он, блжад.

Комментарии