简体   繁体   English

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

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

So.所以。 I found this lib in C called fastpbkdf2 and made shared lib out of it.我在 C 中找到了这个名为 fastpbkdf2 的库,并从中创建了共享库。

I created small C++ snippet that'll call one of the methods from the lib.我创建了小的 C++ 片段,它将调用 lib 中的方法之一。 But I'm constantly getting但我不断得到

error: undefined reference to ...

I search for so many stuff, try everything, but no luck.我搜索了很多东西,尝试了一切,但没有运气。 I'm probably missing something obvious here.我可能在这里遗漏了一些明显的东西。 (oh, and I've never programmed for C++ or C so maybe that could be the problem) (哦,我从来没有为 C++ 或 C 编程,所以这可能是问题所在)

All the files are in same folder.所有文件都在同一个文件夹中。

Here's Android.mk这是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)

Here's my try in C++:这是我在 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;
    }
}

And pbkdf2core.h:和 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

When I skip the "bad" code, everything is ok (I can run the other method, or return anything from the first, so all the other setup should be ok).当我跳过“坏”代码时,一切正常(我可以运行其他方法,或者从第一个方法返回任何内容,因此所有其他设置都应该没问题)。

If I change anything from header, I get different error (not declared).如果我更改标题中的任何内容,则会收到不同的错误(未声明)。 What am I missing here?我在这里缺少什么? (oh. the lib I'm using is in C. (哦。我使用的库是 C 语言。

Edit:编辑:

Here's error I get:这是我得到的错误:

[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

Oh.哦。 I also tried with我也试过

LOCAL_ALLOW_UNDEFINED := true

Build does go ok (obviously), but then I get app runtime error:构建确实没问题(显然),但随后我收到应用程序运行时错误:

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

It looks like the linker cannot find the method fastpbkdf2HmacSha1, in your source code and the shared library.看起来链接器在您的源代码和共享库中找不到方法 fastpbkdf2HmacSha1。 By forcing it to ignore the problem (eg using the LOCAL_ALLOW_UNDEFINED flag), you simple move the problem at runtime.通过强制它忽略问题(例如使用 LOCAL_ALLOW_UNDEFINED 标志),您可以在运行时简单地移动问题。 That's why you get the UnsatisfiedLinkError (the VM tries to load the library, which has a missing dependency, and the loading fails).这就是您收到 UnsatisfiedLinkError 的原因(VM 尝试加载缺少依赖项的库,但加载失败)。

First I would make sure that the library you are using is correct.首先,我会确保您使用的库是正确的。 You need to look into the libpbkdf2core.so for the missing symbol (fastpbkdf2HmacSha1).您需要查看 libpbkdf2core.so 以查找缺少的符号 (fastpbkdf2HmacSha1)。 You can do this using readelf and nm.你可以使用 readelf 和 nm 来做到这一点。 Nm will show you the symbols if you have a debug .so, whereas with readelf is a more powerful tool.如果你有一个 debug .so,Nm 会向你显示符号,而 readelf 是一个更强大的工具。

To get the symbol table from the .so do something like this:要从 .so 获取符号表,请执行以下操作:

readelf -Ws libpbkdf2core.so | grep fastpbkdf2HmacSha1

If the symbol is not there, you either have a corrupt .so or you are using the wrong .so?如果该符号不存在,那么您要么损坏了 .so,要么使用了错误的 .so?

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

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