bridge
Ponte entre FatScript e bibliotecas C externas
A biblioteca bridge
permite que o FatScript interaja com bibliotecas C externas, fornecendo capacidades de linkagem dinâmica e interface de função estrangeira (FFI). Isso é útil para aproveitar as vantagens de desempenho do C e usar bibliotecas C existentes em aplicativos FatScript.
Importação
_ <- fat.bridge
Tipos
A biblioteca bridge
introduz dois tipos principais para lidar com a linkagem dinâmica de bibliotecas externas e chamar funções externas: DLL
e FFI
.
DLL
O tipo DLL
representa um identificador para uma biblioteca carregada dinamicamente.
Construtor
Nome | Assinatura | Breve descrição |
---|---|---|
DLL | (filename) | Carrega uma biblioteca dinâmica |
O construtor DLL
aceita o seguinte argumento:
- filename: O caminho para o arquivo de objeto compartilhado (.so/.dll) a ser carregado.
FFI
O tipo FFI
permite vincular funções externas da biblioteca carregada dinamicamente, utilizando o sistema CType
do FatScript para corresponder os tipos de entrada e saída esperados pela função.
Construtor
Nome | Assinatura | Resumo |
---|---|---|
FFI | (lib, name, in, out) | Vincula a uma função externa |
O construtor FFI
aceita os seguintes argumentos:
- lib: Uma instância de
DLL
representando a biblioteca carregada. - name: Um nome (
Text
) da função a ser vinculada dentro da biblioteca. - in: Uma lista
List/Ctype
de tipos de argumento esperados pela função. - out: O tipo de retorno
CType
da função.
Membros do protótipo
Nome | Assinatura | Breve descrição |
---|---|---|
call | (args...): Any | Chama a função vinculada |
Aliases
- CPointer: Representa um ponteiro de memória (semelhante a
void*
), com o tipo baseChunk
. - CType: Representa tipos C no FatScript, com o tipo base
Number
.
CType
O sistema CType
mapeia tipos C comuns para tipos correspondentes no FatScript, permitindo uma interação segura com bibliotecas C. Os seguintes tipos estão disponíveis no escopo ctype
e implementam a correspondência automática com os tipos FatScript:
Nome | Tipo C | Correspondência |
---|---|---|
sint | int | Number |
sintP | int* | Number |
uint | unsigned int | Number |
uintP | unsigned int* | Number |
float | float | Number |
floatP | float* | Number |
double | double | Number |
doubleP | double* | Number |
schar | char | Chunk |
scharP | char* | Chunk |
uchar | unsigned char | Chunk |
ucharP | unsigned char* | Chunk |
sshort | short | Number |
sshortP | short* | Number |
ushort | unsigned short | Number |
ushortP | unsigned short* | Number |
slong | long | Number |
slongP | long* | Number |
ulong | unsigned long | Number |
ulongP | unsigned long* | Number |
string | char* (tipo retorno) | Text |
void | void (tipo retorno) | Void |
voidP | void* | Chunk |
string
deve ser um ponteiro de caractere alocado dinamicamente e terminado em nulo.
Métodos avulsos
Nome | Assinatura | Breve descrição |
---|---|---|
unsafePeek | (ptr: CPointer, offset: Number, len: Number): Chunk | Lê de ptr, considerando deslocamento e comprimento |
detachNode | (node: Any): Void | Libera à propriedade da memória |
marshal | (val: Any, type: CType): Chunk | Converte um valor FatScript para um tipo C bruto |
unmarshal | (raw: Chunk, type: CType): Any | Converte de um tipo C para FatScript |
getErrno | (): Number | Retorna o errno da última chamada FFI |
sizeOf | (type: CType): Number | Obtém o número de bytes para um determinado CType |
unsafePeek
Permite a leitura direta de memória bruta, que pode ser usada para interagir com estruturas de dados C. Aviso: Este método não realiza verificação de limites e depende de parâmetros corretos. O uso incorreto pode causar falhas no sistema ou vulnerabilidades de segurança.
detachNode
Renuncia à propriedade da memória apontada por Text
ou Chunk
para evitar a liberação dupla de memória. Consulte a documentação da biblioteca externa para entender a propriedade da memória antes de usar detachNode
, já que nem sempre é necessário.
marshal
Converte um valor FatScript para um bloco de memória bruta usando um CType
específico. Útil para compor structs C. Apenas string
e voidP
são válidos para marshaling de Text
e Chunk
como tipos de ponteiro, respectivamente. Aviso: Garanta o manuseio correto dos ponteiros de buffer para evitar liberação dupla de memória.
unmarshal
Converte blocos de memória bruta para tipos específicos do FatScript com base em CType
. Útil para interpretar dados retornados de structs C. Aviso: O uso incorreto ou CType
incorreto pode resultar em comportamento indefinido ou corrupção de dados.
getErrno
O errno
da última chamada FFI é armazenado em cache e pode ser recuperado por este método.
sizeOf
Determina o tamanho da memória (em bytes) de um determinado CType
. Isso é útil para usar com segurança funções como unsafePeek
.
Exemplo de Uso
Carregando uma biblioteca
Para carregar uma biblioteca dinâmica, use o tipo DLL
:
zlibDLL = DLL('libz.so')
Isso tentará carregar a biblioteca de objeto compartilhado libz.so
(neste exemplo, a biblioteca de compressão zlib).
Vinculando a uma função
Para vincular a uma função dentro da biblioteca carregada, use o tipo FFI
:
compressFFI = FFI(zlibDLL, 'compress', [ucharP, slongP, ucharP, slong], sint)
Isso vincula à função compress
na biblioteca zlib. Os tipos de argumento e o tipo de retorno são especificados usando CType
.
Chamando a função
Uma vez vinculada, você pode chamar a função usando o método call
:
compressedData = compressFFI.call(destBuff, destSize, source, sourceSize)
Isso chama a função compress
e retorna o resultado.
Exemplo Completo: comprimindo dados com zlib
_ <- fat.type._
bridge <- fat.bridge
zlibDLL = DLL('libz.so')
{ ucharP, slong, slongP, sint } = bridge.ctype
compressFFI = FFI(zlibDLL, 'compress', [ucharP, slongP, ucharP, slong], sint)
# Comprimir dados
source = 'Hello, zlib compression!'.toChunk
destSize = 256
destBuff = Chunk(256)
compressedData = compressFFI.call(destBuff, destSize, source, source.size)
Observe que destSize
usa o mapeamento do tipo slongP
, e embora seja considerado imutável no FatScript, ele pode ser alterado pela chamada da função. Esse comportamento é esperado e é a forma de interface do FatScript com o C.
Manipulação avançada de dados brutos
Para obter uma melhor compreensão de como o bridge
funciona, você pode estudar o caso de teste do FFI e os projetos de implementação de exemplo zlib.fat e qrcode.fat.
Bridge na Web Build
Ao usar fry
compilado com Emscripten (por exemplo, ao usar FatScript Playground), não há suporte para esta biblioteca.