Postagem em destaque

BlackTDN :: DynCall no Protheus: Uma Nova Era na Integração com C/C++

_Créditos das imagens: ChatGPT
🚀 **DynCall no Protheus: Uma Nova Era na Integração com C/C++**  

Do meu ponto de vista, um dos recursos mais interessantes na nova versão do Protheus "Onça Preta" é a possibilidade de uso do **DynCall**.

A linguagem AdvPL/TLPP, utilizada no Protheus, pode ser considerada um "superconjunto" de Clipper com FiveWin, mas com características e funcionalidades específicas voltadas para o ecossistema TOTVS. Um dos recursos marcantes do Clipper e de linguagens padrão xBase, como Harbour, é a possibilidade de incorporar código C/C++ diretamente no código-fonte. Até então, o Protheus não suportava isso nativamente. No entanto, com a introdução do **DynCall**, é possível simular essa integração ao carregar e executar funções de bibliotecas dinâmicas (DLLs) escritas em C ou C++. A seguir, comparamos os recursos das linguagens xBase padrão (exemplificadas pelo Harbour) com a implementação no Protheus via DynCall e apresentamos exemplos dos novos recursos oferecidos por essa tecnologia.

---

### **Recursos em Linguagens Padrão xBase (Harbour)**

Nas linguagens xBase padrão, como o Harbour, é possível incorporar código C/C++ diretamente no mesmo arquivo de código usando diretivas como `#pragma BEGINDUMP` e `#pragma ENDDUMP`. Isso permite que funções escritas em C/C++ sejam chamadas de forma natural no código xBase, como se fossem funções nativas. Veja um exemplo:

```c
#pragma BEGINDUMP

#include "hbapi.h"

HB_FUNC(STROCCURS)
{
    const char *s1 = hb_parc(1);
    char *s2 = hb_parc(2);
    HB_SIZE len = hb_parclen(2);
    HB_SIZE count = 0;
    
    for (HB_SIZE i = 0; i < len; i++) {
        if (s1[0] == s2[i]) count++;
    }
    hb_retns(count);
}

#pragma ENDDUMP
```

Nesse caso:
- A função `STROCCURS` é escrita em C e integrada diretamente no Harbour.
- Após a compilação, pode ser chamada no código xBase como qualquer outra função: `nCount := STROCCURS("a", "banana")`.

Esse modelo oferece uma integração perfeita, mas exige que o código C/C++ seja compilado junto com o código xBase, limitando a flexibilidade em cenários onde bibliotecas externas já existem.

---

### **Implementação no Protheus com DynCall**

No Protheus, a incorporação direta de código C/C++ não é suportada. Em vez disso, o **DynCall** permite carregar bibliotecas dinâmicas (DLLs) em tempo de execução e chamar suas funções ou métodos. Isso simula a integração com código de baixo nível, mas com uma abordagem diferente. Vamos analisar como isso funciona.

#### **Exemplo Básico com DynCall**

Considere uma DLL em C que exporta uma função simples de soma:

```c
#define EXPORT __declspec(dllexport)

EXPORT int add(int a, int b)
{
    return a + b;
}
```

No Protheus, essa função pode ser chamada usando DynCall assim:

```advpl
#include "tlpp-core.th"

Function U_SimpleDynCall()
    Local oDll := tRunDll():New("dllc.dll")
    Local nValue as Numeric
    oDll:CallFunction("add", "III", nValue, 4, 8)
    Conout("Resultado: " + cValToChar(nValue)) // Resultado: 12
    oDll:Free()
Return
```

### **Comparação entre Harbour e Protheus com DynCall**

| **Aspecto**            | **Harbour (xBase Padrão)**                          | **Protheus com DynCall**                          |
|------------------------|----------------------------------------------------|--------------------------------------------------|
| **Integração**         | Código C/C++ é incorporado diretamente no fonte.   | Requer uma DLL externa carregada dinamicamente. |
| **Flexibilidade**      | Menos flexível; exige recompilação do projeto.     | Mais flexível; permite usar DLLs pré-existentes.|
| **Naturalidade**       | Chamada direta como função nativa.                 | Usa API DynCall, com assinaturas explícitas.    |
| **Portabilidade**      | Depende da compilação para cada plataforma.        | Suporta Windows e Linux com a mesma lógica.    |
| **Resiliência**        | Sem isolamento nativo; crashes afetam o programa.  | Sandbox isola a DLL, com timeouts configuráveis.|

O DynCall no Protheus permite, além de chamadas simples a funções, a invocação de métodos de classes C++, acesso a variáveis globais e manipulação de ponteiros.

---

### **DynCall no Harbour**

O Harbour também possui suporte para DynCall via funções como `hb_libLoad()` e `hb_libCall()`. Um exemplo pode ser encontrado neste repositório: [Harbour DLL Example](https://raw.githubusercontent.com/naldodj/naldodj-harbour-core/81be99f647f8e752c05ba782e3ca4d5e9333c2c9/contrib/hbfoxpro/dll.prg).

---

### **Conclusão**

Embora o Protheus não suporte a incorporação direta de código C/C++ como o Harbour, o **DynCall** oferece uma alternativa poderosa para integrar bibliotecas dinâmicas. Ele permite chamar funções e métodos, acessar variáveis globais, gerenciar ponteiros e configurar timeouts, tudo com um modelo de sandbox que garante resiliência. Comparado ao Harbour, o DynCall troca a simplicidade da integração direta por maior flexibilidade e portabilidade, sendo ideal para cenários onde é necessário usar bibliotecas externas ou estender o Protheus com código de baixo nível de forma segura e robusta.

⚠️ **Observação:** Infelizmente, o DynCall no Protheus está disponível apenas para uso interno da TOTVS.

---

### ***Hashtags***
#AdvPL, #TLPP, #Protheus, #TOTVS, #DynCall, #Cplusplus, #Harbour, #xBase, #ERP, #Desenvolvimento

Comentários

Postagens mais visitadas