2013-11-22 22 views
1

我生成C++库使用Android SDK编译器使用手动静态库是不同的。结果是libMyUtils.a。的Android NDK:比预编译库中指定

我用我的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。很显然,我所调用的本地函数不在库中。我究竟做错了什么?

回答

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) 

通知的。所以的推广与该PREBUILT_ SHARED _LIBRARY和BUILD_ SHARED _LIBRARY脚本。

+0

你是怎么建立'../../../../ libs/libMyUtils.so'的? –

+0

我使用cmake以及http://code.google.com/p/android-cmake/,所以我将cmake脚本更改为使用SHARED而不是STATIC。 – Emmanuel

+0

是的,这是最简单的修复方法。 –

0

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

静态库应该是纯C/C++,并且使用Android NDK进行封装以便可以从Java使用。

highfive.h:

int giveMeFive(); 

highfive.c:

#include "highfive.h" 

int giveMeFive() { 
    return 5; 
} 

例如,假设您的静态库是由一个简单的.c和.h文件建

这可以被编译为使用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) 

还有,你应该能够为你想使用你的本地库!

希望这有助于!

+0

好吧预构建的库包含包装。我认为发生的事情是,在最后一个本地模块中,符号全部被剥离,因为我没有可用的源文件。 – Emmanuel

+0

是的,这可能会发生什么:没有LOCAL_SRC_FILES意味着没有引用静态库,它被认为是“未使用”,因此被剥离。 – mbrenon

+0

我想不出任何其他解决方案,而不是将NDK包装放入共享库。我不认为它有可能在一个静态库中。 – mbrenon

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) 
+1

我已经试过这个解决方案。我不知道为什么,但似乎没有工作。这很有道理。在这之后,我的图书馆仍然是空的。但我找到了解决方案。 – Emmanuel