FFI — Foreign Function Interface
Archivo: src/ffi.rs (289 líneas)
¿Por qué existe?
Permite que los programas Forja llamen funciones de librerías nativas (.dll en Windows, .so/.dylib en Unix) cargadas con importar externa. Provee el registro global de librerías y las funciones nativas _ffi_obtener_funcion, _ffi_llamar_entero y _ffi_llamar_texto que la VM usa para resolver y ejecutar punteros a función externos.
Arquitectura / Estructuras clave
| Componente | Descripción |
|---|---|
LibHandle | Wrapper de *mut c_void que implementa Send + Sync (el puntero raw no es Send por defecto) |
FFI_REGISTRY | OnceLock<Mutex<HashMap<String, LibHandle>>>: registro global ruta → handle |
registry() | Acceso lazy al registro global (inicialización única) |
| Declaraciones OS | extern "system": LoadLibraryW, GetProcAddress, FreeLibrary, GetLastError (Windows) · extern "C": dlopen, dlsym, dlclose, dlerror + constantes RTLD_LAZY/RTLD_LOCAL (Unix) |
API pública
| Función | Descripción |
|---|---|
esta_cargada(ruta) -> bool | Verifica si la librería ya está en el registro |
cargar_libreria(ruta) -> Result<i64, String> | Carga vía LoadLibraryW (Windows) o dlopen (Unix); si ya está cargada devuelve el handle existente. El handle se convierte a i64 como id opaco |
obtener_funcion(ruta, nombre) -> Result<i64, String> | Resuelve un puntero a función con GetProcAddress (Windows) o dlsym (Unix); error si la librería no está cargada |
liberar_libreria(ruta) -> Result<(), String> | Descarga la librería con FreeLibrary / dlclose |
ruta_libreria_sistema(nombre) | Resuelve nombres de librería del sistema (p. ej. "msvcrt.dll"; en Unix agrega prefijo lib/sufijo .so) |
Funciones nativas de la VM
| Nativa | Firma Forja | Descripción |
|---|---|---|
native_ffi_obtener_funcion | _ffi_obtener_funcion(ruta, nombre) -> Entero | Resuelve el puntero a función y lo devuelve como entero; retorna -1 si falla |
native_ffi_llamar_entero | _ffi_llamar_entero(fn_ptr, args: arreglo<Entero>) -> Entero | Hace transmute del puntero a extern "C" fn y lo invoca con 0 a 5 argumentos i64 |
native_ffi_llamar_texto | _ffi_llamar_texto(fn_ptr, args: arreglo<Texto>) -> Texto | Invoca una función que retorna char* (convierte argumentos a CString, hasta 2 args) y convierte el resultado a Texto de la VM |
Cuidado: el puntero viaja como
i64 y se convierte a usize + *const () antes del transmute para que sea válido también en arquitecturas de 32 bits (wasm32). _ffi_llamar_entero soporta hasta 5 argumentos y _ffi_llamar_texto hasta 2; más allá, se retorna error de tipo.Ciclo de vida: el programa debe cargar la librería primero con
importar externa (que llama cargar_libreria), resolver cada función con _ffi_obtener_funcion, y al finalizar liberar_libreria para descargarla del registro global.