Interoperabilidad con C usando dart:ffi
Para usar código C en tu programa Dart, usa la librería dart:ffi.
Las aplicaciones móviles, de línea de comandos y de servidor de Dart
que se ejecutan en la plataforma nativa de Dart (Dart Native platform)
pueden usar la librería dart:ffi para llamar a las APIs nativas de C,
así como para leer, escribir, asignar y liberar memoria nativa.
FFI significa interfaz de funciones externas (foreign function interface).
Otros términos para funcionalidades similares incluyen
interfaz nativa (native interface) y enlaces de lenguaje (language bindings).
La documentación de la API está disponible en la
referencia de la API de dart:ffi.
Descarga los archivos de ejemplo
#Para trabajar con los ejemplos de esta guía,
descarga el directorio completo de ejemplos de ffi.
Este incluye los siguientes ejemplos que muestran cómo usar la librería dart:ffi:
| Example | Description |
|---|---|
| hello_world | Cómo llamar a una función C sin argumentos ni valor de retorno. |
| primitives | Cómo llamar a funciones C que tienen argumentos y valores de retorno que son enteros (ints) o punteros (pointers). |
| structs | Cómo usar structs para pasar cadenas (strings) hacia y desde C y para manejar estructuras C simples y complejas. |
| test_utils | Utilidades de prueba comunes para todos estos ejemplos. |
Revisa el ejemplo hello_world
#El ejemplo hello_world tiene el código mínimo necesario
para llamar a una librería C.
Este ejemplo se puede encontrar en samples/ffi que descargaste en la
sección anterior.
Archivos
#El ejemplo hello_world contiene los siguientes archivos:
| Source file | Description |
|---|---|
hello.dart
|
Un archivo Dart que utiliza la función hello_world() de una librería C. |
pubspec.yaml
|
El archivo pubspec de Dart, con un límite inferior del SDK de 3.4. |
hello_library/hello.h
|
Declara la función hello_world(). |
hello_library/hello.c
|
Un archivo C que importa hello.h y define la función hello_world(). |
hello_library/hello.def
|
Un archivo de definición de módulo que especifica la información utilizada al compilar una DLL. |
hello_library/CMakeLists.txt
|
Un archivo de compilación de CMake para compilar el código C en una librería dinámica. |
La compilación de la librería C crea varios archivos,
incluyendo un archivo de librería dinámica llamado
libhello.dylib (macOS),
libhello.dll (Windows) o
libhello.so (Linux).
Compila y ejecuta
#Los comandos para compilar la librería dinámica y ejecutar la aplicación Dart se parecerían a la siguiente serie.
cd hello_library
cmake .
...
make
...
cd ..
dart pub get
dart run hello.dart
Hello World
Aprovecha dart:ffi
#Para aprender cómo llamar a una función C usando la librería dart:ffi,
revisa el archivo hello.dart.
Esta sección explica el contenido de este archivo.
-
Importa
dart:ffi.dartimport 'dart:ffi' as ffi; -
Importa la librería path que usarás para almacenar la ruta de la librería dinámica.
dartimport 'dart:io' show Platform, Directory; import 'package:path/path.dart' as path; -
Crea un typedef con la firma del tipo FFI de la función C.
Para conocer los tipos más utilizados de acuerdo con la libreríadart:ffi, consulta Interactuar con tipos nativos.darttypedef hello_world_func = ffi.Void Function(); -
Crea un
typedefpara la variable a usar cuando llames a la función C.darttypedef HelloWorld = void Function(); -
Crea una variable para almacenar la ruta de la librería dinámica.
dartfinal String libraryPath; if (Platform.isMacOS) { libraryPath = path.join( Directory.current.path, 'hello_library', 'libhello.dylib', ); } else if (Platform.isWindows) { libraryPath = path.join( Directory.current.path, 'hello_library', 'Debug', 'hello.dll', ); } else { libraryPath = path.join( Directory.current.path, 'hello_library', 'libhello.so', ); } -
Abre la librería dinámica que contiene la función C.
dartfinal dylib = ffi.DynamicLibrary.open(libraryPath); -
Obtén una referencia a la función C y colócala en una variable. Este código utiliza los
typedefsde los pasos 2 y 3, junto con la variable de librería dinámica del paso 4.dartfinal HelloWorld hello = dylib .lookup<ffi.NativeFunction<hello_world_func>>('hello_world') .asFunction(); -
Llama a la función C.
darthello();
Una vez que comprendas el ejemplo hello_world,
consulta los otros ejemplos de dart:ffi.
Empaqueta y carga librerías C
#El método para empaquetar / empaquetar / distribuir y luego cargar una librería C nativa depende de la plataforma y del tipo de librería.
Para aprender cómo, consulta las siguientes páginas y ejemplos.
- Flutter
dart:ffipara aplicaciones Android - Flutter
dart:ffipara aplicaciones iOS - Flutter
dart:ffipara aplicaciones macOS - Ejemplos de
dart:ffi
Interactúa con tipos nativos
#La librería dart:ffi proporciona múltiples tipos que implementan NativeType
y representan tipos nativos en C. Puedes instanciar algunos tipos nativos.
Algunos otros tipos nativos pueden usarse únicamente como marcadores en firmas de tipos.
Pueden instanciar estos marcadores de firma de tipo
#Los siguientes tipos nativos se pueden utilizar como marcadores en firmas de tipos. Ellos o sus subtipos pueden ser instanciados en código Dart.
| Dart type | Description |
|---|---|
| Array | Un array de elementos de tamaño fijo. Supertipo de los arrays específicos de tipo. |
| Pointer | Representa un puntero a la memoria nativa de C. |
| Struct | El supertipo de todos los tipos de struct de FFI. |
| Union | El supertipo de todos los tipos de unión de FFI. |
Sirven únicamente como marcadores de firma de tipo
#La siguiente lista muestra los tipos nativos independientes de la plataforma que sirven como marcadores en firmas de tipos. No se pueden instanciar en código Dart.
| Dart type | Description |
|---|---|
| Bool | Representa un bool nativo en C. |
| Double | Representa un double nativo de 64 bits en C. |
| Float | Representa un float nativo de 32 bits en C. |
| Int8 | Representa un entero nativo de 8 bits con signo en C. |
| Int16 | Representa un entero nativo de 16 bits con signo en C. |
| Int32 | Representa un entero nativo de 32 bits con signo en C. |
| Int64 | Representa un entero nativo de 64 bits con signo en C. |
| NativeFunction | Representa un tipo de función en C. |
| Opaque | El supertipo de todos los tipos opacos en C. |
| Uint8 | Representa un entero nativo de 8 bits sin signo en C. |
| Uint16 | Representa un entero nativo de 16 bits sin signo en C. |
| Uint32 | Representa un entero nativo de 32 bits sin signo en C. |
| Uint64 | Representa un entero nativo de 64 bits sin signo en C. |
| Void | Representa el tipo void en C. |
También existen muchos tipos nativos marcadores específicos de la ABI que extienden AbiSpecificInteger. Para aprender cómo se mapean estos tipos en plataformas específicas, consulta la documentación de la API vinculada en la siguiente tabla.
| Dart type | Description |
|---|---|
| AbiSpecificInteger | El supertipo de todos los tipos de enteros específicos de la ABI. |
| Int | Representa el tipo int en C. |
| IntPtr | Representa el tipo intptr_t en C. |
| Long | Representa el tipo long int (long) en C. |
| LongLong | Representa el tipo long long en C. |
| Short | Representa el tipo short en C. |
| SignedChar | Representa el tipo signed char en C. |
| Size | Representa el tipo size_t en C. |
| UintPtr | Representa el tipo uintptr_t en C. |
| UnsignedChar | Representa el tipo unsigned char en C. |
| UnsignedInt | Representa el tipo unsigned int en C. |
| UnsignedLong | Representa el tipo unsigned long int en C. |
| UnsignedLongLong | Representa el tipo unsigned long long en C. |
| UnsignedShort | Representa el tipo unsigned short en C. |
| WChar | Representa el tipo wchar_t en C. |
Genera enlaces FFI con package:ffigen
#
Para superficies de API grandes, puede llevar mucho tiempo
escribir los enlaces de Dart que se integran con el código C.
Para que Dart cree envolturas (wrappers) FFI a partir de archivos de cabecera (header files) C,
utiliza el generador de enlaces package:ffigen.
Para obtener información sobre el soporte para activos de código (code assets) en Dart FFI,
consulta la referencia de la API de dart:ffi para Native
y DefaultAsset.
Compila y empaqueta código nativo
#Los build hooks de Dart (anteriormente conocidos como native assets) permiten que los paquetes contengan activos de código nativo que se compilan, empaquetan y ponen a disposición en tiempo de ejecución de manera transparente. Para obtener más información, consulta Hooks.
A menos que se indique lo contrario, la documentación en este sitio refleja Dart 3.12.2. Página actualizada por última vez el 2025-09-15. Ver fuente oreportar un problema.