bridge
Ponte entre FatScript e bibliotecas C externas
a biblioteca
bridgepermite 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
DLLrepresentando a biblioteca carregada. - name: Um nome (
Text) da função a ser vinculada dentro da biblioteca. - in: Uma lista
List/Ctypede tipos de argumento esperados pela função. - out: O tipo de retorno
CTypeda 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* | Text |
| void | void (tipo retorno) | Void |
| voidP | void* | Chunk |
stringdeve ser um ponteiro de caractere alocado dinamicamente e terminado em nulo
Métodos avulsos
| Nome | Assinatura | Breve descrição |
|---|---|---|
| unsafeCStr | (ptr: CPointer): Text | Lê ptr como uma C-string terminada em nulo |
| 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 tipo C |
unsafeCStr
Lê um CPointer como uma C-string terminada em nulo e o converte em um Text do FatScript. Este método é útil para interagir com bibliotecas que retornam C-strings sem informações explícitas sobre o comprimento, criando uma cópia gerenciada. Diferentemente de unsafePeek, unsafeCStr determina automaticamente o comprimento da string usando strlen. Aviso: Certifique-se de que o ponteiro aponte para uma string terminada em nulo para evitar comportamento indefinido.
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.