Instanciar HModule e não liberar

19/05/2008

2

O problema é que, ao carregar um módulo eu faço assim:

(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


Responder

Posts

20/05/2008

Eniorm

sobe


Responder

20/05/2008

Massuda

Não entendi... você está afirmando que modulo.bpl está sendo liberado porque modulo:HModule saiu de escopo? Isso não acontece.


Responder

20/05/2008

Eniorm

pelo que aprendi, as variáveis declaradas num escopo, por ex, no onclick, ao terminar essas variáveis são liberadas...

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


Responder

20/05/2008

Massuda

[quote:9567b038d0=´Enio Marconcini´]já as declaradas dentro do escopo no meu procedimento essas depois da execução do procedimento nao permaneceram instanciadas[/quote:9567b038d0]Sim, são variáveis locais que saem do escopo quando termina a função. Se você quer armazenar o HModule das BPLs que carregar, você precisa manter uma lista ou array (dinamico) que deve ser um membro da classe ou uma variável global da unit ou programa.


Responder

20/05/2008

Eniorm

você precisa manter uma lista ou array (dinamico) que deve ser um membro da classe ou uma variável global da unit ou programa.


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


Responder
[quote:bebc1b283c=´Enio Marconcini´]...ao termino do programa eu libero manualmente assim

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?


Responder

21/05/2008

Eniorm

qdo o programa é encerrado mesmo.

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


Responder
você diz que consegue apagar fisicamente o arquivo bpl? e ainda assim o form contido nele é aberto?

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?


Responder

21/05/2008

Eniorm

tem certeza que seu projeto está modularizado?


rsrsrs sim, está modularizado, o único vinculo que existe em a aplicação principal e os módulos é o [b:f81b9033f4]LoadPackage[/b:f81b9033f4]

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?


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


Responder

26/05/2008

Eniorm

up... :D


Responder

03/06/2008

Eniorm

wana-wanga!!!

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


Responder
×
+1 DevUP
Acesso diário, +1 DevUP
Parabéns, você está investindo na sua carreira