Pregunta

¡Mañana!

He creado un pequeño proyecto NDK que permite la serialización dinámica de objetos entre Java y C ++ a través de JNI. La lógica funciona así:

Bean -> javacinterface.java -> javacinterface.cpp -> javacinterface.java -> bean

El problema es que quiero usar esta funcionalidad en otros proyectos. Separé el código de prueba del proyecto y creé un proyecto de "probador". El proyecto del probador envía un objeto Java a C ++ que luego lo hace volver a la capa Java.

Pensé que vincular sería bastante simple: ("simple" en términos de NDK/JNI suele ser un día de frustración) Agregué el proyecto Jnibridge como un proyecto fuente e incluye las siguientes líneas a Android.mk:

NDK_MODULE_PATH=.../JNIBridge/jni/"

Jnibridge/jni/javacinterface/android.mk:

...
include $(BUILD_STATIC_LIBRARY)

JNITESTER/JNI/Android.mk:

...
include $(BUILD_SHARED_LIBRARY)
$(call import-module, JavaCInterface)

Todo esto funciona bien. Los archivos C ++ que se basan en encabezados del módulo JavaCinterface funcionan bien. Además, las clases de Java pueden usar felizmente interfaces del proyecto Jnibridge. Todo el enlace es feliz.

Desafortunadamente, javacinterface.java, que contiene las llamadas del método nativo, no puede ver el método JNI ubicado en la biblioteca estática. (Lógicamente están en el mismo proyecto, pero ambos se importan al proyecto donde desea usarlos a través del mecanismo anterior).

Mis soluciones actuales son seguidas. Espero que alguien pueda sugerir algo que preserve la naturaleza modular de lo que estoy tratando de lograr:


Mi solución actual sería incluir los archivos CPP JavaCinterface en el proyecto de llamadas como así:

LOCAL_SRC_FILES := FunctionTable.cpp $(PATH_TO_SHARED_PROJECT)/JavaCInterface.cpp

Pero prefiero no hacer esto, ya que me llevaría a la necesidad de actualizar cada proyecto dependiendo si cambié la arquitectura Javacinterface.


Podría crear un nuevo conjunto de firmas de método JNI en cada proyecto local que luego se vincule a los módulos importados. Nuevamente, esto une las implementaciones con demasiada fuerza.

¿Fue útil?

Solución

Después de mucho sudor de sangre y lágrimas, he descubierto esto.

  • Android Jni carga su binario desde un SHARED_LIBRARY solamente.
  • JNI intentará vincular las llamadas nativas a las firmas/trozos de método apropiado desde la biblioteca compartida cargada (no buscará bibliotecas compartidas vinculadas).
  • Puede crear una biblioteca estática con estos métodos y incorporarla en la biblioteca compartida utilizada por su aplicación.

Puede construir su biblioteca estática en su proyecto original utilizando el siguiente código en su androd.xml:

include $(CLEAR_VARS)
LOCAL_CFLAGS    := -O0
LOCAL_MODULE    := LibraryToBeUsedInsideSharedLib
LOCAL_SRC_FILES := ...
include $(BUILD_STATIC_LIBRARY) // This builds a "Static Object" here:
                                // /Project/obj/local/armeabi/libLibraryToBeUsedInsideSharedLib.a

include $(CLEAR_VARS)
LOCAL_MODULE       := LibraryCalledFromJava
LOCAL_SRC_FILES    := ...
LOCAL_STATIC_LIBRARIES := LibraryToBeUsedInsideSharedLib
include $(BUILD_SHARED_LIBRARY)

LOCAL_STATIC_LIBRARIES Incluye la biblioteca estática en su biblioteca compartida. En su código Java ahora puede llamar a esto:

System.loadLibrary("LibraryCalledFromJava");

Debería poder llamar a cualquier método nativo ubicado dentro del LibraryToBeUsedInsideSharedLib Biblioteca desde cualquier punto de su código Java.

Puedes exportar el libLibraryToBeUsedInsideSharedLib.a Archivo y úselo en otros proyectos agregando esto al Android.xml del proyecto externo:

include $(CLEAR_VARS)
LOCAL_MODULE            := LibraryToBeUsedInsideSharedLib
LOCAL_LDLIBS            := -llog/
LOCAL_SRC_FILES         := $(MY_PREBUILT_LIB_DIR)/libLibraryToBeUsedInsideSharedLib.a
include $(PREBUILT_STATIC_LIBRARY)
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top