Este é um post disponível para assinantes MVPIntegre projetos .NET e Win32 - Artigo ClubeDelphi 128
Trata da habilidade de acessar componentes .NET a partir do Delphi, ou acessar componentes do Delphi a partir do .NET, acessar serviços web feitos em ambas as linguagens ou ainda trocar mensagens via API do Windows.
[Artigo já está disponível no Leitor Digital DevMedia®. Clique aqui para acessá-lo]
> Clique aqui para ler todos os artigos da ClubeDelphi 128
Há várias situações em que é necessário integrar ambientes diferentes. As mais comuns são quando uma empresa adquire um conjunto de bibliotecas que não são feitas nativamente na linguagem onde ele deseja usar, por exemplo, compra uma coleção de DLLs feitas em C++ para usar no C#, ou quando a empresa contrata um terceiro apenas para desenvolver a biblioteca. Mais comum ainda são as integrações feitas via Web Services SOAP e via HTTP puro, podendo usar ou não REST e podendo usar ou não XML.
Um importante conceito nesses casos é determinar o que é o componente, entendê-lo como uma caixa preta, criar um programa simples para testá-lo e só então integrá-lo na aplicação principal. Do ponto de vista da aplicação principal esse componente será apenas um método, ou uma unit com um conjunto de métodos.
Para usar DLL é necessário que as funções desta sejam declaradas com stdcall e que se use PChar no lugar de strings. Também é possível usar uma biblioteca do .NET no Delphi. Para isso a biblioteca deve ter um strong name, deve estar no GAC e deve ter a propriedade ComVisible(true) nos parâmetros da biblioteca.
Também é possível a comunicação entre programas e componentes via Web Services, mas, ampliando um pouco os horizontes e pensando mais abstratamente: Web Service é qualquer “site” hospedado na web que fornece um serviço ou funcionalidade. Sendo assim um Web Service não precisa necessariamente seguir o protocolo SOAP, que é bastante extenso, mas pode se beneficiar de qualquer chamada HTTP pura que retorne um XML como resultado.
Outro meio de se implementar a comunicação entre os sistemas é através de troca de mensagens pela API do Windows. Nesta forma o componente ou sistema legado em questão não é um conjunto de DLLs mas sim um programa rodando.
Um ponto muito importante para a integração entre sistemas é a serialização de objetos complexos e estruturas (structs ou records). É possível serializar objetos no formato XML, JSON, Yammel ou TXT. Algumas bibliotecas do Delphi ou do .NET podem auxiliar nesta tarefa, mas esses métodos de serialização podem ser implementados manualmente também. Nem todos os métodos de serialização serão abordados neste artigo.
Comunicação direta via sockets, usando protocolo próprio, pode ser interessante para se passar parâmetros ou objetos serializados entre aplicações. Abstratamente é isso que aplicações DataSnap e Web Services fazem. Em último caso pode-se recorrer ao método mais antigo de todos para integração entre sistemas: troca de arquivos TXT.
DLLs
Assim como o Visual C++ e qualquer outro compilador da Microsoft a direção ou convenção de chamada de métodos é, por padrão, stdcall, herança do C/C++. No Delphi a convenção de chamada utilizada é a FastCall. Nada impediria de mudar isso, mas o que é padrão em um ambiente tem de ser avisado no outro. O que torna isso impossível é o fato de que a convenção FastCall não foi padronizada, tendo sido implementada no Delphi e no .NET/C++ de maneira diferente. Por isso FastCall é incompatível entre Delphi e .NET. Use sempre as convenções padronizadas, dando preferência sempre a stdcall, que é o mais universal.
Nota do DevMan
Convenções de chamada explicam para o sistema, em baixo nível, qual a ordem dos parâmetros de um método, quais serão trazidos dos registradores e quais serão trazidos da memória e “de quem” é a responsabilidade de limpar a pilha: de quem está chamando ou de quem é chamada. A diferença entre stdcall e fastcall é que enquanto stdcall foi padronizado por normas ISO/ANSI, fastcall pode ser implementado diferente de acordo com o fabricante do compilador ou da linguagem. O fastcall do Delphi Win32 não encontra correspondente nas outras linguagens. Para compreender as diferenças entre as convenções de chamada é necessário compreender um pouco de assembly e o conceito de pilha. Enquanto no stdcall a responsabilidade de desempilhar os argumentos ou valores é sempre da função chamada o fastcall tem os primeiros parâmetros armazenados nos registradores do processador enquanto que os subseqüentes ficam na pilha. Como mencionado a implementação de fastcall pode ser diferente de acordo com o compilador e não é aberta, pode ser proprietária. Na convenção stdcall os parâmetros são empilhados na ordem reversa, a função chamada desempilha todos os argumentos quando retorna, dados primitivos são retornados no registrador EAX ou nos registradores EAX:EDX e estruturas de até 8 bytes são retornadas no par EAX:EDX. Já o fastcall usa os registradores para os quatro primeiros argumentos e a pilha para os subsequentes. Entende-se por função chamadora a que está por fora, que faz a chamada e por função chamada aquela que é executada dentro de uma chamadora. Em um exemplo hipotético caso o Delphi usasse por padrão stdcall, se no evento onClick do button1 é executada a função ShowMessage(‘hello world’) então a ShowMessage é a chamada e button1Click é a chamadora. ShowMessage teria a obrigação de desempilhar o parâmetro ‘Hello World’.
É possível usar stdcall no Delphi, basta usar a diretiva stdcall depois do nome do método. Mandamentos para usar DLLs do Delphi no Prism:
1. Use apenas tipos primitivos;
2. Strings NÃO SÃO tipos primitivos;
3. Não use sharemem e borlandmm.dll porque esses mecanismos servem apenas para transferir strings do Delphi entre aplicações e DLLs feitas
4. Use PChar e PAnsiChar no lado Delphi;
5. No lado .NET, strings são transformados pelo DLLImport
A Listagem 1 mostra o código do lado Delphi e a Listagem 2 do lado Prism. O objetivo dessas primeiras listagens foi mostrar como uma integração pode ser feita através de DLLs feitas em Delphi e utilizadas no Prism. A declaração de métodos estáticos com convenção de chamada stdcall é essencial para isso. É possível também ter forms criadas dentro dessas DLLs contanto que elas sejam criadas e destruídas dentro da DLL.
Listagem 1. DLL feita no Delphi
library DelphiDll;
uses
sharemem,
SysUtils,
Classes,
dialogs;
{$R *.res}
function"
ATENÇÃO! A exibição deste artigo foi interrompida.
Este é um post disponível para assinantes MVP
6 COMENTÁRIOS
Mas seguindo o exemplo, na hora da chamada do metodo da o seguinte erro: "OLE error 80131522". O q pode estar acontecendo?
Nota1: o assembly foi registrado normal (delphi 2007/windows 7 32 bits)
Esse erro pode acontecer por vários motivos.
O Assembly feito em Prism ou C# deve ser "com visible", isso você pode ver nas propriedades do projeto ou no assemblyinfo, dependendo da versão de seu visual studio/prism.
Além de ser comvisible o assembly precisa de uma GUID, e a interface dentro do código - fonte (que você implementa) precisa de outra guid, não pode ser igual. É essa guid que deve ser usada pela interface no lado Delphi.
Essa DLL deve ter um strong name, ou seja, deve ser compilada com um arquivo .snk gerado pela ferramenta sn.exe.
Depois de compilar a DLL deve ser registrada no GAC.
Se o problema persistir, por favor me mande o seu fonte e a DLL para eu examinar.
Pode ser problema de ambiente também. Testei no winXP 32 bits.
Envie os projetos (.net/win32) p/ seu e-mail

Um abraço.
Sempre que você adiciona a referencia a uma DLL do tipo COM/ActiveX é criada automaticamente uma DLL com o mesmo nome e um ".interop". Essa faz o "meio de campo" entre as tecnologias COM e .Net.
Geralmente adicionar a referencia é tudo que se precisa, mas você chama seus objetos e funções através do nome da dll original mesmo, não da interop.
A sua DLL tem os métodos públicos e a guid? Pode postar aqui seu projeto para analisarmos?
Space do autor


0
0
