關於JNI程序中引用另一個lib

我最近在寫一個j2se的程序,我用的是開源的org.amse.ys.zip包裏的代碼,這部分代碼是在FBReaderJ裏抽取的,可是其中包含了一些native的方法,須要用的zlib庫,而FBReaderJ因爲是運行在Android平臺上的,它對應的so庫確定是沒法在個人程序中使用,所以,在這裏下載了zlib的win32運行庫後,我使用 java

1 javah -jni org.amse.ys.zip.DeflatingDecompressor

生成了org_amse_ys_zip_DeflatingDecompressor.h 頭文件,內容以下:redis

 1 /* DO NOT EDIT THIS FILE - it is machine generated */
 2 #include "jni.h"
 3 /* Header for class org_amse_ys_zip_DeflatingDecompressor */
 4 
 5 #ifndef _Included_org_amse_ys_zip_DeflatingDecompressor
 6 #define _Included_org_amse_ys_zip_DeflatingDecompressor
 7 #ifdef __cplusplus
 8 extern "C" {
 9 #endif
10 #undef org_amse_ys_zip_DeflatingDecompressor_IN_BUFFER_SIZE
11 #define org_amse_ys_zip_DeflatingDecompressor_IN_BUFFER_SIZE 2048L
12 #undef org_amse_ys_zip_DeflatingDecompressor_OUT_BUFFER_SIZE
13 #define org_amse_ys_zip_DeflatingDecompressor_OUT_BUFFER_SIZE 32768L
14 /*
15  * Class:     org_amse_ys_zip_DeflatingDecompressor
16  * Method:    startInflating
17  * Signature: ()I
18  */
19 JNIEXPORT jint JNICALL Java_org_amse_ys_zip_DeflatingDecompressor_startInflating
20   (JNIEnv *, jobject);
21 
22 /*
23  * Class:     org_amse_ys_zip_DeflatingDecompressor
24  * Method:    endInflating
25  * Signature: (I)V
26  */
27 JNIEXPORT void JNICALL Java_org_amse_ys_zip_DeflatingDecompressor_endInflating
28   (JNIEnv *, jobject, jint);
29 
30 /*
31  * Class:     org_amse_ys_zip_DeflatingDecompressor
32  * Method:    inflate
33  * Signature: (I[BII[B)J
34  */
35 JNIEXPORT jlong JNICALL Java_org_amse_ys_zip_DeflatingDecompressor_inflate
36   (JNIEnv *, jobject, jint, jbyteArray, jint, jint, jbyteArray);
37 
38 #ifdef __cplusplus
39 }
40 #endif
41 #endif

創建VS2005 DLL工程,加入jni.h, jni_md.h, zlib的 zconf.h, 加入zdll.lib依賴,加入DeflatingDecompressor.cpp:this

 1 /*
 2  * Copyright (C) 2009-2013 Geometer Plus <contact@geometerplus.com>
 3  *
 4  * This program is free software; you can redistribute it and/or modify
 5  * it under the terms of the GNU General Public License as published by
 6  * the Free Software Foundation; either version 2 of the License, or
 7  * (at your option) any later version.
 8  *
 9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301, USA.
18  */
19 #include <string.h>
20 #include "zlib.h"
21 
22 #include <new>
23 #include "jni.h"
24 #include "org_amse_ys_zip_DeflatingDecompressor.h"
25 
26 #define                                SIZE                            10
27 
28 static z_stream*            ourStreams[SIZE]            = { 0 };
29 
30 extern "C"
31 JNIEXPORT jint JNICALL Java_org_amse_ys_zip_DeflatingDecompressor_startInflating(JNIEnv *env, jobject thiz) {
32     int i;
33     for (i = 0; i < SIZE; ++i) {
34         if (ourStreams[i] == 0) {
35             ourStreams[i] = new z_stream;
36             memset(ourStreams[i], 0, sizeof(z_stream));
37             inflateInit2(ourStreams[i], -MAX_WBITS);
38             return i;
39         }
40     }
41     return -1;
42 }
43 
44 extern "C"
45 JNIEXPORT void JNICALL Java_org_amse_ys_zip_DeflatingDecompressor_endInflating(JNIEnv *env, jobject thiz, jint inflatorId) {
46     if (inflatorId >= 0 && inflatorId < SIZE) {
47         inflateEnd(ourStreams[inflatorId]);
48         delete ourStreams[inflatorId];
49         ourStreams[inflatorId] = 0;
50     }
51 }
52 
53 // returns (endFlag << 32) + ((used inLength) << 16) + outLength
54 extern "C"
55 JNIEXPORT jlong JNICALL Java_org_amse_ys_zip_DeflatingDecompressor_inflate(JNIEnv *env, jobject thiz, jint inflatorId, jbyteArray in, jint inOffset, jint inLength, jbyteArray out) {
56     if (inflatorId < 0 || inflatorId >= SIZE) {
57         return -1;
58     }
59     z_stream *stream = ourStreams[inflatorId];
60     if (stream == 0) {
61         return -2;
62     }
63 
64     jbyte* inStart = env->GetByteArrayElements(in, 0);
65     jbyte* outStart = env->GetByteArrayElements(out, 0);
66     stream->next_in = (Bytef*)inStart + inOffset;
67     stream->avail_in = inLength;
68     stream->next_out = (Bytef*)outStart;
69     const int outLength = env->GetArrayLength(out);
70     stream->avail_out = outLength;
71     const int code = inflate(stream, Z_SYNC_FLUSH);
72     env->ReleaseByteArrayElements(in, inStart, 0);
73     env->ReleaseByteArrayElements(out, outStart, 0);
74     if (code == Z_OK || code == Z_STREAM_END) {
75         jlong result = ((inLength - stream->avail_in) << 16) + outLength - stream->avail_out;
76         if (code == Z_STREAM_END) {
77             result |= ((jlong)1) << 32;
78         }
79         return result;
80     }
81     return -1024 + code;
82 }

成功編譯出DeflatingDecompressor.dll文件。spa

而後在的j2se工程的DeflatingDecompressor.java中使用.net

1 static {
2     System.loadLibrary("libs/DeflatingDecompressor");
3 }

加載動態庫,獲得code

1 Exception in thread "main" java.lang.UnsatisfiedLinkError: D:\Works\TextLayout\NewReaderSE\libs\DeflatingDecompressor.dll: Can't find dependent libraries
2     at java.lang.ClassLoader$NativeLibrary.load(Native Method)
3     at java.lang.ClassLoader.loadLibrary0(Unknown Source)
4     at java.lang.ClassLoader.loadLibrary(Unknown Source)
5     at java.lang.Runtime.loadLibrary0(Unknown Source)
6     at java.lang.System.loadLibrary(Unknown Source)
7     at org.amse.ys.zip.DeflatingDecompressor.<clinit>(DeflatingDecompressor.java:7)

使用 DependencyWalker 查看DeflatingDecompressor.dll的依賴關係,發現缺乏zlib1.dll, 這時候我想起來下載的zlib發佈中還有一個動態庫,拷貝到System32文件夾下,再試,果真能夠了。blog

那麼這時候爲何呢?通過資料查詢才知道VS編譯出來的lib文件有靜態和動態lib的區別,簡單的說:靜態lib就是把全部的代碼一股腦編譯進lib文件中,在使用的時候配合頭文件和lib文件就能夠直接用了。而動態lib則是伴隨着dll生成的,其中只包含了動態加載dll的代碼,經過在程序中引用它,就能夠省去了顯式的調用dll的繁瑣。接口

如何判斷一個lib是靜態仍是動態的呢?我沒有找到好的辦法,通常來講,靜態lib的發佈只有兩個文件:一個頭文件定義了lib中的開放接口,一個.lib文件則是實現的內容;而動態lib的文件發佈包含一個頭文件,一個dll文件,一個lib文件,每每還有一個def文件來列出dll中的接口。根據這個就能夠判斷了。ip

好了,這就是調用沒有成功的緣由,我原本已經加載的lib是一個靜態lib, 其實它是一個動態libget

相關文章
相關標籤/搜索