Skip to content
Tech AI Wire

Babashka 1.13.220 adiciona FFI para chamar bibliotecas nativas

O Babashka 1.13.220 adiciona uma FFI construída sobre a API Panama do Java: um script Clojure passa a chamar uma biblioteca nativa sem escrever um pod nem Java.

Por Tech AI Wire Team

3 min de leitura

XLinkedIn
A terminal running Babashka 1.13.220, where an ffi-demo.clj script loads zlib through the new foreign function interface and prints version 1.3.1.

O Babashka, o ambiente de scripting em Clojure de arranque rápido, já consegue chamar bibliotecas nativas em C diretamente. A versão 1.13.220 saiu a 31 de agosto de 2026 com uma interface de funções externas, e o autor Michiel Borkent explicou o desenho no seu blogue. Até agora, chegar a código nativo a partir de um script Babashka obrigava a escrever um pod: um programa separado com o qual o Babashka fala por um socket. A nova FFI elimina esse passo.

Uma interface de funções externas é a canalização que permite a uma linguagem chamar outra. Aqui, o Clojure chama C.

O que faz a nova interface

A implementação assenta em java.lang.foreign, a Foreign Function and Memory API que chegou ao JDK através do projeto Panama. Borkent nota que a biblioteca já existente coffi assenta na mesma base. Não é, portanto, um mecanismo próprio, mas o caminho oficial da JVM para código nativo, aberto a scripts.

A versão cobre mais do que simples chamadas de funções. Segundo as notas de lançamento no GitHub, o trabalho abrange os pull requests #2031 a #2077 e inclui segmentos de memória, gestão de arenas, layouts de structs e uniões, e callbacks. Os callbacks importam: permitem que uma biblioteca C chame de volta o seu código Clojure.

A memória é a parte que exige atenção. A memória nativa fica fora do garbage collector, por isso o Babashka obriga a geri-la explicitamente através de arenas. Uma arena detém um bloco de memória nativa e liberta-o quando fecha. O with-open do Clojure faz essa limpeza automaticamente no fim do bloco. Se errar, não recebe uma exceção. Recebe um segfault.

Uma primeira chamada é pequena. Carregar o zlib e pedir a versão devolve a cadeia 1.3.1.

Porque é que o exemplo do SQLite importa

O exemplo que Borkent destaca não é um brinquedo. A FFI permite definir uma função Clojure e registá-la dentro de uma base de dados nativa, para que uma consulta SQLite a chame durante a execução.

Com pods isso não era possível. Um pod corre no seu próprio processo, e o SQLite não consegue atravessar um socket a meio da avaliação de uma consulta. A função tem de viver no mesmo processo que o motor da base de dados. A FFI direta coloca-a lá.

Esta é a forma geral da mudança. Tudo o que exigia que o seu código e a biblioteca nativa partilhassem um processo e um espaço de memória estava fora de alcance. Callbacks, alocadores próprios e pontos de extensão dentro do processo ficam agora abertos.

Uma mudança mais silenciosa nos binários Linux

Uma linha da versão afeta quem nunca tocar na FFI. Em Linux, a compilação predefinida do Babashka passou de totalmente estática para maioritariamente estática, o que significa que a glibc passa a ser ligada dinamicamente. As compilações de macOS e Windows já funcionavam assim.

A razão é a própria FFI: carregar bibliotecas nativas arbitrárias em tempo de execução não combina com um binário totalmente estático. O preço é a portabilidade. Um binário totalmente estático corre em qualquer lado; um maioritariamente estático espera uma glibc compatível no anfitrião. Se copia o Babashka para um contentor mínimo ou uma imagem Alpine, teste antes de atualizar.

O que isto significa para programadores

Se já usa o Babashka para scripts e evitou uma tarefa por precisar de uma biblioteca C, volte a olhar para ela. O desvio pelos pods era atrito real e desapareceu.

Se mantém um pod, vale a pena ler com atenção. Os pods continuam a fazer sentido para isolamento e para embrulhar SDK nativos grandes. Já não fazem sentido apenas para alcançar meia dúzia de funções C.

Se está a começar, comece pelas regras das arenas e não pela sintaxe da chamada. Chamar zlibVersion é fácil. Saber que memória lhe pertence, e quando é libertada, é o que separa um script que funciona de um crash intermitente. Embrulhe cada arena em with-open enquanto não tiver motivo para o contrário.

E se distribui o Babashka em contentores, verifique a glibc da imagem base antes de saltar para a 1.13.220. Essa mudança vem consigo, use ou não a nova interface.

Fontes

  1. Babashka FFI - Michiel Borkent
  2. Babashka releases: v1.13.220 - GitHub

Artigos relacionados

A process listing on a Kubernetes v1.37 node, showing containerd, kubelet and kube-proxy owned by the kube user while the systemd services still run as root.
Dev Stack

Kubernetes 1.37 promove o modo rootless a beta

O Kubernetes 1.37 promove o KubeletInUserNamespace a beta. O kubelet, os runtimes de contentores, os plugins CNI e o kube-proxy passam a poder correr como utilizador comum.