C++で作成した共有ライブラリ(so)をJNAを利用してJavaプログラムで参照しようとしましたが、
「undefined symbol (未定義のシンボル)」で失敗します。
お教えていただきたいのは、共有ライブラリを作成する時に必ず指定しなければならない
コンパイルオプションかリンクオプションが、あるのでしょうか?
共有ライブラリ作成時に指定しているオプションは、以下の通りです。
- コンパイルオプション
インクルード・パス:(-l xxxxxx)
最適化:なし(-O0)
デバッグレベル:最大(-g3)
全ての警告(-Wall)
その他のフラグ:-c -fmessage-length=0 -fPIC
- リンクオプション
ライブラリの検索パス:(-L xxxxxx)
共有(-shared)
確認した環境は、以下の通りです。
CentOS7(7.8.2003)
Eclipse 2020-03(4.15.0)
CDT 9.11(2020-03)
gcc-c++(4.8.5)
JDK(11)
以下、エラーメッセージです。
error
1Exception in thread "main" java.lang.UnsatisfiedLinkError: Error looking up function 'CAESSecurity': /home/css/eclipse-workspace/CryptoWithA4kCommonLibrarySample/bin/libAESSecurityLibrary.so: undefined symbol: CAESSecurity 2 at com.sun.jna.Function.<init>(Function.java:252) 3 at com.sun.jna.NativeLibrary.getFunction(NativeLibrary.java:600) 4 at com.sun.jna.NativeLibrary.getFunction(NativeLibrary.java:576) 5 at com.sun.jna.NativeLibrary.getFunction(NativeLibrary.java:562) 6 at com.sun.jna.Library$Handler.invoke(Library.java:243) 7 at com.sun.proxy.$Proxy0.CAESSecurity(Unknown Source) 8 at CryptoSample.encryptToken(CryptoSample.java:25) 9 at mainSample.main(mainSample.java:11) 10
以下、プログラムです。
C++
1CAESSecurity::CAESSecurity(bytes& key, bytes& IV, int keytype) 2: m_key(key), m_IV(IV), m_keytype(keytype) 3{ 4 /* Load up the software EVP_CIPHER definitions */ 5 OpenSSL_add_all_ciphers(); 6#ifndef OPENSSL_NO_ENGINE 7 /* Load all compiled-in ENGINEs */ 8 ENGINE_load_builtin_engines(); 9 /* Register all available ENGINE implementations of ciphers. */ 10 ENGINE_register_all_ciphers(); 11#endif 12 13} 14
Java
1 // 暗号化&復号化で使用する鍵 2 private static final byte[] ENCRYPT_KEY = new byte[] { (byte)0x9C, (byte)0x5D, (byte)0x5A, (byte)0x42, (byte)0x8A, (byte)0x20, (byte)0x3D, (byte)0x7B, (byte)0x38, (byte)0x5D, (byte)0xAD, (byte)0x63, (byte)0x29, (byte)0xE6, (byte)0xD2, (byte)0x16 }; 3 // 初期ベクトル 4 private static final byte[] INIT_VECTOR = new byte[] { (byte)0xBB, (byte)0xC0, (byte)0xCE, (byte)0xC6, (byte)0xAE, (byte)0xB8, (byte)0x47, (byte)0x9D, (byte)0xE2, (byte)0xA3, (byte)0x85, (byte)0x93, (byte)0x13, (byte)0xA7, (byte)0x88, (byte)0x65 }; 5 6 public interface A4kCommonLibrary extends Library { 7 A4kCommonLibrary INSTANCE = (A4kCommonLibrary)Native.loadLibrary("AESSecurityLibrary", A4kCommonLibrary.class); 8 9 void CAESSecurity(byte[] key, byte[] iv, int keyType); 10 boolean Encode(byte[] in_bytes, byte[] out_bytes); 11 } 12 13 /** 14 * 暗号化処理 15 */ 16 public String encryptToken(String token) throws Exception { 17 byte[] data = new byte[5000]; 18 A4kCommonLibrary Cipher = A4kCommonLibrary.INSTANCE; 19 Cipher.CAESSecurity(ENCRYPT_KEY, INIT_VECTOR, 128); 20 Cipher.Encode(token.getBytes(), data); 21 22 // 暗号化 23 return new String(data); 24 } 25
共有ライブラリの作成手順を以下にまとめました。
※既存の処理を部分的に抜き出して共有ライブラリとして作成しています。
- Eclipseの新規プロジェクト(C/C++プロジェクト、C++管理ビルドテンプレート、空のプロジェクトを指定)を作成しました。
- 作成したプロジェクトにsrcディレクトリとincludeディレクトリを追加しました。
- 既存のプログラムをプロジェクトに追加(空ファイルを作成し、既存プログラムの内容をコピーする)しました。
- プロジェクトのプロパティで既存と同じ設定を指定しました(設定内容は、前出のコンパイルオプション、リンクオプションです)。
- ビルドしてライブラリを生成しました。
あなたの回答
tips
プレビュー