使用Android NDK从.so文件调用Native函数

时间:2014-09-18 11:55:36

标签: java android c++ android-ndk

我找到了如何使用NDK在Android中链接和使用c / c ++代码的说明。我想知道当你从第三方获得.so时,这个过程有多么不同?

调用System.loadLibrary()似乎正确加载库,但每当我尝试调用我需要的方法时,我都会得到一个UnsatisfiedLinkError。

根据编译.so文件的第三方提供的详细信息声明函数原型。有没有办法可以有效地反编译文件,至少检查原型是否正确?

预编译的.so库的链接进程是否有所不同?也许我错过了导致链接错误的一些步骤。

编辑:

我希望我可以发布代码,但我只能用手机写信。我的Android.mk文件是按照您的预期设置的,引用了.so文件和$(PREBUILT_SHARED_LIBRARY)规范。

我的所有代码都是加载库并使用native关键字声明函数原型。当我尝试调用该函数时,我收到链接错误。

2 个答案:

答案 0 :(得分:0)

  

我想知道当你从第三方获得.so时,这个过程有多么不同?

这是我的一个项目的样子。该项目产生libprng.so。它使用Crypto ++作为底层PRNG(它还会在返回GetBytes中的字节之前对传感器进行采样以重新设置PRNG。)

Crypto ++库位于/usr/local/cryptopp/android-ARCH,其中ARCHarmeabiarmeabi-v7ax86mips

我的共享对象和Crypto ++共享对象都依赖于STLport。因为多个模块依赖于STLport,所以我们必须使用STLport的共享对象版本(即libstlport_shared.so)。

这是Java类文件的样子:

public class PRNG {

    static {
        System.loadLibrary("stlport_shared");
        System.loadLibrary("cryptopp");
        System.loadLibrary("prng");
    }
    ...
}

<强> Application.mk

APP_ABI   := armeabi x86 mips armeabi-v7a

<强> Android.mk

LOCAL_PATH := $(call my-dir)

# NDK_DEBUG_IMPORTS := 1

#########################################################
# STLport library
include $(CLEAR_VARS)

STLPORT_INCL     := /opt/android-ndk-r9/sources/cxx-stl/stlport/stlport
STLPORT_LIB      := /opt/android-ndk-r9/sources/cxx-stl/stlport/libs/$(TARGET_ARCH_ABI)

LOCAL_MODULE := stlport_shared
LOCAL_SRC_FILES := $(STLPORT_LIB)/libstlport_shared.so

LOCAL_EXPORT_CPPFLAGS :=
LOCAL_EXPORT_C_INCLUDES := $(STLPORT_INCL)

include $(PREBUILT_SHARED_LIBRARY)

LOCAL_SHARED_LIBRARIES  := stlport_shared

#########################################################
# Crypto++ library
include $(CLEAR_VARS)

CRYPTOPP_INCL   := /usr/local/cryptopp/android-$(TARGET_ARCH_ABI)/include
CRYPTOPP_LIB    := /usr/local/cryptopp/android-$(TARGET_ARCH_ABI)/lib

LOCAL_MODULE       := cryptopp
LOCAL_SRC_FILES    := $(CRYPTOPP_LIB)/libcryptopp.so

LOCAL_EXPORT_CPPFLAGS := -Wno-unused-parameter -Wno-unused-variable -Wno-unused-function
LOCAL_EXPORT_C_INCLUDES := $(CRYPTOPP_INCL) $(CRYPTOPP_INCL)/cryptopp

include $(PREBUILT_SHARED_LIBRARY)

LOCAL_SHARED_LIBRARIES  := cryptopp

#########################################################
# PRNG library
include $(CLEAR_VARS)

APP_STL         := stlport_shared
APP_MODULES     := prng stlport_shared cryptopp

# My ass... LOCAL_EXPORT_C_INCLUDES is useless
LOCAL_C_INCLUDES   := $(STLPORT_INCL) $(CRYPTOPP_INCL)

LOCAL_CPP_FEATURES := rtti exceptions

LOCAL_CPP_FLAGS    := -Wno-unused-parameter -Wno-unused-variable -Wno-unused-function
LOCAL_CPP_FLAGS    += -Wl,--exclude-libs,ALL

LOCAL_LDLIBS            := -llog -landroid
LOCAL_SHARED_LIBRARIES  := cryptopp stlport_shared

LOCAL_MODULE    := prng
LOCAL_SRC_FILES := libprng.cpp

include $(BUILD_SHARED_LIBRARY)

答案 1 :(得分:0)

首先,你需要你的方法原型来匹配lib设计的原型,但通常包名和类名也必须匹配。

您可以使用binutils中的readelf获取.so文件中声明的符号:

readelf -s libYourLib.so

要查找的符号以Java_开头,后跟包名,然后是类名,最后是方法名,.替换为_

您可以使用我开发的这个应用程序代替使用readelf:https://play.google.com/store/apps/details?id=com.xh.nativelibsmonitor.app

有时只会声明JNI_OnLoad方法而不是Java_*方法。在这种情况下,您无法直接获得所需信息。