djc*_*535 17 java-native-interface linker android shared-libraries android-ndk
我正在编写一个Android应用程序,希望将JNI调用成为使用NDK构建的共享库.诀窍是这个共享库调用OTHER共享库提供的函数.其他共享库是已在其他地方编译的C库.
这是我尝试过的:
我的环境: 我在Eclipse工作.我添加了原生支持并拥有一个jni库.在那个库中,我有我的代码和\ lib目录,我已经复制了我的其他.so文件.
尝试#1 Android.mk:告诉它libs在哪里
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := native_lib
LOCAL_SRC_FILES := native_lib.cpp
LOCAL_LDLIBS := -L$(SYSROOT)/../usr/lib -llog
LOCAL_LDLIBS += -L$(LOCAL_PATH)/lib/support_lib1
LOCAL_LDLIBS += -L$(LOCAL_PATH)/lib/support_lib2
include $(BUILD_SHARED_LIBRARY)
Run Code Online (Sandbox Code Playgroud)
这构建得很好,但是当我尝试运行时,我得到错误,表明dlopen(libnative_lib)失败,因为它无法加载libsupport_lib1.
来到这里我发现了这个:
这说我需要在所有必要的库上调用load库.大!
尝试#2首先打开每个库
static {
System.loadLibrary("support_lib1");
System.loadLibrary("support_lib2");
System.loadLibrary("native_lib");
}
Run Code Online (Sandbox Code Playgroud)
再次,这构建得很好,但是当我运行时,我得到一个新的错误:
无法加载libsupport_lib1.findLibrary返回null.
现在我们到了某个地方.它不能将库加载到目标.
尝试#3将.so文件复制到project/libs/armeabi中
没工作.当Eclipse构建时,它删除了我放在那里的文件.
尝试#4为每个库创建一个新模块
那么我发现了这个:
它是关于静态库的,但也许我遇到了类似的问题.要点是我需要为每个库声明一个模块.所以我的新Android.mk看起来像这样:
LOCAL_PATH := $(call my-dir)
#get support_lib1
include $(CLEAR_VARS)
LOCAL_MODULE := support_lib1
LOCAL_SRC_FILES := $(LOCAL_PATH)/lib/support_lib1.so
include $(BUILD_SHARED_LIBRARY)
#get support_lib2
include $(CLEAR_VARS)
LOCAL_MODULE := support_lib2
LOCAL_SRC_FILES := $(LOCAL_PATH)/lib/support_lib2.so
include $(BUILD_SHARED_LIBRARY)
#build native lib
include $(CLEAR_VARS)
LOCAL_MODULE := native_lib
LOCAL_SRC_FILES := native_lib.cpp
LOCAL_LDLIBS := -L$(SYSROOT)/../usr/lib -llog
LOCAL_LDLIBS += -L$(LOCAL_PATH)/lib/support_lib1
LOCAL_LDLIBS += -L$(LOCAL_PATH)/lib/support_lib2
include $(BUILD_SHARED_LIBRARY)
Run Code Online (Sandbox Code Playgroud)
这构建!更好的是,armeabi现在有了sos!甚至更好我尝试运行时收到以下消息(告诉我loadLibrary打开了support_lib1和2:
试图加载LIB /data/app-lib/com.example.tst/libsupport_lib1.so加入共享库/data/app-lib/com.example.tst/libsupport_lib1.so没有JNI_OnLoad在/数据中发现/ APP-LIB/com.example.tst/libsupport_lib1.so,跳过init
但后来... dlopen失败:无法找到libnative_lib.so引用的符号func_that_exists_in_libsupport_lib.so
编辑:尝试5:使用PREBUILT_SHARED_LIBRARY
所以我发现了这个: 我如何将预建的共享库链接到Android NDK项目?
这似乎正是我所要求的.他们的答案似乎是'不要使用'build_shared_library'而是'使用'PREBUILT_SHARED_LIBRARY
好的,我们试试吧.
LOCAL_PATH := $(call my-dir)
#get support_lib1
include $(CLEAR_VARS)
LOCAL_MODULE := support_lib1
LOCAL_SRC_FILES := $(LOCAL_PATH)/lib/support_lib1.so
include $(PREBUILT_SHARED_LIBRARY)
#get support_lib2
include $(CLEAR_VARS)
LOCAL_MODULE := support_lib2
LOCAL_SRC_FILES := $(LOCAL_PATH)/lib/support_lib2.so
include $(PREBUILT_SHARED_LIBRARY)
#build native lib
include $(CLEAR_VARS)
LOCAL_MODULE := native_lib
LOCAL_SRC_FILES := native_lib.cpp
LOCAL_LDLIBS := -L$(SYSROOT)/../usr/lib -llog
LOCAL_SHARED_LIBRARIES := support_lib1 support_lib2
include $(BUILD_SHARED_LIBRARY)
Run Code Online (Sandbox Code Playgroud)
构建......失败!构建现在抱怨缺少符号.
编辑:尝试6:展平一切
所以我回到了NDK中的预编译文档.它说:
必须将每个预构建的库声明为构建系统的单个独立模块.这是一个简单的例子,我们假设文件"libfoo.so"与Android.mk下面的目录相同:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := foo-prebuilt
LOCAL_SRC_FILES := libfoo.so
include $(PREBUILT_SHARED_LIBRARY)
Run Code Online (Sandbox Code Playgroud)
请注意,要声明此类模块,您实际上只需要以下内容:
给模块一个名字(这里是'foo-prebuilt').这不需要与预构建库本身的名称相对应.
将LOCAL_SRC_FILES分配给您提供的预构建库的路径.像往常一样,路径是相对于您的LOCAL_PATH.
如果要提供共享库,请包括PREBUILT_SHARED_LIBRARY,而不是BUILD_SHARED_LIBRARY.对于静态的,请使用PREBUILT_STATIC_LIBRARY.预建模块不构建任何东西.但是,预建的共享库的副本将被复制到$ PROJECT/obj/local中,另一个将被复制并剥离到$ PROJECT/libs /中.
因此,让我们尝试将所有内容展平以匹配琐碎的例子.我将我的库复制到他们的comfort/lib文件夹中并将它们放在jni根目录中.然后我这样做了:
LOCAL_PATH := $(call my-dir)
#get support_lib1
include $(CLEAR_VARS)
LOCAL_MODULE := support_lib1
LOCAL_SRC_FILES := support_lib1.so
include $(PREBUILT_SHARED_LIBRARY)
#get support_lib2
include $(CLEAR_VARS)
LOCAL_MODULE := support_lib2
LOCAL_SRC_FILES := support_lib2.so
include $(PREBUILT_SHARED_LIBRARY)
#build native lib
include $(CLEAR_VARS)
LOCAL_MODULE := native_lib
LOCAL_SRC_FILES := native_lib.cpp
LOCAL_LDLIBS := -L$(SYSROOT)/../usr/lib -llog
LOCAL_SHARED_LIBRARIES := support_lib1 support_lib2
include $(BUILD_SHARED_LIBRARY)
Run Code Online (Sandbox Code Playgroud)
和......同样的错误.而且我绝对不会看到库文件被复制到$ PROJECT/obj/local.
sooooo ....现在怎么样?
Ale*_*ohn 13
您的问题在于命名约定.NDK和Android坚持共享库名称始终以lib开头.否则,库将无法正确链接,也不会正确复制到libs/armeabi文件夹中,也不会安装在设备上(/data/data/package/lib正确复制到目录中).
如果重support_lib1.so来libsupport_1.so,并support_lib2.so到libsupport_2.so,就把这两个文件jni/lib的目录,那么你尝试#5将与小的改动工作:
LOCAL_PATH := $(call my-dir)
#get support_lib1
include $(CLEAR_VARS)
LOCAL_MODULE := support_lib1
LOCAL_SRC_FILES := lib/libsupport_1.so
include $(PREBUILT_SHARED_LIBRARY)
#get support_lib2
include $(CLEAR_VARS)
LOCAL_MODULE := support_lib2
LOCAL_SRC_FILES := lib/libsupport_2.so
include $(PREBUILT_SHARED_LIBRARY)
#build native lib
include $(CLEAR_VARS)
LOCAL_MODULE := native_lib
LOCAL_SRC_FILES := native_lib.cpp
LOCAL_LDLIBS := -L$(SYSROOT)/../usr/lib -llog
LOCAL_SHARED_LIBRARIES := support_lib1 support_lib2
include $(BUILD_SHARED_LIBRARY)
Run Code Online (Sandbox Code Playgroud)
顺便说一句,我认为你不需要这个-L$(SYSROOT)/../usr/lib.
PS别忘了更新Java方面:
static {
System.loadLibrary("support_lib1");
System.loadLibrary("support_lib2");
System.loadLibrary("native_lib");
}
Run Code Online (Sandbox Code Playgroud)
不确定这是否正是您所处的位置,但这就是我对此类事情的了解。
$(call import-add-path)和包含每个 make 文件$(call import-module)LOCAL_EXPORT_使用变量系列从预构建的 make 文件中导出尽可能多的内容。LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := my_module_name
MY_LIBRARY_NAME := shared_library_name
### export include path
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
### path to library
LOCAL_SRC_FILES := libs/$(TARGET_ARCH_ABI)/lib$(MY_LIBRARY_NAME).so
### export dependency on the library
LOCAL_EXPORT_LDLIBS := -L$(LOCAL_PATH)/libs/$(TARGET_ARCH_ABI)/
LOCAL_EXPORT_LDLIBS += -l$(MY_LIBRARY_NAME)
include $(PREBUILT_SHARED_LIBRARY)
Run Code Online (Sandbox Code Playgroud)
这是假设预构建的库位于这样的目录结构中
+ SharedProjectFolderName
+--- Android.mk
+--- include/
+-+- libs/$(TARGET_ARCH_ABI)/
|- libshared_library_name.so
Run Code Online (Sandbox Code Playgroud)
如果您不是为多个 ABI 构建,我想您可以忽略这一点
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := my_jni_module
## source files here, etc...
### define dependency on the other library
LOCAL_SHARED_LIBRARIES := my_module_name
include $(BUILD_SHARED_LIBRARY)
$(call import-add-path,$(LOCAL_PATH)/path/to/myLibraries/)
$(call import-module,SharedProjectFolderName)
$(call import-module,AnotherSharedProject)
Run Code Online (Sandbox Code Playgroud)
我建议您将所有共享库放在一个文件夹中。当您说它沿着您告诉它的搜索路径$(call import-module,SharedProjectFolderName)查找包含( )Android.mkimport-add-path
顺便说一句,您可能不应该指定LOCAL_LDLIBS := -L$(SYSROOT)/../usr/lib. 它应该自己从 NDK 中找到合适的库。添加更多链接器路径可能会使其混乱。正确的方法是将链接器路径作为标志从子模块导出。
另外,您可以用来ndk-build V=1获取大量有关为什么找不到路径等的信息
| 归档时间: |
|
| 查看次数: |
24253 次 |
| 最近记录: |