arm共享库的重用

Reuse of arm shared library

本文关键字:共享 arm      更新时间:2023-10-16

我已经建立了arm android共享库(libtest.so)。我对重用一个函数感兴趣(它没有很多依赖关系——它只是创建类实例并调用两个方法)。我想调用该函数(它接受一个std::string参数)并获得返回值。

有可能这样做吗?我没有任何头文件。

我试过这个Android。mk,我放libtest。在/jni/libs/armeabi中,/lib/armeabi。在这一点上,我的cpp文件编译,但现在呢?如果可能的话,我如何从libtest.so调用函数?我从objdump

中知道它的名字
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 LOCAL_MODULE:= libtest
 LOCAL_SRC_FILES := libtest.so
 include $(PREBUILT_SHARED_LIBRARY)

 include $(CLEAR_VARS)
 LOCAL_MODULE    := hello-jni
 LOCAL_SRC_FILES := hello-jni.cpp
 LOCAL_SHARED_LIBRARIES := libtest
 include $(BUILD_SHARED_LIBRARY)
编辑:

我试着用这个android.mk:

从hello-jni样本中添加预构建库
include $(CLEAR_VARS)
LOCAL_MODULE:= libhello-jni
LOCAL_SRC_FILES := libhello-jni.so
include $(PREBUILT_SHARED_LIBRARY)

它工作了,但是libtest.so的相同代码显示以下错误(在启动时)

UnsatisfiedLinkError: Cannot load libtest.so: FindLibrary returned null

libtest。so存在于libhello-jni.so旁边的文件夹中(在/data/data/[package]/lib的设备上)。可能出了什么问题?

我有一个应用程序,我做的事情与您需要的类似(或者可能正是您需要的)。

  1. 我已经以*的形式预编译了库。所以文件。(如lib1。所以,lib2。所以等),

  2. 我已经创建了一个模块,它通过包括它们的头和*来使用预编译的库。所以文件。在这个例子中,我称之为"libtestwrapper"。模块定义自己的源文件,并可选地包含。模块功能可以导出到第二个模块(如果你提供头文件),后面会解释。

  3. 我创建了第二个模块(newModule),它通过将其添加到'LOCAL_SHARED_LIBRARIES'来使用第一个模块(libtestwrapper)。这使得你之前导出的头文件(在'libtestwrapper'中)对'newModule'可用。

这是我的Android.mk的内容:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libtestwrapper
LOCAL_SRC_FILES := libtestUsage.c # Use the methods of libtest.h here
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include # This is where libtest.h should be
# provide this line if you intend to export any header files to another module
#LOCAL_EXPORT_C_INCLUDES += $(LOCAL_PATH)/include # you may also use a different directory than 'include'
LOCAL_LDLIBS := -L$(LOCAL_PATH)/dir_with_libtest_so -libtest # -llog etc.
                                #optionally add any as needed: -llog -ljnigraphics -lz -ldl -lgcc
                                # '-libtest' corresponds to 'libtest.so' - the names must match
                                # -llog is for logcat for example
include $(BUILD_SHARED_LIBRARY)
# Optional:
# Define a second module wich is making use of the first one (i.e. libtestwrapper)
include $(CLEAR_VARS)
LOCAL_MODULE := newModule # this module will be making use of the first one (if needed)
                    # Add local source files. If the files are stored in directories
                    # you have to provide a relative path  starting inside the 'jni' directory.
                    # The example is for this structure: jni/dirToSourceFiles1/*.cpp
LOCAL_SRC_FILES := dirToSourceFiles1/SourceFile1.cpp dirToSourceFiles1/SourceFile2.cpp
LOCAL_C_INCLUDES += $(LOCAL_PATH)/newModule_include # path where the headers of this module are stored
LOCAL_SHARED_LIBRARIES += libtestwrapper # make use of the previous module
# Optionally add this line if any other libs should be used
#LOCAL_LDLIBS := -llog -ljnigraphics -lz -ldl -lgcc
include $(BUILD_SHARED_LIBRARY)

如果库不是用Android构建工具(即NDK)构建的,那么它可能不会有兼容的ABI。即使它是使用gcc的ARMv5 EABI兼容版本构建的,如果它依赖于任何libc/libc++,那么它将失败。仿生C库与其他C/c++库不二进制兼容,您必须针对它构建本机代码,即使是共享库。

如果你想从Java调用一个c++方法,并且需要传递像字符串这样的类型,你应该使用JNI (Java Native接口)编写一个转换层。

你可以在网上找到一些关于如何做到这一点的教程。一个例子

作为总结

1-在Java中声明一个本机方法

2-生成应该从c++库中导出的签名,该签名将在Java中调用此方法时被调用。

示例命令:javah com.companyname.JavaTestCaller

该命令将生成一个带有相应签名的头文件。

3-准备一个包含此方法的c++库。在这个方法中做任何您想做的事情(调用libtest。如果你想的话)并返回结果。当需要进行类型转换时,使用from方法。

4-把这个新库放在libtest旁边。在你的应用中。在libtest.so之后加载这个库。

从您的应用程序中调用本机Java方法。

你试过改变这一行吗?

LOCAL_SHARED_LIBRARIES := libtest

:

LOCAL_SHARED_LIBRARIES := test

lib和.so将自动用于解析共享库名称。您还应该能够使用:

LOCAL_LDLIBS += -ltest

PREBUILT_SHARED_LIBRARY是另一个选项。

由于没有头文件,因此可能需要编写一个共享库,用于调用预构建库。您的应用程序将调用新的共享库,它将导出正确的JNI符号名称,新的共享库将调用md5()函数。