[英]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.