Android NDK:使用的静态库与指定的预编译库不同

时间:2013-11-22 05:03:56

标签: android c++ android-ndk java-native-interface

我使用Android SDK编译器手动构建C ++库。结果是libMyUtils.a。

我在Java / JNI测试应用程序中使用以下内容:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE    := MyUtils
LOCAL_SRC_FILES := ../../../../libs/libMyUtils.a

include $(PREBUILT_STATIC_LIBRARY)

LOCAL_MODULE    := AndroidTests
LOCAL_STATIC_LIBRARIES    := MyUtils

include $(BUILD_SHARED_LIBRARY)

构建控制台时显示以下内容:

[armeabi] Install        : libMyUtils.so => libs/armeabi/libMyUtils.so

现在由于一些奇怪的原因,库../../../../libs/libMyUtils.a是几兆字节,但库libs / armeabi / libMyUtils.so只有5KB。它不应该是同一个图书馆吗?

当我运行我的测试应用程序时,我得到UnsatisfiedLinkError。显然我正在调用的本机函数不在库中。我做错了什么?

3 个答案:

答案 0 :(得分:0)

一个完整的解释,因为你的Android.mk对我来说没有多大意义:对不起,如果你已经知道了一些。

静态库应该是纯C / C ++,并使用Android NDK包装,以便可以从Java中使用。

例如,假设您的静态库是使用简单的.c和.h文件构建的:

highfive.h:

int giveMeFive();

highfive.c:

#include "highfive.h"

int giveMeFive() {
  return 5;
}

这可以使用Android NDK编译器编译为静态库,显然您已经知道如何操作:这将为我们提供highfive.a库。

在这种形式中,此库不能从Java中使用,但可以使用Android NDK进行包装。有关命名约定等,请参阅Android NDK文档...

highfiveWrapper.c:

#include "highfive.h"

jint
Java_your_package_name_HighFive_giveMeFive(JNIEnv *env, jobject o) {
  return (jint) giveMeFive();
}

及其相应的Java文件:

package your.package.name;

class HighFive {
  static {
    System.loadLibrary("highfive");
  }

  public native int giveMeFive();
}

现在,我们如何编译所有这些以使其工作:

Android.mk:

include $(CLEAR_VARS)
LOCAL_MODULE            := libhighfive-prebuilt
LOCAL_SRC_FILES         := path/to/highfive.a
LOCAL_EXPORT_C_INCLUDES := path/to/highfive.h/folder
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE      := highfive
LOCAL_SRC_FILES   := path/to/highfiveWrapper.c
LOCAL_STATIC_LIBRARIES := libhighfive-prebuilt
include $(BUILD_SHARED_LIBRARY)

在那里你应该能够按照自己的意愿使用你的本地图书馆!

希望这有帮助!

答案 1 :(得分:0)

通常,静态库包含许多对象,这些对象包含许多未使用的函数。这就是链接器仅从静态库中提取引用对象的原因。因此,在@mbrenon给出的示例中,highfiveWrapper.c定义highfive.a的哪些组件将链接到highfive.so

但是在您的设置中,您需要加载整个静态库。好的,有一个特殊的词:LOCAL_WHOLE_STATIC_LIBRARIES

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE    := MyUtils
LOCAL_SRC_FILES := ../../../../libs/libMyUtils.a

include $(PREBUILT_STATIC_LIBRARY)

LOCAL_MODULE    := AndroidTests
LOCAL_WHOLE_STATIC_LIBRARIES    := MyUtils

include $(BUILD_SHARED_LIBRARY)

答案 2 :(得分:0)

最后,解决方案是将MyUtils库构建为预建的共享库。这样链接器就不会剥离任何东西。然后我按如下方式修改了我的makefile:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE    := MyUtils
LOCAL_SRC_FILES := ../../../../libs/libMyUtils.so

include $(PREBUILT_SHARED_LIBRARY)

LOCAL_MODULE    := AndroidTests
LOCAL_SHARED_LIBRARIES    := MyUtils

include $(BUILD_SHARED_LIBRARY)

请注意 .so 扩展和PREBUILT_ SHARED _LIBRARY和BUILD_ SHARED _LIBRARY脚本。