繁体   English   中英

如何为 Android NDK 使用共享库(C 库添加到 C++)

[英]How to use shared library for Android NDK (C lib adding to C++)

所以。 我在 C 中找到了这个名为 fastpbkdf2 的库,并从中创建了共享库。

我创建了小的 C++ 片段,它将调用 lib 中的方法之一。 但我不断得到

error: undefined reference to ...

我搜索了很多东西,尝试了一切,但没有运气。 我可能在这里遗漏了一些明显的东西。 (哦,我从来没有为 C++ 或 C 编程,所以这可能是问题所在)

所有文件都在同一个文件夹中。

这是Android.mk

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE           := pbkdf2core
LOCAL_SRC_FILES        := libpbkdf2core.so
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE    := pbkdf2
LOCAL_SRC_FILES := pbkdf2.cpp
LOCAL_SHARED_LIBRARIES := pbkdf2core
include $(BUILD_SHARED_LIBRARY)

这是我在 C++ 中的尝试:

#include <jni.h>
#include "native.h"
#include <pbkdf2core.h>

extern "C"{
    JNIEXPORT jbyteArray JNICALL Java_com_package_generatePBKDF2key
    (JNIEnv * env, jclass cls, jbyteArray password, jbyteArray salt, jint iterations)
    {
            uint8_t * out;

            fastpbkdf2HmacSha1(jbyteArrayToString(env, password), 
                env->GetArrayLength(password), 
                jbyteArrayToString(env, salt), 
                env->GetArrayLength(salt), 
                (int) iterations, out, 32);


            jbyteArray bytes = env->NewByteArray(32); 
            env->SetByteArrayRegion(bytes, 0, 32, (jbyte*)out); 
            return bytes;
            //return password; --> running only this works ok
    }

    uint8_t* jbyteArrayToString(JNIEnv* env, jbyteArray barr)
    {
           uint8_t* rtn = NULL;
           jsize alen = env->GetArrayLength(barr);
           jbyte* ba = env->GetByteArrayElements(barr, JNI_FALSE);
           if (alen > 0)
           {
                     rtn = (uint8_t*)malloc(alen + 1);
                     memcpy(rtn, ba, alen);
                     rtn[alen] = 0;
           }
           env->ReleaseByteArrayElements(barr, ba, 0);
           return rtn;
    }

    //commenting out "bad" code, and running only this really works
    JNIEXPORT jint JNICALL Java_com_package_getNum(JNIEnv * env, jclass cls){
        return 1;
    }
}

和 pbkdf2core.h:

#include <jni.h>
#include <stdlib.h>
#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#endif
void fastpbkdf2HmacSha1(const uint8_t *pw, size_t npw,
                          const uint8_t *salt, size_t nsalt,
                          uint32_t iterations,
                          uint8_t *out, size_t nout);
#ifdef __cplusplus
}
#endif

当我跳过“坏”代码时,一切正常(我可以运行其他方法,或者从第一个方法返回任何内容,因此所有其他设置都应该没问题)。

如果我更改标题中的任何内容,则会收到不同的错误(未声明)。 我在这里缺少什么? (哦。我使用的库是 C 语言。

编辑:

这是我得到的错误:

[armeabi] Compile++ thumb: pbkdf2 <= pbkdf2.cpp
[armeabi] SharedLibrary  : libpbkdf2.so
/Users/.../src/main/jni/pbkdf2.cpp:15: error: undefined reference to 'fastpbkdf2HmacSha1'
collect2: error: ld returned 1 exit status
make: *** [/Users/.../src/main/obj/local/armeabi/libpbkdf2.so] Error 1

哦。 我也试过

LOCAL_ALLOW_UNDEFINED := true

构建确实没问题(显然),但随后我收到应用程序运行时错误:

java.lang.UnsatisfiedLinkError: dlopen failed: cannot locate symbol "fastpbkdf2HmacSha1"

看起来链接器在您的源代码和共享库中找不到方法 fastpbkdf2HmacSha1。 通过强制它忽略问题(例如使用 LOCAL_ALLOW_UNDEFINED 标志),您可以在运行时简单地移动问题。 这就是您收到 UnsatisfiedLinkError 的原因(VM 尝试加载缺少依赖项的库,但加载失败)。

首先,我会确保您使用的库是正确的。 您需要查看 libpbkdf2core.so 以查找缺少的符号 (fastpbkdf2HmacSha1)。 你可以使用 readelf 和 nm 来做到这一点。 如果你有一个 debug .so,Nm 会向你显示符号,而 readelf 是一个更强大的工具。

要从 .so 获取符号表,请执行以下操作:

readelf -Ws libpbkdf2core.so | grep fastpbkdf2HmacSha1

如果该符号不存在,那么您要么损坏了 .so,要么使用了错误的 .so?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM