所以。我在 C 中找到了这个名为 fastpbkdf2 的库,并从中创建了共享库。
我创建了一个小的 C++ fragment ,它将调用库中的方法之一。但我不断得到
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
当我跳过“错误”代码时,一切正常(我可以运行其他方法,或者从第一个开始返回任何内容,因此所有其他设置应该都正常)。
如果我更改 header 中的任何内容,我会收到不同的错误(未声明)。我在这里错过了什么? (哦。我正在使用的库是在 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 来执行此操作。如果你有调试 .so,Nm 会显示符号,而 readelf 是一个更强大的工具。
要从 .so 中获取符号表,请执行以下操作:
readelf -Ws libpbkdf2core.so | grep fastpbkdf2HmacSha1
如果该符号不存在,您的 .so 是否已损坏或您使用的是错误的 .so?
关于android - 如何使用 Android NDK 的共享库(C 库添加到 C++),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37494767/