Instanciar HModule e não liberar
19/05/2008
0
(resumidamente, sem os tratamentos)
... var modulo : Hmodule; proc : procedure; modulo := LoadPackage(´modulo.bpl´); @proc := GetProcAddress(modulo, ´ProcedimentoExportado´); proc; end;
acontece que o modulo pertence ao escopo deste procedimento (onclick por exemplo) e o mesmo é liberado ao término da execução (aparentemente).
no meu caso eu preciso carregar vários modulos, mas não tem um número fixo, o que eu não poderia declarar N variávels do tipo HModule, pois esse numero vai variar.
Pensei em usar um array, mas não sei se é correto; ou ponteiros?
abraços
Eniorm
Posts
20/05/2008
Massuda
20/05/2008
Eniorm
por exemplo esse modulo : HModule, eu armazeno o handle dele (cardinal) num stringlist
ao termino do programa eu libero manualmente assim
if (Modulo <> Nil) then
UnLoadPackage(Modulo)
no entando se eu omitir o if e usar UnLoadPackage diretamente da erro pois o módulo foi liberado.
isso só funciona com as variaveis hmodule declaradas por exemplo na sessão public de minha unit, elas permanecem instanciadas até o termino do meu programa, já as declaradas dentro do escopo no meu procedimento essas depois da execução do procedimento nao permaneceram instanciadas
abraços
20/05/2008
Massuda
20/05/2008
Eniorm
então rsrsrs :D é esse mesmo o meu problema até o momento eu não cheguei numa conclusão o que seria melhor usar uma lista ou um array dinâmico,
estou pesquisando como trabalhar com tais listas/arrays e confesso que estou apanhando um pouco.
nao sei ainda como ir adicionando dinamicamente cada modulo no array
abraço
20/05/2008
Emerson Nascimento
if (Modulo <> Nil) then
UnLoadPackage(Modulo)...[/quote:bebc1b283c]
quando você diz ´ao término do programa´, você quer dizer do programa mesmo ou o uso do pacote?
21/05/2008
Eniorm
Outro detalhe: eu uso forms MDI
fiz um teste ontem e notei que
1- após abrir o programa, e carregar o modulo e disparar o evento, eu consigo por exemplo trocar o nome ou até apagar o modulo carregado
2- apos, posso chamar novamente o evento que continua abrindo o form, mesmo o modulo ter sido apagado.
rsrsrs
21/05/2008
Emerson Nascimento
tem certeza que seu projeto está modularizado?
se você fechar o sistema (estando o bpl apagado) e abri-lo novamente, ao chamar o form que deveria estar no bpl, ainda assim ele abre?
entendeu o que eu disse?
1 - feche o sistema
2 - apague o bpl
3 - abra o sistema
4 - execute a opção que abre o form
funciona?
21/05/2008
Eniorm
rsrsrs sim, está modularizado, o único vinculo que existe em a aplicação principal e os módulos é o [b:f81b9033f4]LoadPackage[/b:f81b9033f4]
ai não, da erro na hora do LoadPackage pois não consegue localizar o pacote.bpl...
o estranho é que se seguir essa ordem, funciona:
1) abro o programa, clico no item de menu que abre um form que fica dentro do modulo.bpl. Os códigos são usados os que acima eu informei, resumidamente.
2) tanto faz eu deixar aberto ou fechar este form, eu posso ir na pasta onde está o exe e os bpls que eu consigo renomear ou apagar o modulo.bpl
3) o item do menu continua funcionando mesmo com o bpl excluído.
4) se eu fechar o programa, ai na proxima vez gera o erro caso o pacote não estiver presente.
a variável onde eu instancio o HModule pertence ao escopo da implementação do evento OnClick deste item de menu. A variável tipo procedure tbm pertence a este escopo.
muito estranho, não? rsrsr
03/06/2008
Eniorm
amigos, achei uma solução da seguinte forma para o meu problema,
... type TModulo = record Bpl : String; Modulo : HModule; end; var ModulosCarregados : array of TModulo; ...
dessa forma eu tenho um vetor dinâmico do meu tipo TModulo...
[b:bd1ef9aa94]cada módulo é instanciado assim:[/b:bd1ef9aa94]
procedure AbreModulo(Bpl : String); var I, Posicao : SmallInt; begin // pra saber se o modulo já foi instanciado Posicao := -1; for I := Low(ModulosCarregados) to High(ModulosCarregados) do if (ModulosCarregados[I].Bpl = Bpl) then Posicao := I; // instancia caso não tenha encontrado if (Posicao = -1) then begin I := Length(ModulosCarregados); SetLength(ModulosCarregados,I+1); ModulosCarregados[I].Bpl := Bpl; ModulosCarregados[I].Modulo := LoadPackage(Bpl); end; end;
[b:bd1ef9aa94]para abrir um método implementado dentro de um módulo bpl eu faço assim[/b:bd1ef9aa94]
procedure CarregaMetodo(Bpl, Metodo : String; var Implementacao : Pointer); var I, Posicao : SmallInt; begin // novamente pra saber a posicao do modulo no vetor Posicao = -1; for I := Low(ModulosCarregados) to High(ModulosCarregados) do if (ModulosCarregados[I].Bpl = Bpl) then begin Posicao := I; Exit; // para sair do IF e do LAÇO ??? end; // agora eu carrego o método solicitado if (Posicao > -1) then implementacao := GetProcAddress(ModulosCarregados[Posicao].Modulo,Metodo); end;
[b:bd1ef9aa94]no momento em que eu preciso abrir um método eu faço:[/b:bd1ef9aa94]
[i:bd1ef9aa94]por exemplo no onClick qualquer[/i:bd1ef9aa94]
... var proc : procedure; begin AbreModulo(´clientes.bpl´); CarregaMetodo(´clientes.bpl´,´cadastroclientes´,@proc); proc; end;
analisando a implementação dos métodos AbreModulo e CarregaMetodo da pra ver que pode ser melhorado.
Eu uso o FOR para pesquisar pelo vetor pois não sei se o Delphi existe alguma função ou procedimento mais útil para pesquisar itens num vetor.
nos códigos acima eu, para resumir, não inclui os tratamentos de exceções que por ventura possa acontecer caso dê algum erro na hora de carregar o módulo ou uma tentativa de chamada de método inexistente.
Espero que possa ajudar os outros necessitados rsrsrsrs :D
Clique aqui para fazer login e interagir na Comunidade :)