Na linguagem C++, é permitido criar funções "sobrecarregadas" (overloaded), isto é, várias funções podem ter o mesmo nome mas ter parâmetros em quantidade e tipos diferentes. Por causa dessa peculiaridade, compiladores C++ incluem "decorações" no nome de todas as funções - sobrecarregadas ou não - de modo a garantir a unicidade desses nomes no código binário final gerado. Normalmente, essa "decoração" significa incluir mnemônicos do tipo de retorno da função e um mnemônico do tipo de cada parâmetro. Veja o exemplo abaixo, tirado do Wikipedia para o C++ da Borland:
Função C++ | Nome exportado |
void funcao(int par1) | @funcao$qi |
void funcao(int par1, char par2) | @funcao$qizc |
void funcao(void) | @funcao$qv |
Então, para mapear uma função C++ no Delphi, precisaremos descobrir o nome com que ela foi exportada na biblioteca DLL e utilizar esse nome na declaração pascal. Suponha que a DLL seja BIBLIO.DLL e as funções são as do exemplo acima. O mapeamento dessas funções em Delphi seria :
procedure funcao1 (par1 : integer);cdecl;
external 'BIBLIO.DLL' name '@funcao$qi';
procedure funcao2(par1 : integer; par2 : char);cdecl;
external 'BIBLIO.DLL' name '@funcao$qizc';
procedure funcao3;cdecl;
external 'BIBLIO.DLL' name '@funcao$qv';
external 'BIBLIO.DLL' name '@funcao$qi';
procedure funcao2(par1 : integer; par2 : char);cdecl;
external 'BIBLIO.DLL' name '@funcao$qizc';
procedure funcao3;cdecl;
external 'BIBLIO.DLL' name '@funcao$qv';
Esse tipo de mapeamento é estático, de forma que as DLLs assim mapeadas são carregadas imediamente, junto com o executável. Se preferir carregar as bibliotecas somente quando forem de fato necessárias, use as funções LoadLibrary e GetProcAddress, lembrando que o nome de função que deve ser passado a essa última é o nome com as "decorações".
Como descobrir o nome modificado pelo compilador e exportado nas bibliotecas é assunto tratado em outro post.
3) Para o caso de ter que usar classes instanciadas do C++ no Delphi, o mapeamento de tipos para os campos deve ser feito da mesma maneira que para estruturas, como mostrado no post anterior. Para as funções virtuais da classe, o mapeamento deve ser feito do mesmo modo que as funções mostrado no post anterior, com uma diferença : deve-se sinalizar ao Delphi que essa função é abstrata, isto é, que essa função será localizável pela tabela de funções virtuais e que o Delphi não deve esperar encontrar a implementação da função nessa classe. Segue exemplo do mapeamento de uma função virtual do C++ no Delphi; este exemplo é utilizado na prática na ABC71, dentro do Gerador de Relatórios:
procedure Preview (aReport : TPtrFolderData);virtual;abstract;
Como a tabela de funções virtuais funciona de forma idêntica no Delphi e no C++, ao invocar essa função ("mensagem", para os puristas) no Delphi, a função que será chamada efetivamente será aquela cujo corpo está codificado na biblioteca C++. Lembre-se que no pascal ela foi declarada como "abstrata" e portanto não tem implementação aí.
Implicações disso que foi exposto nos dois últimos parágrafos : as funções que serão chamadas no Delphi têm que ser virtuais no C++ e o C++ deve disponibilizar uma forma de se obter uma instância da classe, provavelmente através de uma função tipo Create ou do tipo Get.
Por fim, as regras e recomendações são bastante parecidas com isso caso se queira fazer o contrário, isto é, chamar no C++ código feito no Delphi.
Nenhum comentário :
Postar um comentário
OBS: Os comentários enviados a este Blog são submetidos a moderação. Por isso, eles serão publicados somente após aprovação.
Observação: somente um membro deste blog pode postar um comentário.