GARANTIR DESCONTO

Fórum Erro ao usar DLL #344231

08/08/2007

0

Olá a Todos...

Pessoal tenho a seguinte dll:


library Biblio;

{ Important note about DLL memory management: ShareMem must be the
first unit in your library´s USES clause AND your project´s (select
Project-View Source) USES clause if your DLL exports any procedures or
functions that pass strings as parameters or function results. This
applies to all strings passed to and from your DLL--even those that
are nested in records and classes. ShareMem is the interface unit to
the BORLNDMM.DLL shared memory manager, which must be deployed along
with your DLL. To avoid using BORLNDMM.DLL, pass string information
using PChar or ShortString parameters. }

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, DB, Grids, DBGrids, Buttons, StdCtrls, Mask, DBCtrls, ExtCtrls,
ActnList, ComCtrls, FMTBcd, Provider, DBClient;

{$R *.res}

procedure LimpaCampos(vForm: TForm; vFormHandle: THandle);
var i : Integer;
begin

for i := 0 to (vForm.ControlCount -1) do
if vForm.Controls[i].ClassName = ´TEdit´ then
begin
TEdit(vForm.Controls[i]).Text:=´´;
end;

for i := 0 to (vForm.ControlCount -1) do
if vForm.Controls[i].ClassName = ´TDBEdit´ then
begin
TDBEdit(vForm.Controls[i]).Text:=´´;
end;

for i := 0 to (vForm.ControlCount -1) do
if vForm.Controls[i].ClassName = ´TCheckBox´ then
begin
TCheckBox(vForm.Controls[i]).Checked:= False;
end;

for i := 0 to (vForm.ControlCount -1) do
if vForm.Controls[i].ClassName = ´TDBCheckBox´ then
begin
TDBCheckBox(vForm.Controls[i]).Checked:= False;
end;

end;

Exports

LimpaCampos;

begin

end.



E no Form frmCadKits declaro a procedure e a dll.

...


public
{ Public declarations }
end;

procedure LimpaCampos(vForm: TForm; vFormHandle: THandle); external ´biblio.dll´;


var

...


E faço uma chamada no show do Form



procedure TfrmCadKits.FormShow(Sender: TObject);
begin

LimpaCampos(frmCadKits,frmCadKits.Handle);


end;


E recebo o erro:

Project Aplicativo.exe raised exception class EAccessViolation with message ´Access violation at address 045DF5B in module Aplicativo.exe´. Read of address 00000180´. Process stopped. Use Step or Run to continue.


Alguém tem uma solução, já tentei de várias formas e nada, sempre dá esse erro. No mesmo diretório da aplicação estão a biblio.dll e a borlndmm.dll.

Grato a todos.

Alexandre.


Alexandregois

Alexandregois

Responder

Posts

08/08/2007

Massuda

Do seu código fonte...
Important note about DLL memory management: ShareMem must be the first unit in your library´s USES clause AND your project´s (select Project-View Source)
Você incluiu a unit ShareMem como sendo a primeira unit no uses da DLL e do seu projeto?


Responder

Gostei + 0

08/08/2007

Emerson Nascimento

na verdade Massuda, lendo o texto completo, pode-se observar que o uso de ShareMem só é necessário se a dll criada exportar qualquer procedure que receba parâmetros string ou função que retorne strings, o que não é o caso (pelo menos no código apresentado).

[i:1fd0d20f93]{ Important note about DLL memory management: ShareMem must be the
first unit in your library´s USES clause AND your project´s (select
Project-View Source) USES clause [b:1fd0d20f93]if your DLL exports any procedures or
functions that pass strings as parameters or function results[/b:1fd0d20f93]. This
applies to all strings passed to and from your DLL--even those that
are nested in records and classes. ShareMem is the interface unit to
the BORLNDMM.DLL shared memory manager, which must be deployed along
with your DLL. To avoid using BORLNDMM.DLL, pass string information
using PChar or ShortString parameters. }
[/i:1fd0d20f93]
[color=blue:1fd0d20f93]tradução livre:[/color:1fd0d20f93]
[i:1fd0d20f93]{ Nota importante sobre gerenciamento de memória em DLL: ShareMem deve
ser a primeira unit na cláusula USES da sua biblioteca e na cláusula
USES do seu projeto (selecione Project-View Source) se sua DLL exporta
procedimentos que passam strings como parâmetro ou retorno de função.
Isto aplica-se a todas as strings passadas para e da sua DLL -- até
aquelas dentro de registros e classes. ShareMem é a unit com a interface
para o gerenciador de memória compartilhada BORLNDMM.DLL, que deve ser
distribuído junto com sua DLL. Para evitar o uso da BORLNDMM.DLL,
passe as informações string usando parâmetros PChar ou ShortString. }[/i:1fd0d20f93]


[b:1fd0d20f93]teste com este código:[/b:1fd0d20f93]
library Biblio;

{ Important note about DLL memory management: ShareMem must be the
first unit in your library´s USES clause AND your project´s (select
Project-View Source) USES clause if your DLL exports any procedures or
functions that pass strings as parameters or function results. This
applies to all strings passed to and from your DLL--even those that
are nested in records and classes. ShareMem is the interface unit to
the BORLNDMM.DLL shared memory manager, which must be deployed along
with your DLL. To avoid using BORLNDMM.DLL, pass string information
using PChar or ShortString parameters. }

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, DB, Grids, DBGrids, Buttons, StdCtrls, Mask, DBCtrls, ExtCtrls,
  ActnList, ComCtrls, FMTBcd, Provider, DBClient;

{$R *.res}

procedure LimpaCampos(vForm: TForm; vFormHandle: THandle);
var
  i : Integer;
  classe: string;
begin
  // alterei, de forma a fazer a verredura apenas uma vez.
  // da forma que estava, se seu formulário tivesse 500
  // componentes, a sua dll iria avaliar 2.000 iterações,
  // pois faria uma varredura completa 4 vezes.
  // da forma que está agora essa varredura será feita apenas
  // 1 vez, aumentando a performace
  for i := 0 to (vForm.ControlCount -1) do
  begin
    classe := UpperCase(vForm.Controls[i].ClassName);

    if classe = ´TEDIT´ then
      TEdit(vForm.Controls[i]).Text := ´´
    else
    if classe = ´TDBEDIT´ then
      TDBEdit(vForm.Controls[i]).Text := ´´
    else
    if classe = ´TCHECKBOX´ then
      TCheckBox(vForm.Controls[i]).Checked := False
    else
    if classe = ´TDBCHECKBOX´ then
      TDBCheckBox(vForm.Controls[i]).Checked := False;
  end;
end;

exports
  LimpaCampos;

begin

end.


e execute a função como no exemplo abaixo:
procedure TfrmCadKits.FormShow(Sender: TObject);
begin
  LimpaCampos(Self, Self.Handle);
end;



Responder

Gostei + 0

08/08/2007

Massuda

lendo o texto completo, pode-se observar que o uso de ShareMem só é necessário se a dll criada exportar qualquer procedure que receba parâmetros string ou função que retorne strings, o que não é o caso (pelo menos no código apresentado).
Na verdade, as strings são passadas indiretamente através de componentes que estão no form (esse caso é previsto no texto padrão do Delphi: ´even those that are nested in records and classes´).

Note que o tratamento feito no edits que tem no form consiste em atribuir uma string vazia à propriedade Text; indiretamente, está retornando uma string vazia para o executável que está usando a DLL.


Responder

Gostei + 0

08/08/2007

Emerson Nascimento

Note que o tratamento feito no edits que tem no form consiste em atribuir uma string vazia à propriedade Text;
nos componentes de edição do delphi, a propriedade Text é do tipo TCaption, que é do tipo ´type string´, e não ´string´. e o fato de atribuir um vazio (var := ´´) não é necessariamente uma string, pois atribuições a variáveis PChar podem ser feitas dessa mesma forma.

indiretamente, está retornando uma string vazia para o executável que está usando a DLL.
humm... não sei... na minha interpretação nada é retornado, visto que não é uma função; é feita uma manipulação direta no valor, mas não há retorno de string. mesmo porque, como dito acima, não é necessariamente uma string.

mas posso estar errado....

obs.: os testes que eu fiz funcionaram perfeitamente sem precisar adicionar ShareMem


Responder

Gostei + 0

08/08/2007

Massuda

Provavelmente isto resolve problema...
e execute a função como no exemplo abaixo:
procedure TfrmCadKits.FormShow(Sender: TObject);
begin
  LimpaCampos(Self, Self.Handle);
end;
...pois tem grande chace desse form estar sendo criado com Visible = True e o Show é executado durante a criação do form, de modo que frmCadKits ainda é nil.

Com relação ao ShareMem, acredito que neste caso deveria incluí-la no uses. Se tiver tempo, dou uma investigada nisso.


Responder

Gostei + 0

08/08/2007

Emerson Nascimento

Provavelmente isto resolve problema...

até porque, em função de como o form foi instanciado, a variável frmCadKits pode não ter sido atribuída.
um caso em que isso pode acontecer é se o form foi criado assim:
Application.CreateForm(TfrmCadKits, frmCadastraKits)
no caso, apesar de ser uma instância de TfrmCadKits, a variável ´criada´ será frmCadastraKits e não frmCadKits. o uso de Self evita esse tipo de problema.

Se tiver tempo, dou uma investigada nisso

:D


Responder

Gostei + 0

09/08/2007

Alexandregois

Testei todas as opções passadas e nada. A procedure não executa e o erro agora acontece na saída do aplicativo, seguindo o que o emerson.en passou.

Alexandre.


Responder

Gostei + 0

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.

Aceitar