Cómo comenzar a usar código C ++ en su proyecto de Android

El año pasado di una charla en el GDG DevFest en Ankara, Turquía. He estado planeando compartir esa charla aquí desde entonces. Ahora que soy un candidato a doctorado y tengo un poco más de tiempo, estoy poniendo la publicación aquí.

Si desea obtener la presentación, está disponible en mi disco.

Calentar

Me gustaría comenzar explicando el proceso de compilación de una aplicación en Android. Debido a que necesita conocer algunas cosas internas básicas, este tema es algo técnico.

No necesita saber todo lo que se muestra en la imagen de arriba, pero es una buena referencia.

Ahora digamos que escribe una aplicación para Android usando Java. Vas a tener:

  • el código fuente de esa aplicación
  • algún tipo de archivos de recursos (como imágenes o archivos xml para la disposición de la GUI)
  • y quizás algunos archivos AIDL, que son interfaces Java que hacen que los procesos se comuniquen entre sí.

Probablemente también usará bibliotecas adicionales y sus archivos relacionados en su proyecto.

Al crear una aplicación que funcione, primero compila esos códigos fuente juntos. Un compilador producirá un archivo DEX que luego puede ser leído por una máquina virtual. Este archivo legible por máquina y cierta información adicional sobre la aplicación serán empaquetados juntos por un administrador de paquetes. El paquete final, llamado paquete APK, es la aplicación final.

Este es el proceso de construcción de un paquete de Android en los términos más simples.

Tiempo de ejecución de Android

Ahora hablemos del tema del tiempo de ejecución. Tienes una aplicación y cuando comienza a ejecutarse, una máquina la lee. Android tiene dos tipos de máquinas virtuales para ejecutar una aplicación. No presentaré el anterior, llamado Dalvik, ya que hoy en día la mayoría de los dispositivos Android ejecutan una máquina virtual llamada Android Run Time, ART; de eso es de lo que hablaremos aquí.

ART es una máquina virtual anticipada (AOT). ¿Entonces que significa eso? Dejame explicar. Cuando su aplicación comienza a ejecutarse por primera vez, su código se compila en código de máquina que luego puede ser leído por la máquina real. Esto significa que el código no se compila parte por parte en tiempo de ejecución. Esto mejora el tiempo de instalación de la aplicación al tiempo que reduce el uso de la batería.

En resumen, escribe una aplicación y luego la compila en un código binario que el ART lee. Luego, ART convierte ese código en código nativo que puede ser leído por el propio dispositivo.

ARTE y C ++

¿Qué sucede si escribe una aplicación de Android usando Java pero hay algún código C ++ que está en contacto con Java? ¿Cuál es el efecto de ese código C ++ en el proceso de compilación o el tiempo de ejecución de su aplicación? No demasiado.

El código C ++ se compila directamente en el código de la máquina real por su compilador. Entonces, si usa código C ++, se empaquetará como código legible por máquina en su paquete. ART no lo volverá a procesar mientras convierte el código legible ART en código legible por máquina en el primer uso. No necesita preocuparse por este proceso. Solo eres responsable de escribir una interfaz que permita a Java comunicarse con C ++. Vamos a hablar de eso pronto.

Proceso de compilación de C ++

Ahora tenemos que hablar sobre el proceso de compilación de C ++. El código fuente (los archivos .cpp y .h) se convierte en código fuente expandido por un preprocesador en el primer paso. Este código fuente contiene una gran cantidad de código. Si bien puede obtener el archivo ejecutable final usando un comando como el anterior, es posible cortar los pasos de compilación con indicadores relacionados. Puede obtener la fuente extendida dando la bandera -E al compilador g ++ . Tengo un archivo de línea 40867 para un código fuente .cpp 'hola mundo' de 4 líneas.

Utilice g ++ -E hello.cpp -o hello.ii para obtener el código fuente extendido.

El segundo es el paso de compilación real. El compilador compila nuestro código para obtener un archivo ensamblador. Entonces, la compilación real produce un archivo ensamblador, no el ejecutable. Este archivo lo ensambla un ensamblador. El código resultante se llama código objeto. Cuando tenemos varias bibliotecas destinadas a vincularse entre sí, tenemos muchos códigos de objeto. Estos códigos de objeto están vinculados por un enlazador. Luego obtenemos un ejecutable.

Hay dos tipos de enlaces: dinámicos y estáticos.

Así que ahora es el momento de profundizar un poco más mientras discutimos cosas de C ++ puro.

Lo importante: puede considerar las bibliotecas vinculadas estáticas como parte de su código. Así que tenga cuidado cuando vincule una biblioteca a su proyecto. Porque es posible que la biblioteca que utilice no tenga una licencia adecuada para vincularse estáticamente. La mayoría de las bibliotecas de código abierto se han restringido para su uso como vinculadas dinámicamente.

Desde un punto de vista técnico, el compilador vincula una biblioteca enlazada estáticamente al proyecto en el momento de la compilación. Por otro lado, una biblioteca vinculada dinámicamente está vinculada por el sistema operativo en tiempo de ejecución. Por lo tanto, no necesita distribuir su proyecto con el código de biblioteca que usa. También puede utilizar la biblioteca del sistema o la biblioteca de otro proyecto.

Debido a este hecho, la vinculación dinámica puede causar vulnerabilidad en su proyecto. Sin embargo, aunque el caso de seguridad está fuera del alcance de esta publicación.

Algunos conceptos

CMake y Gradle

Si queremos agregar código C ++ en nuestro proyecto de Android, es bueno usar CMake para manejar las operaciones de compilación. ¿Recuerda el proceso de construcción que acabo de presentar arriba? Cuando tienes un montón de bibliotecas C ++ y código fuente, se vuelve más complicado manejarlos todos. Una herramienta como CMake facilita la realización del proceso de construcción.

CMake estará disponible de forma predeterminada cuando elija incluir compatibilidad con C ++ al inicio de su proyecto. También debe usar un cierre de Gradle para empaquetar bibliotecas en su APK.

ABI

Como saben, Android se distribuye para una variedad de dispositivos. Cada dispositivo puede tener una arquitectura de CPU diferente. Cuando desarrolla una aplicación de Android que contiene código C ++, debe preocuparse por las plataformas en las que se ejecutará su aplicación.

¿Recuerda el mecanismo de compilación de C ++ que presenté anteriormente? El código C ++ debe compilarse como una biblioteca para cada plataforma a la que se dirija. Puede compilar la biblioteca para todas las plataformas compatibles o puede optar por compilarla solo para una plataforma.

Tenga en cuenta que la compatibilidad con ABI de 64 bits será obligatoria con la versión de Android Pie si desea colocar su aplicación en Google Play Store.

JNI

Esto es lo último que me gustaría presentarles sobre el uso de C ++ en Android. Como mencioné anteriormente, le presento estos conceptos considerando que desea desarrollar una aplicación usando Java.

JNI es una abreviatura de Java Native Interface. Permite que las partes de C ++ y Java se comuniquen entre sí en los términos más simples. Por ejemplo, si desea llamar a una función desde C ++ en Java, debe escribir una interfaz JNI para este propósito.

Native-lib.cpp es la interfaz y conecta el código C ++ con el código Java. En el ejemplo anterior, el único código C ++ es el propio JNI. Sin embargo, puede incluir las bibliotecas que desea usar e implementar una función que las llame. Esta nueva función se puede llamar desde la parte de Java. Entonces funciona como un puente de esa manera.

Cosas que hacer en caso de que quieras probarlo

Aquí tienes todos los conocimientos básicos y necesarios para utilizar C ++ en tu proyecto de Android. Si quieres probarlo, así es como crear un proyecto de Android simple con código C ++.

Las siguientes imágenes le muestran los pasos para iniciar un proyecto de este tipo. Después de terminarlos, es posible que desee leer esta publicación para modificar y comprender el mecanismo más profundamente.

Esta publicación fue solo una introducción. No olvide que hay muchas más cosas que aprender. Sin embargo, mi objetivo era presentarles las cosas más importantes sobre el concepto de uso de C ++.