Packages na prática
Como se gera um package (.dll + .fxd), como um cliente o usa, as versões do formato e os erros típicos.
O que é e por que existe#
A página Packages e o .fxd explica a ideia (o equivalente do .bpl + .dcp do Delphi). Esta aqui é o lado prático: o que escrever, o que sai, como o cliente liga e o que dá errado.
Resumo da ideia: uma library exporta só o que está no exports e o cliente precisa escrever external … name … à mão. Um package exporta tudo o que é public e deixa um arquivo .fxd do lado, com tudo o que o compilador precisa para compilar um cliente: layout dos tipos, slots da VMT, assinaturas, constantes, o texto dos genéricos e os corpos inline.
Gerando um package#
O arquivo do package só lista os módulos que ele reúne; o corpo é vazio:
package GreeterPkg;
uses Greeter; // Greeter.fxm: um módulo com declarações public
begin
end.fc GreeterPkg.fxpEsse é o formato dos packages de teste do próprio compilador (package libm1322pk; uses …; begin end.). Saem: a DLL com o código, o .fxd (formato binário, serialização da árvore sintática), o .fxnames (o mapa de nomes dos símbolos) e a .lib de importação. Se o package precisa que o compilador exporte tudo (como a RTL faz), o fonte começa com {$config exportall on}.
Usando em um cliente#
No .config do cliente, LinkPackage liga um .fxd (nome-base, sem extensão); UnlinkPackage cancela um que veio de uma configuração acima; --NoPackages ignora todos numa compilação.
Config All LinkPackage ($ProjectPath)\..\GreeterPkgO cliente escreve uses Greeter; normalmente: o compilador resolve os tipos a partir do .fxd, e o programa em execução precisa da DLL ao lado. A RTL BedRock é o primeiro cliente do mecanismo (RtlPackage), com o .fxd dela.
Versões e erros#
O .fxd leva o número de versão do formato e a impressão digital do compilador que o gerou. O compilador atual escreve a v20 e lê da v17 à v20. A ordem das recusas ao abrir:
| Código | Situação |
|---|---|
FE1922 | versão do .fxd mais nova que a deste compilador: use um compilador mais novo, ou recompile o package |
FE1923 | versão anterior à v17: recompile o package com este compilador |
FE1489 | mesma versão de formato, mas escrito por outro build do compilador |
FE1490 | arquivo corrompido (as três acima não são isso) |
Na prática, um package feito por outra versão do fc aparece como erro de .fxd ou como símbolo não resolvido na ligação. Recompile o package com o fc que compila o cliente.
Classes, genéricos e tuplas atravessando#
- Herdar de classe do package funciona, inclusive de classe que implementa interface: o cliente que deriva (
TCli = class(TPkImpl)) ganhaSupports,ase a atribuição à interface (a partir do formato v20). Createde classe de package no cliente é recusado por padrão (FE0971): a instância seria alocada no gerenciador de memória do cliente e devolvida, na destruição, ao da DLL. O idioma é uma fábrica do package (MakeGreeter), com oFreeno cliente rodando o destrutor virtual na DLL. O package pode optar por{$config pkgcreate on}, que exporta o alocador e deixa o cliente darCreate(exige o.fxnamesao lado).- Genéricos viajam como texto no
.fxd(a monomorfização reparseia texto). O cliente adota a instância que o package já fez, se o texto for o mesmo, ou instancia sozinho. - Tuplas do package e do cliente passam a ser o mesmo tipo.
protectedé a visibilidade que existe para isso: visível entre os módulos do projeto, não exportada (Módulos).- Posições: o
.fxdpode levar uma seção opcionalFXPS(arquivo e linha de cada declaração) para o "ir para a definição" do editor chegar ao fonte do package. Sem o fonte, o editor mostraarquivo:linhamas não abre nada. Renomear um símbolo de package é sempre recusado pelo servidor de linguagem.
O que ainda não está decidido#
Segundo o desenho do compilador: a ordem de initialization entre vários packages (rodam no DllMain de cada um); a impressão digital conferida na carga da DLL (trocar a .dll por outra compilada de fonte diferente muda offsets e slots da VMT em silêncio); package que usa package (o requires do Delphi); e a poda (o que é público vira raiz, então escrever algo public num package tem custo).
Veja também#
- Packages e o .fxd, Configuração, Módulos.
- fc --lsp, para a navegação em símbolos de package.