Como declarar função de uma DLL (Delphi)
Boa tarde, tenho uma função numa DLL que retorna diversos valores, então o retorno da função é uma classe, pergunto, como faço o chamado dessa função (que esta na DLL) em outra aplicação, visto que a classe que ela retorna não existe na aplicação?
Estou usando o delphi 7 nesse caso..
Ex:
TMInhaClasse = class
FCod : Integer;
FNome : String;
FSituacao : String;
function RetornaDados(pValor: Integer) : TMinhaClasse; stdcall;
begin
comandos....
result.Cod := ret.codigo;
result.Nome := ret.nome;
result.Situacao := ret.status;
end;
Na aplicação poderia fazer o chamado no método estático:
function RetornaDados(pValor: Integer) : TMinhaClasse; stdcall; external 'Arquivo.DLL'
Mas TMinhaClasse não existe na aplicação, como resolver isso?
Estou usando o delphi 7 nesse caso..
Ex:
TMInhaClasse = class
FCod : Integer;
FNome : String;
FSituacao : String;
function RetornaDados(pValor: Integer) : TMinhaClasse; stdcall;
begin
comandos....
result.Cod := ret.codigo;
result.Nome := ret.nome;
result.Situacao := ret.status;
end;
Na aplicação poderia fazer o chamado no método estático:
function RetornaDados(pValor: Integer) : TMinhaClasse; stdcall; external 'Arquivo.DLL'
Mas TMinhaClasse não existe na aplicação, como resolver isso?

Domper Ltda
Curtidas 0
Respostas

Arthur Heinrich
24/03/2025
Eu posso estar falando besteira, mas funções que retornam classes, na realidade retornam a referência para uma instância da classe.
No seu caso, por se tratar de uma DLL, o acesso da aplicação à memória alocada pela DLL eu tenho a impressão de que não é permitido, já que a aplicação e a DLL trabalham em contextos diferentes.
O que normalmente se faz é utilizar funções ou procedures na DLL que fazem a troca das informações através de parâmetros escalares, passados por referência, ou mediante estruturas (record), que é preenchido a partir de um endereço passado.
Uma maneira de tentar resolver é vendo como funciona a API do Windows. Geralmente tem uma estrutura do tipo TProcessInfo (exemplo), que contém informações sobre um processo. Alocamos um buffer com o tamanho desta estrutura e o passamos para a função, que retorna X bytes no buffer alocado.
Algumas funções podem retornar dados de tamanho variado e, aí, precisamos informar o tamanho máximo do buffer e a função retorna o tamanho da informação retornada.
Não parece algo simples.
No seu caso, por se tratar de uma DLL, o acesso da aplicação à memória alocada pela DLL eu tenho a impressão de que não é permitido, já que a aplicação e a DLL trabalham em contextos diferentes.
O que normalmente se faz é utilizar funções ou procedures na DLL que fazem a troca das informações através de parâmetros escalares, passados por referência, ou mediante estruturas (record), que é preenchido a partir de um endereço passado.
Uma maneira de tentar resolver é vendo como funciona a API do Windows. Geralmente tem uma estrutura do tipo TProcessInfo (exemplo), que contém informações sobre um processo. Alocamos um buffer com o tamanho desta estrutura e o passamos para a função, que retorna X bytes no buffer alocado.
Algumas funções podem retornar dados de tamanho variado e, aí, precisamos informar o tamanho máximo do buffer e a função retorna o tamanho da informação retornada.
Não parece algo simples.
GOSTEI 0

Domper Ltda
24/03/2025
Bom dia, podemos fazer a função na DLL retornando um record como citou, mas a declaração dessa função na aplicação terá o mesmo problema, afinal o record não existe na aplicação, como resolver isso? teria algum exemplo?
GOSTEI 0

Arthur Heinrich
24/03/2025
O link abaixo descreve bem os problemas de se utilizar DLLs e suas limitações. Acredito que valha a pena dar uma olhada para esclarecer.
http://rvelthuis.de/articles/articles-dlls.html
De acordo com o artigo, é melhor que as functions retornem datatypes simples, como um Inteiro, por exemplo, para indicar se a função foi executada com sucesso (0) ou insucesso (1).
Para retornar estruturas, o melhor jeito é utilizar pointers.
Você declara o mesmo tipo, tanto na DLL como na aplicação. Obviamente, se criar um parâmetro do tipo "var", que passa o parâmetro por referência, vai ter um problema de checagem de datatypes, já que o tipo da DLL e da aplicação não são os mesmos, embora do mesmo tipo.
O que é comum de se fazer é declarar o parâmetro como um ponteiro para a estrutura e passar o endereço.
Exemplo:
Ao invés de fazer:
Você faz:
Dentro da DLL, que vai receber um pointer, a função deve utilizar um cast:
Tem que tomar cuidado com o tipo String do Delphi, que é bem diferente. O Delphi aceita vários modelos de armazenamento para representar strings e podem não representar tipos válidos em outras linguagens.
Este link comenta sobre eles:
https://docwiki.embarcadero.com/RADStudio/Athens/en/String_Types_(Delphi)
http://rvelthuis.de/articles/articles-dlls.html
De acordo com o artigo, é melhor que as functions retornem datatypes simples, como um Inteiro, por exemplo, para indicar se a função foi executada com sucesso (0) ou insucesso (1).
Para retornar estruturas, o melhor jeito é utilizar pointers.
Você declara o mesmo tipo, tanto na DLL como na aplicação. Obviamente, se criar um parâmetro do tipo "var", que passa o parâmetro por referência, vai ter um problema de checagem de datatypes, já que o tipo da DLL e da aplicação não são os mesmos, embora do mesmo tipo.
O que é comum de se fazer é declarar o parâmetro como um ponteiro para a estrutura e passar o endereço.
Exemplo:
Ao invés de fazer:
type TEstrutura = record Field1 : Integer; Field2 : Single; end; function Funcao1(var E1 : TEstrutura):Integer; ... var Estrutura : TEstrutura; Return : Integer; Return := Funcao1(Estrutura);
Você faz:
type TEstrutura = record Field1 : Integer; Field2 : Single; end; function Funcao1(E1 : ^TEstrutura):Integer; ... var Estrutura : TEstrutura; Return : Integer; Return := Funcao1(@Estrutura);
Dentro da DLL, que vai receber um pointer, a função deve utilizar um cast:
function Funcao1(E1 : ^TEstrutura):Integer; ... TEstrutura(E1^).Field1 := xxx;
Tem que tomar cuidado com o tipo String do Delphi, que é bem diferente. O Delphi aceita vários modelos de armazenamento para representar strings e podem não representar tipos válidos em outras linguagens.
Este link comenta sobre eles:
https://docwiki.embarcadero.com/RADStudio/Athens/en/String_Types_(Delphi)
GOSTEI 0