Francesco Perrotti wrote:
> Oi pessoal,
>  
> Tenho algumas dúvidas sobre o uso de PChar, agradeceria alguma ajuda.
>  
> É o seguinte, fiz uma DLL com uma função que precisa retornar uma string, 
> portanto tenho que usar um PChar
> já que provalvelmente a DLL será usada com linguagem C.

Se você envia strings para a dll, você pode criar um tipo string e fazer 
um cast para pchar. Uma ansi string é compatível com pchar internamente.

> Só que ainda não consegui entender direito como o Delphi trata esse tipo. Por 
> exemplo,
> se eu declarar em uma função:
>  
> var p:pchar;
>  
> o que exatamente o delphi cria? apenas um ponteiro para chars? ele já aloca 
> memória
> para conter strings? se eu tiver que retornar um pchar por uma função, por 
> exemplo:

Nada de alocação, apenas um tipo ponteiro.

> function Hello: pchar;
> begin
>   result := 'Hello';
> end;

'Hello' é uma literal que é alocada e liberada pelo compilador, e neste 
caso específico você não terá problemas nem com memória corrompida nem 
com vazamento.

> isso está correto? ou tenho que alocar memória para o pchar como eu teria que 
> fazer em c?

É como programar em C, exatamente. No caso acima você não precisa alocar 
porque a string é uma literal, mas nos demais casos você tem que cuidar 
se as rotinas que você está manipulando estão alocando memória 
corretamente. E se estão alocando, tenha em mente aonde e como elas 
serão desalocadas.

> nesse caso o delphi já coloca o terminador zero no final ou eu devo colocar 
> explicitamente?

Ansi strings são compatíveis com pchar, elas já possuem um #0 no final. 
Até isso o Delphi e o fpc faz por nós.

> E no lugar onde faço a chamada a essa função, depois eu tenho que liberar a 
> memória?
> Por exemplo:
>  
> var p: pchar;
> begin
>   p := Hello;
>  
> e agora? depois de usar a string em p o que eu devo fazer? liberar a memória? 
> ou o delphi já faz isso?
> No help do delphi há exemplos usando arrays de char que depois são 
> "casteados" para pchar,

Usando um array de char (com um #0 no final) ou string, o compilador irá 
alocar e desalocar a memória por você, mas cuidado para não mandar uma 
string para outra rotina sendo que a string foi alocada localmente (tal 
como uma variável local). Depois que a sua rotina terminar, babau 
string. Exemplo, isto aqui funciona:

var
   VStr: string;
begin
   VStr := Copy(Alguem, AlgumaPos, AlgumTamanho);
   ChamaDll(PChar(VStr));
end;

A string é alocada por Copy, guardada em VStr, é passado para ChamaDll 
como um PChar, e depois que volta da rotina ChamaDll é que é desalocada 
pelo compilador.

> mas no meu caso eu não sei qual será o tamanho final da string, devo alocar 
> um array dentro da função 
> e liberar ele fora dela?

Ou isso, ou usar ansi strings, ou usar StrAlloc, ou usar GetMem, ou usar 
alguma rotina que se preocupe com isto (exemplo strpcopy), etc. E 
lembrar de desalocar essa memória caso tenha sido alocada por você ou 
por alguma rotina que você chamou.

Geralmente, ao programar com bibliotecas de link dinâmico, é comum 
utilizar ansi strings na aplicação e fazer um cast forçado na chamada à 
rotina. Todo o trabalho de alocação fica transparente pra você e você 
tem mais tempo para se preocupar com coisas mais importantes.

Joao Morais

Responder a