Professional Documents
Culture Documents
Como voc deve saber, uma string longa no muito mais que um ponteiro para um local na
memria. Este local tem algumas informaes importantes a respeito da string, alm, claro, dos
caracteres armazenados no momento.
Por fim, existe o campo reference count, outro inteiro de 32 bits indicando o nmero de variveis
que esto apontando no momento para aquele local na memria. Isso permite ao Delphi fazer
algumas otimizaes na atribuio de variveis string.
Quando voc atribui um valor a uma varivel string, o Delphi normalmente aloca o espao em
memria necessrio ao armazenamento dos caracteres, preenche os campos que indicam o
comprimento e reference count e copia os caracteres para esse local na memria.
Quando a execuo sair do escopo da varivel (por exemplo sair da funo onde existe uma varivel
local do tipo string), o Delphi trata de zerar as variveis string e verificar se precisa desalocar o
espao onde os caracteres se encontram. Se precisar, utiliza a funo de desalocao do gerenciador
de memria.
O gerenciador de memria uma biblioteca (localizada na unidade System) que trata de alocao,
desalocao e realocao de memria no Delphi. Veja GetMem, FreeMem e ReallocMem para saber
mais sobre essas operaes.
O problema que um executvel host e as DLLs ligadas ele tm seus prprios gerenciadores de
memria. Uma poro de memria alocada em um deles no pode ser liberado em outro. Veja o
diagrama abaixo.
Apesar dos gerenciadores serem idnticos (ambos implementados na unidade System), a "instncia"
diferente. Todas as variveis e reas de controle, etc, esto localizadas em locais diferentes.
Quando a unidade Sharemem includa em um executvel e suas DLLs, ela trata de substituir o
gerenciador de memria padro para um localizado em BORLANDMM.DLL. O Delphi permite essa
alterao do gerenciador de memria atravs da procedure SetMemoryManager.
Assim, qualquer poro de memria (incluindo strings) alocada em um pode ser desalocada em
outro.
Desta forma, o gerenciador padro para o executvel e suas DLLs so ignorados, dando lugar a um
gerenciador compartilhado. Ele compartilhado tambm por qualquer outro aplicativo que utilizar
Sharemem.
Vantagens
Desvantagens
Sempre que a DLL retornar uma PChar, o programa deve se encarregar de liber-la ao final do uso.
Isso no chega a ser uma desvantagem pois isso uma consequncia do uso de PChar.
No prtico se voc utiliza vrias DLLs. interessante para aplicativos com s uma DLL.
Como mencionado, cada DLL deve exportar sua funo de desalocao de PChar, o que pode tornar
o programa confuso se voc precisar usar vrias. Cada uma teria que ter um nome diferente e isso
poderia criar algumas confuses como tentar desalocar uma PChar criada por uma DLL com a
procedure de liberao de outra. Isso, claro, iria gerar uma exceo.
library StrDLL2;
uses
SysUtils,
Classes;
{ Funo de demonstrao }
function GetAutoexec: PChar; stdcall;
var
SL: TStringList;
begin
SL := TStringList.Create;
try
SL.LoadFromFile('c:\autoexec.bat');
Result := DllStrGet(SL.Text);
finally
SL.Free;
end;
end;
exports
DllStrFree, GetAutoexec;
begin
end.
A funo de alocao e cpia da string (DllStrGet) usada s internamente, sempre que voc for
retornar uma string. Se quiser, voc pode tranquilamente alocar a PChar usando diretamente
StrAlloc ou outras funes do Delphi.
Para usar as funes da DLL em seu aplicativo, voc deve primeiro declarar as funes:
procedure ShowAutoexec;
var
P: PChar;
begin
P := GetAutoexec;
try
ShowMessage(P);
finally
DllStrFree(P);
end;
end;
O bloco try..finally foi usado para garantir a desalocao da varivel. Se ocorresse exceo entre a
chamada de GetAutoexec e DllStrFree, esta no seria chamada, fazendo com que o PChar retornado
no fosse desalocado.
Nenhuma funo de desalocao precisa ser chamada. A desalocao feita automaticamente pelo
Delphi, mesmo utilizando PChar.
Pode ser usada em vrias DLLs sem causar confuso.
A nica desvantagem com relao performance. O processo de transferncia de strings um
pouco mais lento do que com strings longas.
A soluo baseia-se nas facilidades que o Delphi apresenta com relao a interfaces COM. Iremos
utilizar duas unidades novas. Uma delas ser usada tanto no aplicativo host quanto nas DLLs e a
outra, s nas DLLs.
A primeira a declarao de uma interface que chamaremos de IString. Em sua declarao, existe
s um mtodo, o Str, que deve retornar um PChar:
unit StrInt;
interface
type
IString = interface(IUnknown)
['{6ADF6275-82C0-4290-8C8D-DFDAA2AA17CC}']
function Str: PChar;
end;
implementation
end.
unit StrIntImp;
interface
type
TString = class(TInterfacedObject, IString)
private
FStr: PChar;
{ IString }
function Str: PChar;
public
constructor Create(AString: string); overload;
destructor Destroy; override;
end;
implementation
{ TString }
destructor TString.Destroy;
begin
StrDispose(FStr);
inherited;
end;
end.
Ao implementar a DLL, sempre que quiser retornar uma string, voc deve faz-lo atravs de IString,
e no mais PChar. Exemplo:
library strdll;
uses
SysUtils,
Classes,
StrIntImp,
StrInt;
{$R *.RES}
exports
GetAutoexec;
begin
end.
Perceba, ento, que onde se retornaria um PChar, retornamos um IString criado atravs de
TString.Create, que tem como parmetro a string longa original que queremos retornar.
Para usar uma DLL criada com este mtodo em um aplicativo host, voc deve incluir na clusula
uses de todas as unidades que usarem a DLL a unidade StrInt e usar o valor retornado de forma
parecida com o seguinte:
procedure ShowAutoexec;
var
I: IString;
begin
I := GetAutoexec;
ShowMessage(I.Str);
end;
Note que podemos usar tambm a seguinte forma para fazer a mesma coisa:
procedure ShowAutoexec;
begin
ShowMessage(GetAutoexec.Str);
end;
Perceba que a utilizao muito mais simples que quando com o primeiro mtodo (o que usa uma
procedure para liberar o PChar).
Para entender o funcionamento desse mtodo, voc deve ter um pouco de conhecimento de
interfaces COM. Se quiser, pode pular os pargrafos seguintes.
O mtodo baseia-se na chamada automtica do mtodo Release das interfaces quando a execuo
sai do escopo de uma varivel do tipo interface COM. Ao sair do escopo de uma dessas variveis o
Delphi zera ela e chama o mtodo Release automaticamente, de forma semelhante liberao de
strings.
Aproveitamos isso, ento, para criarmos um objeto que implementa uma interface especial (IString).
O objeto (TString) mantm uma PChar apontada para a string. Quando o objeto destrudo, ele
automaticamente libera a varivel PChar.
Quando o aplicativo chama a funo GetAutoexec, esta (que est na DLL), cria uma string e a usa
como parmetro para a criao de um objeto TString. O construtor desse objeto, ento, aloca o
espao necessrio e copia os caracteres da string para l. GetAutoexec retorna a interface IString
associada ao objeto (o Delphi faz automaticamente a "converso" entre TString e IString baseado no
tipo que deve ser retornado por GetAutoexec).
No aplicativo host, usamos o mtodo Str da interface como parmetro para ShowMessage. Ao final
da procedure ShowAutoexec, o Delphi executa automaticamente o mtodo Release da interface
IString.
Claro que voc no precisa entender isso para usar o mtodo. Basta seguir os exemplos.
Importante
S utilize estes mtodos se realmente no quiser incluir a unidade Sharemem e a DLL
BORLANDMM.DLL em seu projeto. A incluso desses componentes facilita bastante a comunicao
entre seu aplicativo e as DLLs criadas para ele, visto que as operaes com strings longas em Delphi
so bastante facilitadas pela linguagem.