Cómo usar la biblioteca boost (incluido shared_ptr) con Android NDK y STLport

6 minutos de lectura

avatar de usuario
Gama Draconis

Esto es más una respuesta que una pregunta, porque lo he descubierto, al menos en lo que respecta a la compilación limpia de la biblioteca. El principal problema para mí fue hacer que shared_ptr funcionara.

Ingredientes:

Boost versión 1.45.0

La versión de STLport en http://www.anddev.org/viewtopic.php?p=29939.

Versión r4b del NDK.

Direcciones:

En su archivo Android.mk agregue:

LOCAL_CFLAGS += -DBOOST_EXCEPTION_DISABLE -D_STLP_NO_EXCEPTIONS -DOS_ANDROID -D_STLP_USE_SIMPLE_NODE_ALLOC

Elimine la llamada a __stl_throw_length_error en la línea 613 de stlport/stl/_string.h. Puede usar _STLP_NO_EXCEPTIONS si lo desea.

Edite boost/boost/smart_ptr/shared_ptr.hpp después de la línea 261 para deshacerse de la llamada a boost::throw_exception en el constructor shared_ptr. Usé #ifndef BOOST_EXCEPTION_DISABLE en todo el cuerpo del método. (Pero vea la respuesta a continuación).

A continuación, debe proporcionar algunas piezas faltantes. Cree un archivo de encabezado con lo siguiente:

#ifdef OS_ANDROID

#include <exception>

namespace std
{
    struct bad_alloc : public exception { bad_alloc operator()(){}};
}

#endif

y un archivo fuente con una clase de excepción simplificada para admitir bad_alloc:

#ifdef OS_ANDROID

#include <exception>

namespace std
{
    exception::exception() {}
    exception::~exception() {}
    const char* exception::what() const {}
}

#endif

Incluya el encabezado dondequiera que esté incluyendo boost/shared_ptr.hpp. Compile la fuente y agréguela a su biblioteca.

  • Para evitar que esta pregunta quede abierta para siempre, sería genial si pudiera reformular esta publicación como una pregunta y luego responderla usted mismo, como se sugiere en las preguntas frecuentes.

    – dennycrane

    3 de diciembre de 2010 a las 15:49

  • ¡Gracias por compartir lo que has aprendido! Estoy seguro de que esto es útil para muchos.

    – Daniel Lidström

    3 de diciembre de 2010 a las 16:08

  • Dennycrane, todavía estoy experimentando con este enfoque, así que quiero dejarlo un poco abierto en caso de que haya más para agregar. Cuando obtenga una biblioteca que funcione correctamente, lo informaré y cerraré la pregunta con una respuesta.

    – Gamma Draconis

    5 de diciembre de 2010 a las 20:16

  • Estoy de acuerdo con @dennycrane en lo que sería mejor en el futuro, pero mucho más importante es el hecho de que se tomó el tiempo de publicar esta guía útil en SO en cualquier formato en el que la publique. Ya la encontré útil y ni siquiera he tenido la oportunidad de leerlo; el simple hecho de saber que esto es posible me ayudará mucho a diseñar mi proyecto actual. Gracias por ahorrarme a mí, y a muchas otras personas, el tiempo de encontrar la respuesta de la misma manera que lo hiciste tú, sin una pregunta que te incitara.

    – Daniel H.

    2 de mayo de 2012 a las 9:59


Resultó que este enfoque no funciona del todo cuando se compila una biblioteca depurable. La biblioteca de lanzamiento se compila con -O2, lo que optimiza algunas infelicidades, pero la biblioteca de depuración se realiza con -O0, lo que revela algunos problemas adicionales. Además, no estaba muy contento de tener que editar los archivos de impulso. Entonces, con un poco de estudio adicional, se me ocurrió la siguiente solución.

Primero, no edite ninguno de los archivos boost. En su lugar, agregue lo siguiente al encabezado dentro del espacio de nombres estándar:

struct bad_cast : public exception {bad_cast operator()(){}};

A continuación, agregue lo siguiente al archivo fuente:

namespace boost
{
    void throw_exception(std::exception const&) {}
}

Esto ahora compila y vincula la aplicación incluso con android:debuggable=”true” en AndroidManifest.xml. No se ejecuta en el emulador, pero tampoco lo estaba haciendo antes de incluir esta biblioteca.

  • Te di tantos votos a favor como pude. Pasé alrededor de 1 día completo trabajando para resolver esto, y encontrar esto fue de gran ayuda.

    usuario562566

    16 de septiembre de 2011 a las 12:22

  • Y dado que, de hecho, respondió a su propia pregunta como se sugirió anteriormente, merece otro voto a favor. Desearía que más personas (incluyéndome, desafortunadamente, a mí mismo) pensaran en publicar sus soluciones encontradas aquí sin que nadie más se lo pida.

    – Daniel H.

    2 de mayo de 2012 a las 10:04

En particular, NDK r5 viene con STLport y GNU STL, por lo que los trucos aquí ya no serán necesarios ahora que hay a) compatibilidad con STL b) compatibilidad con excepciones en el compilador NDK C++.

  • Sus puntos a y b son verdaderos individualmente, pero no en combinación (consulte la ADVERTENCIA en la sección III de CPLUSPLUS-SUPPORT.html en la documentación de nkd). En consecuencia, aún necesitará std::bad_alloc, std::bad_cast y boost::throw_exception hacks que discutí.

    – Gamma Draconis

    9 de diciembre de 2010 a las 5:03

  • Es extraño. La documentación que cité anteriormente no se refiere en absoluto a GNU STL, excepto para decir que el “soporte completo de GNU libstdc++” es un plan futuro. Pero ahí está en el NDK bajo fuentes/cxx-stl junto con su sistema mínimo y stlport. ¿Has conseguido que funcione? Tomo nota de una discusión en curso sobre el tema en grupos.google.com/group/android-ndk/browse_thread/thread/….

    – Gamma Draconis

    9 de diciembre de 2010 a las 6:26

  • Parece ser mencionado en la página de NDK en desarrollador.android.com/sdk/ndk/index.html y no en los documentos. cita “Proporciona una implementación STL de C++ predeterminada (basada en STLport) como un módulo auxiliar. Se puede usar como una biblioteca estática o compartida (los detalles y los ejemplos de uso se encuentran en source/android/stlport/README). Binarios precompilados para STLport ( estático o compartido) y GNU libstdc++ (solo estático)” Parece que libstdc++ funciona con excepciones y RTTI.

    – grussel

    9 de diciembre de 2010 a las 14:13


  • Puedo compilar con él, pero la etapa de enlace de la biblioteca va mal con muchos errores de referencia indefinidos. Probé un LOCAL_LDLIBS explícito += -lstdc++ pero no ayudó. ¿Ha conseguido que APP_STL := gnustl_static funcione?

    – Gamma Draconis

    9 de diciembre de 2010 a las 16:45


  • Sí, me funciona ™. No necesitaba adiciones explícitas a los argumentos ld para el STL; para cada otra biblioteca que construyo y uso, pero no para el STL en sí. Puede verificar con un hola mundo usando std::vector o similar.

    – grussel

    9 de diciembre de 2010 a las 17:09


Otra solución para shared_ptr en particular es usar boost::intrusive_ptr en su lugar. Esto no siempre es posible, pero funcionó para mi situación.

  • También puede usar extract shared_ptr de shared_ptr_nmt.hpp con bastante facilidad, es una versión simplificada.

    – Chris

    31 de enero de 2012 a las 2:36

La versión actual de Android NDK (r9) ahora admite excepciones.

Las capacidades de los distintos tiempos de ejecución varían. Ver esta tabla:

          C++       C++   Standard
          Exceptions  RTTI  Library
system    no           no        no
gabi++   yes          yes        no
stlport  yes          yes       yes
gnustl   yes          yes       yes

stlport puede usarse en binarios que no sean GPL. Todavía está marcado como experimental, pero puedes usarlo con clang y gcc.

Ver http://developer.android.com/tools/sdk/ndk/

¿Ha sido útil esta solución?