Vincular con código nativo usando el template de plugin FFI heredado
Usa el template de plugin FFI heredado y dart:ffi para vincular con código C nativo en tu plugin o aplicación Flutter.
Las aplicaciones móviles y de escritorio de Flutter pueden
usar la biblioteca dart:ffi
para llamar a las API nativas de C.
FFI significa foreign function interface.
Otros términos para una funcionalidad similar incluyen
interfaz nativa y bindings de lenguaje.
Antes de que tu biblioteca o programa pueda usar la biblioteca FFI para vincularse con código nativo, debes asegurarte de que el código nativo esté cargado y sus símbolos sean visibles para Dart. Esta página se centra en compilar, empaquetar, y cargar código nativo dentro de un plugin o aplicación Flutter.
Este tutorial demuestra cómo empaquetar fuentes de C/C++
en un plugin de Flutter y vincularlos usando la biblioteca FFI de Dart.
En este tutorial paso a paso, crearás una función de C que
implementa la suma de 32 bits y luego la expone a través
de un plugin de Dart llamado native_add.
Enlace dinámico versus estático
#Una biblioteca nativa se puede vincular a una aplicación de forma dinámica o estática. Una biblioteca vinculada estáticamente se incrusta en la imagen ejecutable de la aplicación, y se carga cuando la aplicación se inicia.
Los símbolos de una biblioteca vinculada estáticamente se pueden
cargar usando DynamicLibrary.executable
o
DynamicLibrary.process.
Una biblioteca vinculada dinámicamente, por el contrario, se distribuye en un archivo o carpeta independiente dentro de la aplicación, y se carga bajo demanda. El formato de distribución depende de la plataforma:
- En Android, una biblioteca vinculada dinámicamente se distribuye como un
conjunto de archivos
.so(ELF), uno para cada arquitectura. Solo se admiten bibliotecas dinámicas, porque el ejecutable principal es la JVM, la cual Flutter no vincula estáticamente. - En iOS y macOS, la biblioteca vinculada dinámicamente se
distribuye como una carpeta
.framework.
Una biblioteca vinculada dinámicamente se puede cargar en
Dart usando DynamicLibrary.open.
Crear un plugin FFI
#Para crear un plugin FFI llamado native_add,
usa flutter create con el template plugin_ffi:
flutter create --platforms=android,ios,macos,windows,linux --template=plugin_ffi native_add
Esto crea un plugin con fuentes C/C++ en native_add/src.
Estos fuentes se compilan mediante los archivos de compilación nativos en las
diversas carpetas de compilación del SO.
La biblioteca FFI solo puede vincularse contra símbolos de C,
por lo que en C++ estos símbolos se marcan como extern "C".
También debes agregar atributos para indicar que los
símbolos están referenciados desde Dart,
para evitar que el enlazador descarte los símbolos
durante la optimización en tiempo de enlace:
__attribute__((visibility("default"))) __attribute__((used)).
El archivo de compilación específico de la plataforma vincula el código:
- En Android,
native_add/android/build.gradle. - En iOS,
native_add/ios/native_add.podspec. - En macOS,
native_add/macos/native_add.podspec. - En Linux,
native_add/linux/CMakeLists.txt. - En Windows,
native_add/windows/CMakeLists.txt.
El código nativo se invoca desde
Dart en lib/native_add_bindings_generated.dart.
Los bindings se generan con package:ffigen.
Otros casos de uso
#iOS
#El enlazador dinámico carga automáticamente
las bibliotecas vinculadas dinámicamente cuando se inicia la aplicación.
Sus símbolos constituyentes pueden resolverse usando DynamicLibrary.process.
También puedes obtener una referencia a la biblioteca con DynamicLibrary.open
para
restringir el alcance de la resolución de símbolos, pero
no está claro cómo maneja esto el proceso de revisión de Apple.
Los símbolos vinculados estáticamente en el binario de la aplicación pueden
resolverse usando DynamicLibrary.executable
o DynamicLibrary.process.
Biblioteca de la plataforma
#Para vincular con una biblioteca de la plataforma, sigue estas instrucciones:
- En Xcode, abre
Runner.xcworkspace. - Seleccionar la plataforma de destino.
- Haz clic en + en la sección Linked Frameworks and Libraries.
- Seleccionar la biblioteca del sistema con la que vincular.
Biblioteca propia (first-party)
#Una biblioteca nativa propia (first-party) se puede incluir ya sea
como código fuente o como un archivo .framework (firmado).
Probablemente sea posible incluir también archivos de almacenamiento vinculados
estáticamente, pero requiere pruebas.
Código fuente
#Para vincular directamente al código fuente, sigue estas instrucciones:
En Xcode, abre
Runner.xcworkspace.-
Añade los archivos de código fuente de C/C++/Objective-C/Swift al proyecto de Xcode.
-
Añade el siguiente prefijo a las declaraciones de símbolos exportados para asegurarte de que sean visibles para Dart:
C/C++/Objective-C:
objcextern "C" /* <= C++ only */ __attribute__((visibility("default"))) __attribute__((used))Swift:
swift@_cdecl("myFunctionName")
Biblioteca compilada (dinámica)
#Para vincular a una biblioteca dinámica compilada, sigue estas instrucciones:
- Si se encuentra presente un archivo
Frameworkcorrectamente firmado, abreRunner.xcworkspace. - Añade el archivo de framework a la sección Frameworks, Libraries, and Embedded Content del target en Xcode.
- Bajo la columna Embed, selecciona Embed & Sign.
Biblioteca de terceros de código abierto (open-source)
#Para crear un plugin de Flutter que incluya tanto código de C/C++/Objective-C como código de Dart, sigue estas instrucciones:
- En el proyecto de tu plugin, abre
ios/<myproject>.podspec. - Añade el código nativo al campo
source_files.
El código nativo se vinculará entonces estáticamente en el binario de la aplicación de cualquier aplicación que use este plugin.
Biblioteca de terceros de código cerrado (closed-source)
#Para crear un plugin de Flutter que incluya código fuente de Dart, pero distribuya la biblioteca C/C++ en formato binario, sigue estas instrucciones:
- En el proyecto de tu plugin, abre
ios/<myproject>.podspec. - Añade un campo
vendored_frameworks. Consulta el ejemplo de CocoaPods.
Eliminación de símbolos (stripping)
#Al crear una compilación de lanzamiento (release), Xcode elimina los símbolos.
- En Xcode, selecciona el target Runner, luego ve a Build Settings > Strip Style.
- Cambia de All Symbols a Non-Global Symbols.
macOS
#El enlazador dinámico carga automáticamente
las bibliotecas vinculadas dinámicamente cuando se inicia la aplicación.
Sus símbolos constituyentes pueden resolverse usando DynamicLibrary.process.
También puedes obtener una referencia a la biblioteca con DynamicLibrary.open
para
restringir el alcance de la resolución de símbolos, pero
no está claro cómo maneja esto el proceso de revisión de Apple.
Los símbolos vinculados estáticamente en el binario de la aplicación pueden
resolverse usando DynamicLibrary.executable
o DynamicLibrary.process.
Biblioteca de la plataforma
#Para vincular con una biblioteca de la plataforma, sigue estas instrucciones:
- En Xcode, abre
Runner.xcworkspace. - Seleccionar la plataforma de destino.
- Haz clic en + en la sección Linked Frameworks and Libraries.
- Seleccionar la biblioteca del sistema con la que vincular.
Biblioteca propia (first-party)
#Una biblioteca nativa propia (first-party) se puede incluir ya sea
como código fuente o como un archivo .framework (firmado).
Probablemente sea posible incluir también archivos de almacenamiento vinculados
estáticamente, pero requiere pruebas.
Código fuente
#Para vincular directamente al código fuente, sigue estas instrucciones:
En Xcode, abre
Runner.xcworkspace.-
Añade los archivos de código fuente de C/C++/Objective-C/Swift al proyecto de Xcode.
-
Añade el siguiente prefijo a las declaraciones de símbolos exportados para asegurarte de que sean visibles para Dart:
C/C++/Objective-C:
objcextern "C" /* <= C++ only */ __attribute__((visibility("default"))) __attribute__((used))Swift:
swift@_cdecl("myFunctionName")
Biblioteca compilada (dinámica)
#Para vincular a una biblioteca dinámica compilada, sigue estas instrucciones:
- Si se encuentra presente un archivo
Frameworkcorrectamente firmado, abreRunner.xcworkspace. - Añade el archivo de framework a la sección Frameworks, Libraries, and Embedded Content del target en Xcode.
- Bajo la columna Embed, selecciona Embed & Sign.
Biblioteca compilada (dinámica), de código cerrado
#Para añadir una biblioteca de código cerrado a una aplicación de Flutter macOS Desktop, sigue estas instrucciones:
- Sigue las instrucciones para Flutter desktop para crear una aplicación Flutter desktop.
-
Open the
yourapp/macos/Runner.xcworkspacein Xcode.- Arrastra tu biblioteca precompilada (
libyourlibrary.dylib) aRunner/Frameworks. - Click
Runnerand go to theBuild Phasestab.- Arrastra
libyourlibrary.dyliba la listaCopy Bundle Resources. - Bajo
Embed Libraries, marcaCode Sign on Copy. - Bajo
Link Binary With Libraries, establece el estado enOptional. (Usamos enlace dinámico, no es necesario vincular estáticamente).
- Arrastra
- Click
Runnerand go to theGeneraltab.- Arrastra
libyourlibrary.dyliba la lista Frameworks, Libraries, and Embedded Content. - Selecciona Embed & Sign.
- Arrastra
- Click Runner and go to the Build Settings tab.
- En la sección Search Paths configura los
Library Search Paths para incluir la ruta
donde se encuentra
libyourlibrary.dylib.
- En la sección Search Paths configura los
Library Search Paths para incluir la ruta
donde se encuentra
- Arrastra tu biblioteca precompilada (
-
Edit
lib/main.dart.- Usa
DynamicLibrary.open('libyourlibrary.dylib')para vincular dinámicamente los símbolos. - Llama a tu función nativa en algún lugar de un Widget.
- Usa
- Ejecuta
flutter runy comprueba que se llame a tu función nativa. - Ejecuta
flutter build macospara compilar una versión de lanzamiento autónoma de tu aplicación.
Eliminación de símbolos (stripping)
#Al crear una compilación de lanzamiento (release), Xcode elimina los símbolos.
- En Xcode, selecciona el target Runner, luego ve a Build Settings > Strip Style.
- Cambia de All Symbols a Non-Global Symbols.
Android
#Biblioteca de la plataforma
#Para vincular con una biblioteca de la plataforma, sigue estas instrucciones:
-
Busca la biblioteca deseada en la lista Android NDK Native APIs en la documentación de Android. Esta lista contiene API nativas estables.
-
Carga la biblioteca usando
DynamicLibrary.open. Por ejemplo, para cargar OpenGL ES (v3):dartDynamicLibrary.open('libGLES_v3.so');
Es posible que necesites actualizar el archivo del manifiesto de Android de la aplicación o plugin si así lo indica la documentación.
Biblioteca propia (first-party)
#El proceso para incluir código nativo en formato de código fuente o binario es el mismo para una aplicación o un plugin.
Biblioteca de terceros de código abierto (open-source)
#Sigue las instrucciones de Añadir código C y C++ a tu proyecto
en la documentación de Android para
añadir código nativo y soporte para la cadena de herramientas de código nativo (ya sea CMake o ndk-build).
Biblioteca de terceros de código cerrado (closed-source)
#Para crear un plugin de Flutter que incluya código fuente de Dart, pero distribuya la biblioteca C/C++ en formato binario, sigue estas instrucciones:
- Abre el archivo
android/build.gradlede tu proyecto. - Añade el artefacto AAR como una dependencia. No incluyas el artefacto en tu paquete Flutter. En su lugar, debe descargarse desde un repositorio, como Maven Central.
Tamaño del APK de Android (compresión de objetos compartidos)
#Las directrices de Android en general recomiendan distribuir objetos compartidos nativos sin comprimir porque eso en realidad ahorra espacio en el dispositivo. Los objetos compartidos se pueden cargar directamente desde el APK en lugar de desempaquetarlos en el dispositivo en una ubicación temporal y luego cargarlos. Además, los APK se empaquetan en tránsito; es por eso que deberías fijarte en el tamaño de descarga.
De forma predeterminada, los APK de Flutter comprimen libflutter.so y libapp.so,
lo que resulta en un tamaño de APK más pequeño pero un mayor tamaño ocupado en el dispositivo.
Para controlar si las bibliotecas nativas se almacenan comprimidas y se extraen al
instalar, establece la opción useLegacyPackaging del plugin de Android Gradle.
Para ver las recomendaciones actuales, consulta las directrices de Android.
Otros recursos
#Para obtener más información sobre la interoperabilidad de C, echa un vistazo a estos videos:
A menos que se indique lo contrario, la documentación de este sitio refleja Flutter 3.44.0. Página actualizada por última vez el 2026-06-08. Ver código fuente oreportar un problema.