Recentemente, comecei a trabalhar em Delphi e descobri que muitos pacotes eram usados no programa original, mas eu estava sempre em um estado ignorante. Pode levar algum tempo para estudar esse problema. Portanto, liste primeiro as perguntas que precisam ser analisadas:
O que é uma bolsa? O que é um exe? Quais são suas diferenças de composição? Qual é a relação entre o pacote e a DCU? O que o DCP faz? Qual é a relação entre esses arquivos na hora da compilação? Como é carregado? Como operar o pacote após o carregamento? A DLL pode exportar, mas por que o Delphi não ajuda a trazer as exportações do pacote, mas alguns usos de código são executados no pacote?
Primeiro, vamos dar uma olhada no processo de compilação da Delphi. Existem dois tipos de projetos em Delphi: pacotes e programas. Comece com um simples, vamos começar com o DPR. De acordo com a documentação de ajuda de Delphi, a estrutura de um arquivo DPR típico é o seguinte:
1 editor de programas;
2
3 usos
4 formas, {altere para Qforms em Linux}
5 Reabrot em 'reabout.pas' {aboutbox},
6 permanecem em 'permanecem.pas' {mainform};
7
8 {$ r *.res}
9
10 Comece
11 Application.Title: = 'Text Editor';
12 Application.CreatEform (tmainform, Mainform);
13 Application.Run;
14 fim.
Entre eles, 10 a 14 linhas, começam ... o fim é naturalmente a entrada de execução do programa. A parte de usos indica algumas unidades que o programa precisa usar, o que é bastante vago. precisar? Em seguida, cada unidade usará outras unidades, e esse problema parece estar ficando cada vez mais complicado. Vejamos a estrutura de todo o código -fonte primeiro:
Eu acho que a primeira etapa do compilador é atravessar esse gráfico direcionado, compilar cada unidade, se necessário, e gerar o DCU correspondente. Quanto a essa questão "necessária", inicialmente pensei que a declaração de uso da unidade estava, mas depois descobri que estava errado. Porque no caso acima, a unidade3 não especifica o caminho na cláusula de uso da unidade1, mas o arquivo DCU correspondente ainda é gerado corretamente. Posteriormente, Filemon é usado para monitorar a situação de abertura do arquivo, e o processo de descoberta é o seguinte: para cada nó no gráfico, o compilador pesquisa os nós correspondentes no caminho de pesquisa no diretório atual - atributo do projeto - caminho da biblioteca na biblioteca Ambiente.
Agora que a compilação é feita, cada unidade (ou seja, o arquivo PAS) gerou o arquivo DCU para ele. Quando se trata de conexões, o problema é complicado. A conexão estática significa combinar todo esse DCU. Dessa forma, a chamada de uma unidade para outra unidade se torna uma questão interna do programa. Esse benefício é que é rápido e simples, e problemas como compartilhamento simultâneo são fáceis de lidar. A desvantagem é que o programa de destino é grande e, se outro programa for escrito agora e a unidade3 pode ser reutilizada, a unidade3.dcu será copiada novamente quando conectada. Dessa forma, quando dois programas são executados ao mesmo tempo, haverá duas cópias da unidade3 na memória, o que é um desperdício. A conexão dinâmica significa que, quando dois programas se conectam, eles mantêm apenas referências à unidade3 e não copiam o conteúdo da Unit3. Em tempo de execução, carregue a unidade3 na memória e torne os dois programas comuns. DLL e BPL são soluções para conexões dinâmicas. O problema é que a única opção de conexão em Delphi aparece no menu do projeto | Opções | Então, precisamos estudá -lo novamente.
Quando o programa é executado, podemos usar o View | Debug Window | Moudles para ver o que as coisas são carregadas na memória e qual o conteúdo elas contêm.
Para ser simples, configuramos um programa com a seguinte estrutura:
Programa ProjectEXE;
usos
Formas,
Windows,
UnitFormMain em 'UnitFormMain.pas' {formmain};
{$ R *.res}
Começar
Application.initialize;
Application.CreatEform (TFormMain, FormMain);
Application.run;
fim.
unidade unitFormMain;
interface
usos
Windows, stdctrls, formulários, unidades de formação, classes, controles;
tipo
TFormMain = classe (tform)
Button1: tbutton;
Procedimento Button1Click (remetente: Tobject);
Privado
{Declarações privadas}
público
{Declarações públicas}
fim;
var
FormMain: TFormMain;
Implementação
{$ R *.dfm}
procedimento TFormMain.Button1Click (remetente: TOBJECT);
var
LFORM: TFormanOther;
Começar
Lform: = tFormanother.create (aplicação);
Lform.showmodal;
Lform.free;
fim;
fim.
unidade de unidade;
interface
usos
Formas;
tipo
TFormanOther = Class (TForm)
Privado
{Declarações privadas}
público
{Declarações públicas}
fim;
Implementação
{$ R *.dfm}
fim.
Vamos receber as notícias agora. "Build With Runtime Pacotes" é verificado e agora é encontrado que o arquivo ProjectEXE.EXE de tempo de execução contém apenas quatro partes: dois formulários, um sysinit.pas e um projectexe.dpr; Na árvore do processo: RTL60 e VCL60, seu conteúdo são as unidades que apareceram na conexão estática agora. ProjectExe.exe tem apenas 16k agora. Em outras palavras, parte da unidade no gráfico direcionada é colocada no EXE e a outra parte é colocada no BPL. Mas em que a divisão é baseada? É baseado na cláusula de uso, ou com base na lista em "Build With Runtime Pacotes" aqui? Continuando o teste, descobri que, se a lista contiver apenas VCL60, os dois BPL mais um exe carregado na memória ainda serão carregados na memória; O EXE mudou: o número de unidades dentro aumentou e elas estão basicamente no pacote VCL60. Eu acho que deve haver um relacionamento de requisito entre os pacotes RTL e VCL. Isso será testado na próxima etapa. No entanto, durante o processo de estimativa inicial, a lista de pacotes será definitivamente usada para excluir unidades que já existem no pacote do exe.
Após a conexão dinâmica, há outro problema: carregando. Existem duas estratégias para carregar, estática, também conhecida como automática, que gera código da Delphi e carrega automaticamente o pacote antes de carregar o EXE; IT. O problema é que eu tenho que descobrir em que circunstâncias o Delphi carregará automaticamente um pacote e, em que circunstâncias, posso evitar que Delphi seja inteligente para que eu possa usar o pacote com flexibilidade. No experimento anterior, só pode -se ver que antes do arquivo DPR ser executado para começar, o pacote estaticamente conectado foi carregado na memória. Não conheço o processo específico.