¿Impedir que las funciones sean eliminadas de una biblioteca estática cuando están enlazadas en una biblioteca compartida?

Tengo una biblioteca estática, Foo, que es utilizada por una biblioteca compartida, barra. Bar es la biblioteca compartida nativa cargada por mi aplicación de Android. Foo contiene funciones JNI que sólo son llamadas por código Java y no por ningún código C ++ en Bar. Debido a esto, esas funciones JNI se eliminan de la biblioteca estática (Foo) cuando se crea la biblioteca compartida (Barra). Actualmente utilizo un método ligeramente hacky para evitar que eso suceda.

Así que, en este caso, ¿hay una manera de decirle al compilador que no quita las funciones de JNI (o ninguna) al vincularlas?

2 Solutions collect form web for “¿Impedir que las funciones sean eliminadas de una biblioteca estática cuando están enlazadas en una biblioteca compartida?”

No están siendo despojados, están siendo ignorados. Cuando la biblioteca compartida está vinculada, el vinculador sólo está extrayendo los archivos de objeto con funciones que se utilizan realmente. (Así se definen las librerías estáticas para trabajar.)

Creo que pasar la bandera "–whole-archive" al enlazador hará que tire de todos los archivos de objetos de una biblioteca estática. Puede proporcionarlo en la línea de enlace gcc con "-Wl, -whole-archive". Debes seguirlo con "-Wl, -no-whole-archive" después de especificar tu biblioteca, o ld continuará el comportamiento de cualquier otra biblioteca estática que encuentre, lo cual probablemente no sea el comportamiento que deseas. Consulte también la página del manual ld (1) en un sistema Linux.

Otra forma de lograr lo mismo es generar un solo archivo masivo .o en lugar de un archivo .a.

EDIT: ejemplo de línea de comandos simple, utilizando libz en el escritorio:

% echo "int main() { return 0; }" > foo.c % gcc -o foo /usr/lib/libz.a foo.c % ls -s foo 12 foo* % gcc -o foo -Wl,-whole-archive /usr/lib/libz.a -Wl,-no-whole-archive foo.c % ls -s foo 104 foo* 

(Tienes que usar "/usr/lib/libz.a" en lugar de "-lz" aquí porque éste encuentra la biblioteca compartida /usr/lib/libz.so.)

No he utilizado el NDK mucho, pero parece que añadir las banderas a LOCAL_LDFLAGS podría hacer el truco.

Empecemos con la muestra básica de dos libras de NDK . Aquí está su archivo original de Android.mk:

  1 # Copyright (C) 2009 The Android Open Source Project 2 # 3 # Licensed under the Apache License, Version 2.0 (the "License"); 4 # you may not use this file except in compliance with the License. 5 # You may obtain a copy of the License at 6 # 7 # http://www.apache.org/licenses/LICENSE-2.0 8 # 9 # Unless required by applicable law or agreed to in writing, software 10 # distributed under the License is distributed on an "AS IS" BASIS, 11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 # See the License for the specific language governing permissions and 13 # limitations under the License. 14 # 15 16 # the purpose of this sample is to demonstrate how one can 17 # generate two distinct shared libraries and have them both 18 # uploaded in 19 # 20 21 LOCAL_PATH:= $(call my-dir) 22 23 # first lib, which will be built statically 24 # 25 include $(CLEAR_VARS) 26 27 LOCAL_MODULE := libtwolib-first 28 LOCAL_SRC_FILES := first.c 29 30 include $(BUILD_STATIC_LIBRARY) 31 32 # second lib, which will depend on and include the first one 33 # 34 include $(CLEAR_VARS) 35 36 LOCAL_MODULE := libtwolib-second 37 LOCAL_SRC_FILES := second.c 38 39 LOCAL_STATIC_LIBRARIES := libtwolib-first 40 41 include $(BUILD_SHARED_LIBRARY) 

Tenga en cuenta que la función JNI se encuentra en second.c que no forma parte de la libtwolib-first estática libtwolib-first .

Primero, reproduzcamos su problema. El cambio es simple:

 ... 27 LOCAL_MODULE := libtwolib-first 28 LOCAL_SRC_FILES := first.c second.c ... 36 LOCAL_MODULE := libtwolib-second 37 LOCAL_SRC_FILES := 

Si ejecuta el proyecto modificado, obtendrá el siguiente error:

 E/AndroidRuntime( 4213): FATAL EXCEPTION: main E/AndroidRuntime( 4213): java.lang.UnsatisfiedLinkError: add E/AndroidRuntime( 4213): at com.example.twolibs.TwoLibs.add(Native Method) E/AndroidRuntime( 4213): at com.example.twolibs.TwoLibs.onCreate(TwoLibs.java:39) E/AndroidRuntime( 4213): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047) E/AndroidRuntime( 4213): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2627) E/AndroidRuntime( 4213): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679) E/AndroidRuntime( 4213): at android.app.ActivityThread.access$2300(ActivityThread.java:125) E/AndroidRuntime( 4213): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2033) E/AndroidRuntime( 4213): at android.os.Handler.dispatchMessage(Handler.java:99) E/AndroidRuntime( 4213): at android.os.Looper.loop(Looper.java:123) E/AndroidRuntime( 4213): at android.app.ActivityThread.main(ActivityThread.java:4627) E/AndroidRuntime( 4213): at java.lang.reflect.Method.invokeNative(Native Method) E/AndroidRuntime( 4213): at java.lang.reflect.Method.invoke(Method.java:521) E/AndroidRuntime( 4213): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:871) E/AndroidRuntime( 4213): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:629) E/AndroidRuntime( 4213): at dalvik.system.NativeStart.main(Native Method) 

Explicó este problema con precisión: el vinculador "eliminó" la entrada "no utilizada" Java_com_example_twolibs_TwoLibs_add ().

Ahora vamos a arreglar esto:

  39 LOCAL_STATIC_LIBRARIES: = libtwolib-first
 39 LOCAL_WHOLE_STATIC_LIBRARIES: = libtwolib-first 

¡Y otra vez la muestra trabaja!

  • JNI y Gradle en Android Studio
  • Android, genera archivos de encabezado jni con javah, muestra error que no puede encontrar org.opencv.core.Mat
  • Android JNI: root-making deadd00d (dvmAbort)
  • Compilar Java para Android nativo en lugar de escribir en C
  • Utilizar bibliotecas jni de 32 bits en android de 64 bits
  • Es una pérdida de una sola vez de referencia a la memoria nativa asignada por una aplicación Android un gran negocio?
  • ¿Por qué algunos teléfonos Android hacen que nuestra aplicación lance un java.lang.UnsatisfiedLinkError?
  • Android ffmpeg simple JNI envoltorio
  • Android ICS 4.0 NDK NewStringUTF se está estrellando la aplicación
  • Ejecutar código en el subproceso principal / UI en Cocos2dx
  • JNI proguard obfuscation
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.