3

Java Native Interface で md5 共有ライブラリを使用しようとしています。ここでソースを確認できます。このライブラリは大きすぎて、JNI で使用する準備ができていません。そこで、リンク用のシンプルなアクセサリ ライブラリを使用したいと考えています。テスト中にこのライブラリをビルドすると、次の出力が得られました。

  java: symbol lookup error: ./libMd5bridge.so: undefined symbol: _Z3md5Ss

LD_PRELOAD を実行しようとしましたが、これは結果ではありませんでした。だからここで私はすべての私の行動を段階的に投稿します。

1)非常に単純な C++ コードで md5 ライブラリを呼び出すことができます。

#include <iostream>
#include "md5.h"

int main(int argc, char* argv[]) {
    std::string passedValue;
    for(int i = 1; i < argc; i++)
     passedValue += argv[i];
    std::cout << "MD5 sum is: " << md5(passedValue) <<std::endl;
    return 0;
}

アクセサリ ライブラリに Md5bridge という名前を付けました。したがって、次のコンテキストではそう呼びます。

2) Md5Bridge.java

public class Md5bridge{
     native public void MD5SUM(String[] passedValue);
}

3) Md5bridge ヘッダー ファイルの取得:

javac Md5Bridge.java && javah Md5Bridge

Md5bridge.h

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class Md5bridge */

#ifndef _Included_Md5bridge
#define _Included_Md5bridge
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     Md5bridge
 * Method:    MD5SUM
 * Signature: ([Ljava/lang/String;)V
 */
JNIEXPORT void JNICALL Java_Md5bridge_MD5SUM
  (JNIEnv *, jobject, jobjectArray);

#ifdef __cplusplus
}
#endif
#endif

4)ステップ 1 から jni で使用するコードの準備:

#include <iostream>
#include "md5.h"
#include "Md5bridge.h"
JNIEXPORT void JNICALL Java_Md5bridge_MD5SUM
  (JNIEnv *, jobject, jobjectArray) {

    std::string passedValue;
    md5(passedValue);
}

5)共有ライブラリとしてコンパイル:

g++ -shared -fPIC -I /opt/jdk1.6.0_45/include/ -I /opt/jdk1.6.0_45/include/linux -o libMd5bridge.so Md5bridge.cpp

6)このライブラリをチェックするための簡単な Java プログラムを準備します。

   public class Main{
    static{
    System.loadLibrary("Md5bridge");
    }
    public static void main(String[] passedValue){
    new Md5bridge().MD5SUM(passedValue);
    }
    }

このプログラムは javac でコンパイルされ、エラーで実行されました (この記事の冒頭に書きました)。

java: symbol lookup error: ./libMd5bridge.so: undefined symbol: _Z3md5Ss

私は Java に詳しくないので、私のステップの 1 つで何か間違ったことをしたと思います。何か案が?

更新: extern "C"{} md5 ヘッダー ファイルを追加した後 ( Chris Strattonに 感謝)、次の出力が得られます。

java: symbol lookup error: /home/andrey/Desktop/md5LIB/libMd5bridge.so: undefined symbol: md5

libmd5.so へのリンクが抜けているようです。

$ ldd libMd5bridge.so 
    linux-vdso.so.1 =>  (0x00007fff38666000)
    libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x00007f2dfde3a000)
    libm.so.6 => /lib/libm.so.6 (0x00007f2dfdbb7000)
    libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x00007f2dfd99f000)
    libc.so.6 => /lib/libc.so.6 (0x00007f2dfd619000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f2dfe36b000)

両方のライブラリをリンクする方法は?

4

2 に答える 2

1

C 実装は次のようにする必要があります。

#include <iostream>
#include "md5.h"
#include "Md5bridge.h"
#ifdef __cplusplus
extern "C" {//pay attention to this!
#endif 
JNIEXPORT void JNICALL Java_Md5bridge_MD5SUM
  (JNIEnv *, jobject, jobjectArray) {

   std::string passedValue;
   md5(passedValue);
}
#ifdef __cplusplus
} //pay attention to this
#endif 

しかし、より良い!JDK に既に実装されている origin md5 を使用する

ここに私のJavaコードからのスナップショットがあります:

public class MD5Converter {

    private final static String ALGORITHM = "MD5";
    private final static String ENCODING = "UTF-8";

    public static String encryptToMd5(String normal) {
        MessageDigest digest;
        try {
            digest = java.security.MessageDigest.getInstance(ALGORITHM);
            digest.reset();
            digest.update(normal.getBytes(ENCODING));
            byte[] hash = digest.digest();
            return byteToHex(hash); //This is on you res to implement this 
        } catch (NoSuchAlgorithmException e) {
            final String err = "No such digest algorithm \"" + ALGORITHM + "\"";
            log.fatal(err, e);
            throw new IllegalStateException(err, e);
        } catch (UnsupportedEncodingException e) {
            final String err = "Unsupported encoding \"" + ENCODING + "\"";
            log.fatal(err, e);
            throw new IllegalStateException(err, e);
            }
        }
}
于 2013-06-26T14:36:39.003 に答える
0

オプションを使用してコンパイルすることにより、.so を他のライブラリにリンクでき-lます。ライブラリがシステム ディレクトリにインストールされていない場合は、検索するディレクトリを指定できます-L

たとえば、md5 関数が作業ディレクトリにある場合は、コンパイラ コマンド ラインに次のlibmd5.soように追加します。-L. -lmd5

g++ -共有 -fPIC -I /opt/jdk1.6.0_45/include/ -I /opt/jdk1.6.0_45/include/linux -o libMd5bridge.so Md5bridge.cpp -L. -lmd5

この場合のライブラリは非常に小さいように見えるため、コードを別のライブラリからロードするのではなく、「ブリッジ」ライブラリに直接コンパイルすることが理にかなっています。これを行うには、ソース ファイルをコマンド ラインに追加するだけです。

g++ -shared -fPIC -I /opt/jdk1.6.0_45/include/ -I /opt/jdk1.6.0_45/include/linux -o libMd5bridge.so Md5bridge.cpp MD5.cppWhatever.cpp

于 2013-06-27T13:13:57.943 に答える