Sign in Join
Wiki copytemporary

Code Conversion Guide/pt

Deutsch · English · Español · Français · Português · Slovenčina · Русский · 日本語

Guia de conversão do Delphi para o Lazarus

Sobre

Esta página é sobre como converter um código para poder usá-lo no compilador Free Pascal e a IDE do Lazarus. O Lazarus e o Free Pascal tem aspectos em comum com o Delphi e Kylix, porém, não são clones. Há várias diferenças nos códigos e convenções... e em algumas áreas, o FPC pode exigir uma sintaxe mais correta. Por favor veja o guia Lazarus For Delphi Users para uma descrição de algumas das diferenças funcionais.

O propósito deste guia é documentar algumas das diferenças específicas que freqüentemente são encontradas durante o processo de conversão de código ao traduzir código existente de Delphi para Lazarus.

Este documento foi colocado na área de conhecimento-base de wiki para que assim pudesse ser ampliado facilmente por qualquer um que tenha encontrado um problema e gostaria de postar isto para outros estarem atentos

Selecionando um componente ou biblioteca para conversão

Onde achar conteúdo para converter

Há MUITOS códigos possíveis na internet de serem convertidos para serem usados com o FPC e o Lazarus. Aqui tem uma Page Of Code Sites por onde você pode começar. Por favor adicione outro link se encontrar algum outro local. TurboPower Software recentemente seus produtos comerciais sob a MPL. Uma lista de packages disponíveis pode ser encontrado aqui.

Para evitar retrabalho, packages que foram convertidas estão listadas em Components and Code examples Se você converteu uma package ou está convertendo, por favor adicione uma nota na página Current conversion projects

Licenciamento

Licenças para a faixa de domínio de código existente freeware/domínio público para versões restritivas que proíbem a modificação, re-distribuição e uso comercial. Antes de converter qualquer pacote, é uma boa idéia analisar seu licenciamento e ter a certeza que ele vai ser compatível com o Lazarus e o compilador Free Pascal. Verificação de licença é especialmente importante com componentes, de vez que ao incorporar um a um formulário, isso pode impor a necessidade de obter uma licença, o que pode ser indesejável ​​ou incompatível para o aplicativo inteiro.

Ao converter componentes, por favor, respeite os desejos do autor original e mantenha todos os direitos autorais e cabeçalhos de licenciamento junto com endereços de e-mail e url's. É cortês e, muitas vezes útil para informar o autor que a sua componente está sendo (ou foi) convertida... especialmente se o componente está sob uma licença restritiva. Novo interesse em um antigo ou esquecido componente, pode às vezes inspirar autores a revisar seus originais e excessivo licenciamento restritivo.

Em geral, Domínio Público (freeware), e o LGPL/MPL são as formas de licenciamento mais flexível para a distribuição de componentes. Para mais informações, o site Open Source Definition é um bom lugar para iniciar. Há também diversas comparações disponíveis para ajudar a esclarecer como os vários tipos de licenças de trabalho e qual o impacto que terá sobre o código que está sendo vinculado. Procure por "open source license comparison"

Dependências

Outro passo antes de começar a trabalhar em uma conversão é verificar se o código não tem dependências profundas de outros pacotes que podem não estar disponíveis ou representam um desafio considerável de conversão. Algumas ofertas de freeware obrigam ou se estendem a pacotes proprietários que freqüentemente não estão disponíveis ou vêm com licenças inadequadas.

Questões de Compilador

Atualmente a versão estável 1.0.x do compilador Free Pascal não suporta interfaces, threads ou registros Variant. Se o código que você está convertendo necessita desses construtores, você terá que usar o ramo de desenvolvimento 1.1 do compilador ... que não é sempre garantido para trabalhar com Lazarus.

Veja também:

SO e problemas de plataforma

Lazarus e o compilador Free Pascal são cross-platform e ferramentas de desenvolvimento para serem usadas também em vários sistemas operacionais. Em contraste, a maioria dos códigos escritos em Delphi são especificamente escritos para rodar em um processador Intel sob Win32. Se o seu canditado a componente possui muito código específico da plataforma Win32, seria sábio procurar uma alternativa independente da plataforma. Mas não desista... é verdadeiramente incrível o suporte LCL.

Fazendo a conversão

Montando o ambiente de Lazarus para um projeto de conversão

Crie um projeto teste

Termos iniciais para se cuidar

Fontes Delphi VCL, Kylix CLX no Lazarus

Ao converter fontes de Delphi/Kylix, é freqüentemente útil fazer uma declaração sobre o que uma função específica está fazendo. A IDE Lazarus pode analisar as fontes de Delphi/Kylix. Para isto, é necessário indicar o local dos arquivos para o compilador. Pode-se conseguir isso através do menu Environment->CodeTools Defines Editor->Insert Template

Problemas de conversão e soluções

Arquivos Delphi / Kylix equivalentes no Lazarus

Delphi / Kylix Lazarus Descrição
.pas .dfm / .xfm .dcu / .dpu .dpr .res .dof / .kof --- --- --- .pas, .pp .lfm .o .lpr --- --- .lrs .lpi .ppu Arquivo unit de Pascal Arquivos de dados do form Arquivo da unit compilada Arquivo do Projeto Arquivo de recursos Arquivo de opções do projeto Arquivo de recursos do Lazarus Arquivo de informações do projeto Arquivo de descrição de unit FPC

Contentendo projetos/forms/units Delphi para Lazarus

Renomeie ou copie o arquivo .dpr para um arquivo .lpr. Comente ou remova a diretiva

{$R *.res}

e adicione

{$mode delphi}{$H+}

ou

{$mode objfpc}{$H+}

no arquivo .lpr. A IDE do Lazarus pode através do menu Tools no item "Convert Delphi Project to Lazarus Project". Ele solicita um arquivo .dpr (Delphi Project) e o converte para um .lpr; mais tarde, também cria um .lpi.

Existe várias maneiras de converter forms do Delphi através da IDE do Lazarus que realiza o trabalho da conversão do .dfm para o .lfm. Isso pode ser encontrado como item do menu Tools com o sob o nome "Convert DFM file to LFM". Clique nele, e na caixa de dialogo escolha seu arquivo .dmf e o conversor fará o resto.

Se você precisa converter a unit inteira (com ou sem um form), o Lazarus também inclui a opção de converter uma unit Delphi para uma Unit Lazarus, através do item "Convert Delphi unit to Lazarus unit" que fará o seguinte:

  1. renomeiará os arquivos .pas and .dfm para minúsculas.

  2. converterá .dfm para .lfm file (atualmente sem a verificação da validade do conteúdo; somente o formato)

  3. criará um arquivo .lrs vazio (o conteúdo será adicionado mais tarde)

  4. adicionará a diretiva {$mode delphi}

  5. substituirá as unidades Windows por LCLIntf

  6. adicionará units LResources se necessário (i.e., se o unit.lrs for usado; o uso de LResources

    pode ser implementado a parte)

  7. removerá variáveis da unit

  8. removerá a diretiva {$R *.dfm}

  9. adicionará a seção de inicialização e a diretiva {$i unit.lrs}

Isto fará uma conversão rápida e fácil da maioria das Units Delphi ao formato do Lazarus. Isto não checa a validade, ou muda a sintaxe automática. Assim, qualquer mudança na sintaxe, mudanças adicionais nos nomes das Units, mudanças necessárias por causa de diferenças nos objetos/controles, você terá que fazer manualmente.

Selecting the right compiler mode

The Free Pascal Compiler supports 5 different pascal modes. For example TP for turbo pascal, lets you compile turbo pascal units. There is also a DELPHI compatibility mode that can be set to make existing code easier to convert. Lazarus prefers the OBJFPC mode, which almost equals the DELPHI mode, but is less ambigious than the Delphi syntax. Here are the important points:

The mode can be selected at command line or at the start of the source. Using the command line has the advantage, that you don't need to change the source, but the disadvantage, that others must be told.

Most Delphi units can be compiled by the Free Pascal compiler by adding

text
{$IFDEF FPC}
  {$MODE DELPHI}
{$ENDIF}

right after the unit name.

For more details about Free Pascal modes see the Free Pascal Documentation

Cross-Platform considerations

Useful compiler variables

To write code, that behaves on different systems differently, you can use the

{$IFDEF Name}

directives.

This variable is defined, when using the LCL package. Useful to write code, that works with the LCL and Delphi.

This variable is defined, when using the FPC compiler. Useful to write code, that works with FPC and Delphi.

Defined by FPC for the current Target OS. Delphi defines "Linux", "Win32" and "MSWindows". Free Pascal runs on much more platforms and so it is recommended to use the more general items. For example "Unix" is defined for Linux, FreeBSD, NetBSD and OpenBSD, where Lazarus already runs. Use

text
{$IfDef Linux}
  {$Define Unix}
{$EndIf}

to work around this for Kylix.

For more details see the Free Pascal Documentation.

Finding a missing identifier

There are differences in how the LCL is organized when compared to the Delphi VCL. If you get a "not found" compiler error about a major class or identifier, the chances are good that it's in a different unit. A complete cross reference can be found by grep'ing lazarus/docs/xml or the lcl subdirectory.

For example the commonly used tbutton typically throws an error in Delphi code because it's located in a unit named buttons.pp. The following command finds the correct unit very quickly (in the lazarus source directory):

text
 grep -in ' tbutton =' lcl/*

Major unit differences between Lazarus and Delphi

As the LCL is not windows specific, the code that is in the Delphi Windows unit for directly accessing the Win32 API is abstracted into seperate interfaces, which can be accessed from the LCLIntf unit. Keep in mind, that Lazarus does not emulate win32, so many functions are missing and some do not work as their win32 counterparts. These functions only exist for Delphi compatibility and should only be used for quick & dirty porting. LCL also breaks out many of the types, so often LCLType, and sometimes VCLGlobals are required. LCLProc also contains a few functions which can be useful for lower level handling such as "FreeThenNil" as is in Delphi 5 and higher, "DeleteAmpersands" to remove additional ampersands from a string for controls(& vs && etc). The Interfaces unit needs to be included in the .lpr file to initialize the appropriate widgetset.

TControl Messages for win32 event callbacks of the format WM_CALLBACK and the structs associated with them are often found in the Messages unit in Delphi. In the LCL these types of messages and there structs are usually found in LMessages, usually with name changes of WM to LM, so for instance WM_MOUSEENTER becomes LM_MOUSEENTER, and TWMMouse becomes TLMMouse.

To simplify some things and break complexity of circles between units, a few types have been abstracted into a shared unit called GraphType, which includes things, which in Delphi are located in Graphics or Controls, for instance the bvNone etc of panels. So sometimes you have to include it. Also a unit which, although incompatible with Delphi, adds other useful functionality is GraphMath, which adds a TFloatPoint for precision, misc routines for dealing with beziers, lines, and arcs, as well as some operator overloading for use with TPoints and TRect, such as for instance Point1 := Point2 + Point3, and comparing two rects like if (rect1 = rect2) then ...

For more intelligent naming considerations, the unit for TMaskEdit is called [MaskEdit|] instead of the slightly more nebulous Mask as in many versions of Delphi.

In many version of Delphi TButton is located in StdCtrls, while TSpeedButton and TBitBtn are in Buttons. For consistency and simplicity the LCL puts all button types in Buttons, which can occasionally break code conversion, so it is always a good idea to include.

Property and method differences Delphi -> FPC/LCL

Syntax differences

Please add to this topic!

Because of the inherent strictness in FPC, some syntax changes are necessary, even though

{$Mode Delphi}

does allow more laziness like Delphi does. For this reason complying as much with the syntax rules of

{$Mode ObjFPC}

as possible is highly recommended, even when the codebase is still going to be shared between Delphi and the LCL. Some of these are simply better coding practices, and sometimes because Delphi mode is not entirely accurate, or in a few instances Delphi acceptible code does not function as expected with FPC, even though it might compile. To that end even though not all such are strictly required, the following list of changes should be considered mandatory :

When assigning an event handling entry point, prefix it with an "@"

For instance, you might assign a button callback manually

Delphi

FPC

begin

if not

Assigned(MyButton.OnClick)

then

    MyButton.OnClick:= SomeFunction; 

//@ not required

//more code...

end

;

begin

if not

Assigned(MyButton.OnClick)

then

    MyButton.OnClick:= @SomeFunction; 

//@ IS required

//more code...

end

;

When calling a procedure variable use this syntax
theprocname()

In Delphi there is no difference between a function result and a variable, however there is in FPC, so to call a function, even if it has no parameters, you must append parenthesis. For Example -

Delphi

FPC

With

(SomeObject)

do begin

If

Assigned(OnMyCallback)

then

    OnMyCallback; 

//parenthesis not required

end

;

With

(SomeObject)

do begin

If

Assigned(OnMyCallback)

then

    OnMyCallback(); 

//parenthesis required

end

;

When accessing values in a pointer to a record you must dereference first

In Delphi it is not required to de-reference a pointer to a record to access values within it, it can, in fact, be treated just like the record itself, or any other object. In FPC it must be first de-referenced. As an example,

Delphi

FPC

Function

GetSomeValue(ARecord: PMyRecord)

Integer;

begin

If

Assigned(ARecord)

then

    Result

=

ARecord.SomeValue

else

    Result:= 

0

;

end

;

Function

GetSomeValue(ARecord: PMyRecord)

Integer;

begin

If

Assigned(ARecord)

then

    Result

=

ARecord^.SomeValue

else

    Result:= 

0

;

end

;

When accessing chars of an indexed string Property of an object, it must be enclosed in parentheses

With Delphi it is possible to treat a Property exactly like some other const or var, even to accessing for instance individual chars of a string directly, while this is not always possible in FPC, specifically for indexed properties. Instead it must be enclosed in parentheses, to make distinct. While this may not always hold true it is probably a good practice to consider anyway. For example

Delphi

FPC

Type

TSomeComponent=

class

(TComponent)

//More code...

Published

Property

MyString:

String

index

3

read

GetMyString;

//More code...

End

;

var

  MyChar

char;

begin

If

Length(MyString)>

2

then

//no parenthesis needed

    MyChar:= MyString[

3

];

//More code...

end

;

Type

TSomeComponent=

class

(TComponent)

//More code...

Published

Property

MyString:

String

index

3

read

GetMyString;

//More code...

End

;

var

  MyChar

char;

begin

If

Length(MyString)>

2

then

//parenthesis sometimes needed

    MyChar:= (MyString)[

3

];

//More code...

end

;

You must typecast pointers to actual type when using with var or function of that type

Sometimes in Delphi you will have a null pointer variable representing an object. While it might seem a complex situation, it is oddly quite common especially in large component packs as a method of preventing too many circular includes between objects in different units. In Delphi it is then possible to send this null pointer to a function expecting that object, without bothering to typecast to actual type, in fpc you must typecast.

For example -

Delphi

FPC

Unit 1

Type

TSomeObject=

class

(TComponent)

//More code...

End

;

Procedure

DoSomething(Value: TSomeObject);

Function

GetSomeObject: TSomeObject;

Unit 2

Type

TSomeComponent=

class

(TComponent)

//More code...

Published

  SomeObject: Pointer

;

//More code...

End

;

Application

var

  MyComponent: TSomeComponent

;

begin

  MyComponent.SomeObject

=

GetSomeObject;

//More code...

  DoSomething(MyComponent.SomeObject)

;

end

;

Unit 1

Type

TSomeObject=

class

(TComponent)

//More code...

End

;

Procedure

DoSomething(Value: TSomeObject);

Function

GetSomeObject: TSomeObject;

Unit 2

Type

TSomeComponent=

class

(TComponent)

//More code...

Published

  SomeObject: Pointer

;

//More code...

End

;

Application

var

 MyComponent: TSomeComponent

;

begin

  MyComponent.SomeObject

=

Pointer(GetSomeObject);

//More code...

  DoSomething(TSomeObject(MyComponent.SomeObject))

;

end

;

Resources

Delphi resource files are win32 specific and not compatible with Lazarus, so you'll have to recreate and compile them using the lazres. Lazres can be found in the lazarus/tools subdirectory. If you've downloaded the Lazarus sources, you'll need to compile it first.

To add a resource to your application:

Example:

function

TForm1.LoadGlyph(

const

GlyphName:

String

): TBitMap;

begin

  Result:= TPixmap.Create

;

  Result.LoadFromLazarusResource(GlyphName)

;

end

;

//More code...

begin

  Speedbutton1.glyph:= LoadGlyph('mypix')

;

//More code...

end

;

initialization

{$I unit1.lrs}

{$I myresource.lrs}

end

.

Another method to convert a Delphi or Kylix project to Lazarus

  1. Add {$mode delphi}{$H+} or {$mode objfpc}{H+} directives
  2. Add 'Interfaces' to uses clause
  3. Comment out or delete {$R *.res} or directive
  1. Add {$mode delphi}{$H+} or {$mode objfpc}{H+} directives
  2. Add 'LResources', and if the form has buttons, add 'Buttons' to uses clause
  3. Comment out or delete {$R *.dfm} or {$R *.xfm} directive
  4. Add 'Initialization' section at the end of each unit file, and add {$I unitname.lrs} directive in it

Getting Help

If you encounter a problem during conversion that you just can't solve, there are a wide variety of places to get help. For pure Object Pascal and FPC issues, the best place to start is the Free Pascal Documentation by Michaël Van Canneyt and Florian Klämpfl. For more Lazarus oriented problems, the Lazarus Project Documentation in the Lazarus-CCR Knowledgebase [Main Page] is the next place to look. Finally you can post a question on any of the mailing lists for the Free Pascal Compiler or the FPC forums where a lot of experts are subscribed.

There are some outstanding search and knowledge bases online that can also be a great help for learning new techniques and solving problems. Tamarack Associates operates a fast search engine specifically for the Borland usenet archives. Mer Systems Inc. provides a similar search engine. Another outstanding source of information along with a sitewide search capability is Earl F. Glynn's Computer Lab and Reference Library.

Packaging and Releasing your component

Creating a Lazarus package for your component(s)

Creating a package makes installing the code you've converted a much easier process... especially if you're providing more then one component. Mattias Gärtner has written an overview of Lazarus Packages that should be read before beginning this process.

Documentation

The purpose of this site and the wiki format is to make the generation of professional documentation an easy and quick process. The wiki also makes it possible to see the results of your posting immediately and make any changes you'd like in real time.

Using the Lazarus-CCR wiki to create nice looking documentation is very easy. If you've never used wiki markup before, you can get familiar with it in the Sand Box practice area.

Creating a Code Release Page

The Code Release Page contains vital information about your component that a potential downloader will need to know, such as license, intended platform, status (alpha, beta, stable...), where to download it, who wrote it, is support available... etc.

The following procedure will let you create a Code Release Page with your browser:

Submitting the component

If you're a release technician on the project, upload your component to the SourceForge File Release System and add it to the list of release packages. Otherwise send it to one of the project administrators (Tom Lisjac or Vincent Snijders) and we'll add it to the repository.

If you think you need to continue to develop on the component, we can also put it into CVS so you'll continue to have access to it.

Contributors and Changes

This page has been converted from the epikwiki version.


From the Free Pascal wiki, page "Code Conversion Guide/pt", as it stood on 2012-01-12 after a change by Jrxds, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's Licensing page. If you have concerns about this material, message the admin.

Revision 4, last changed by WikiArchive .

Talk about this page

Nobody has opened a bench for this page yet. Sign in to open one.