2016-05-28 16 views
1

So.私はこのlibをfastpbkdf2というC言語で見つけ出し、共有libを作りました。Android NDKの共有ライブラリの使い方(C libにC++を追加)

libからメソッドの1つを呼び出す小さなC++スニペットを作成しました。しかし、私は常に得ています

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 

私は "悪い" コードをスキップすると、すべてのもの(私は他の方法を実行するか、最初から何かを返すことができるので、他のすべての設定はokです)。

ヘッダから何かを変更すると、別のエラー(宣言されていない)が発生します。私はここで何が欠けていますか? (オハイオ州私が使用しているのlibは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 
てみました

ビルドはOKです(明らかに)が、アプリケーションランタイムエラーが発生します。

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

あなたは正確なエラーメッセージを投稿できますか? –

+0

エラーが発生しました。 – dmestrovic

答えて

1

リンカがソースコードと共有ライブラリにfastpbkdf2HmacSha1メソッドを見つけることができないようです。 LOCAL_ALLOW_UNDEFINEDフラグを使用して問題を無視するように強制すると、実行時に問題を簡単に移動できます。そのため、UnsatisfiedLinkError(VMが依存関係がなく、読み込みに失敗したライブラリをロードしようとします)が発生します。

まず、使用しているライブラリが正しいことを確認します。不足しているシンボル(fastpbkdf2HmacSha1)のlibpbkdf2core.soを調べる必要があります。これはreadelfとnmを使って行うことができます。あなたがデバッグ.soを持っているなら、Nmはシンボルを表示しますが、readelfはより強力なツールです。あなたのいずれかが破損する.soを持っているか、あなたは間違っているの.soを使用している、シンボルが存在しない場合には

readelf -Ws libpbkdf2core.so | grep fastpbkdf2HmacSha1 

はこのような何かをする.soからシンボルテーブルを取得するには?

+0

これはむしろ奇妙です。 greadelf(macバージョン)から何を期待するのか本当に分かっていませんが、私は何を見ているのでしょうか。唯一の問題は、私がソースからこのlibを作った人だということです。何かが間違っているように見える。 :) 少なくとも私はどこを見るか知っています。 ありがとうございました。私はもっ​​と深く掘り下げて、更新を投稿します。 – dmestrovic

+0

私はそれが私のせいだったと思う。それを私がやったやり方で作ることができなかった。どうやってそれを作るのかは分かりません。 :)それはまったく別のものです。お手伝いありがとう。私たちはそれを「腐敗した.soのためのエラー」と呼ぶことができます。 – dmestrovic

関連する問題