关于JNI程序中引用另外一个lib
2013-06-26 12:40
337 查看
我最近在写一个j2se的程序,我用的是开源的org.amse.ys.zip包里的代码,这部分代码是在FBReaderJ里抽取的,但是其中包含了一些native的方法,需要用的zlib库,而FBReaderJ由于是运行在Android平台上的,它对应的so库肯定是无法在我的程序中使用,因此,在这里下载了zlib的win32运行库后,我使用
生成了org_amse_ys_zip_DeflatingDecompressor.h 头文件,内容如下:
建立VS2005 DLL工程,加入jni.h, jni_md.h, zlib的 zconf.h, 加入zdll.lib依赖,加入DeflatingDecompressor.cpp:
成功编译出DeflatingDecompressor.dll文件。
然后在的j2se工程的DeflatingDecompressor.java中使用
加载动态库,得到
使用 DependencyWalker 查看DeflatingDecompressor.dll的依赖关系,发现缺少zlib1.dll, 这时候我想起来下载的zlib发布中还有一个动态库,拷贝到System32文件夹下,再试,果然可以了。
那么这时候为什么呢?经过资料查询才知道VS编译出来的lib文件有静态和动态lib的区别,简单的说:静态lib就是把所有的代码一股脑编译进lib文件中,在使用的时候配合头文件和lib文件就可以直接用了。而动态lib则是伴随着dll生成的,其中只包含了动态加载dll的代码,通过在程序中引用它,就可以省去了显式的调用dll的繁琐。
如何判断一个lib是静态还是动态的呢?我没有找到好的办法,一般来说,静态lib的发布只有两个文件:一个头文件定义了lib中的开放接口,一个.lib文件则是实现的内容;而动态lib的文件发布包含一个头文件,一个dll文件,一个lib文件,往往还有一个def文件来列出dll中的接口。根据这个就可以判断了。
好了,这就是调用没有成功的原因,我本来已经加载的lib是一个静态lib, 其实它是一个动态lib
javah -jni org.amse.ys.zip.DeflatingDecompressor
生成了org_amse_ys_zip_DeflatingDecompressor.h 头文件,内容如下:
/* DO NOT EDIT THIS FILE - it is machine generated */ #include "jni.h" /* Header for class org_amse_ys_zip_DeflatingDecompressor */ #ifndef _Included_org_amse_ys_zip_DeflatingDecompressor #define _Included_org_amse_ys_zip_DeflatingDecompressor #ifdef __cplusplus extern "C" { #endif #undef org_amse_ys_zip_DeflatingDecompressor_IN_BUFFER_SIZE #define org_amse_ys_zip_DeflatingDecompressor_IN_BUFFER_SIZE 2048L #undef org_amse_ys_zip_DeflatingDecompressor_OUT_BUFFER_SIZE #define org_amse_ys_zip_DeflatingDecompressor_OUT_BUFFER_SIZE 32768L /* * Class: org_amse_ys_zip_DeflatingDecompressor * Method: startInflating * Signature: ()I */ JNIEXPORT jint JNICALL Java_org_amse_ys_zip_DeflatingDecompressor_startInflating (JNIEnv *, jobject); /* * Class: org_amse_ys_zip_DeflatingDecompressor * Method: endInflating * Signature: (I)V */ JNIEXPORT void JNICALL Java_org_amse_ys_zip_DeflatingDecompressor_endInflating (JNIEnv *, jobject, jint); /* * Class: org_amse_ys_zip_DeflatingDecompressor * Method: inflate * Signature: (I[BII[B)J */ JNIEXPORT jlong JNICALL Java_org_amse_ys_zip_DeflatingDecompressor_inflate (JNIEnv *, jobject, jint, jbyteArray, jint, jint, jbyteArray); #ifdef __cplusplus } #endif #endif
建立VS2005 DLL工程,加入jni.h, jni_md.h, zlib的 zconf.h, 加入zdll.lib依赖,加入DeflatingDecompressor.cpp:
/* * Copyright (C) 2009-2013 Geometer Plus <contact@geometerplus.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. */ #include <string.h> #include "zlib.h" #include <new> #include "jni.h" #include "org_amse_ys_zip_DeflatingDecompressor.h" #define SIZE 10 static z_stream* ourStreams[SIZE] = { 0 }; extern "C" JNIEXPORT jint JNICALL Java_org_amse_ys_zip_DeflatingDecompressor_startInflating(JNIEnv *env, jobject thiz) { int i; for (i = 0; i < SIZE; ++i) { if (ourStreams[i] == 0) { ourStreams[i] = new z_stream; memset(ourStreams[i], 0, sizeof(z_stream)); inflateInit2(ourStreams[i], -MAX_WBITS); return i; } } return -1; } extern "C" JNIEXPORT void JNICALL Java_org_amse_ys_zip_DeflatingDecompressor_endInflating(JNIEnv *env, jobject thiz, jint inflatorId) { if (inflatorId >= 0 && inflatorId < SIZE) { inflateEnd(ourStreams[inflatorId]); delete ourStreams[inflatorId]; ourStreams[inflatorId] = 0; } } // returns (endFlag << 32) + ((used inLength) << 16) + outLength extern "C" JNIEXPORT jlong JNICALL Java_org_amse_ys_zip_DeflatingDecompressor_inflate(JNIEnv *env, jobject thiz, jint inflatorId, jbyteArray in, jint inOffset, jint inLength, jbyteArray out) { if (inflatorId < 0 || inflatorId >= SIZE) { return -1; } z_stream *stream = ourStreams[inflatorId]; if (stream == 0) { return -2; } jbyte* inStart = env->GetByteArrayElements(in, 0); jbyte* outStart = env->GetByteArrayElements(out, 0); stream->next_in = (Bytef*)inStart + inOffset; stream->avail_in = inLength; stream->next_out = (Bytef*)outStart; const int outLength = env->GetArrayLength(out); stream->avail_out = outLength; const int code = inflate(stream, Z_SYNC_FLUSH); env->ReleaseByteArrayElements(in, inStart, 0); env->ReleaseByteArrayElements(out, outStart, 0); if (code == Z_OK || code == Z_STREAM_END) { jlong result = ((inLength - stream->avail_in) << 16) + outLength - stream->avail_out; if (code == Z_STREAM_END) { result |= ((jlong)1) << 32; } return result; } return -1024 + code; }
成功编译出DeflatingDecompressor.dll文件。
然后在的j2se工程的DeflatingDecompressor.java中使用
static { System.loadLibrary("libs/DeflatingDecompressor"); }
加载动态库,得到
Exception in thread "main" java.lang.UnsatisfiedLinkError: D:\Works\TextLayout\NewReaderSE\libs\DeflatingDecompressor.dll: Can't find dependent libraries at java.lang.ClassLoader$NativeLibrary.load(Native Method) at java.lang.ClassLoader.loadLibrary0(Unknown Source) at java.lang.ClassLoader.loadLibrary(Unknown Source) at java.lang.Runtime.loadLibrary0(Unknown Source) at java.lang.System.loadLibrary(Unknown Source) at org.amse.ys.zip.DeflatingDecompressor.<clinit>(DeflatingDecompressor.java:7)
使用 DependencyWalker 查看DeflatingDecompressor.dll的依赖关系,发现缺少zlib1.dll, 这时候我想起来下载的zlib发布中还有一个动态库,拷贝到System32文件夹下,再试,果然可以了。
那么这时候为什么呢?经过资料查询才知道VS编译出来的lib文件有静态和动态lib的区别,简单的说:静态lib就是把所有的代码一股脑编译进lib文件中,在使用的时候配合头文件和lib文件就可以直接用了。而动态lib则是伴随着dll生成的,其中只包含了动态加载dll的代码,通过在程序中引用它,就可以省去了显式的调用dll的繁琐。
如何判断一个lib是静态还是动态的呢?我没有找到好的办法,一般来说,静态lib的发布只有两个文件:一个头文件定义了lib中的开放接口,一个.lib文件则是实现的内容;而动态lib的文件发布包含一个头文件,一个dll文件,一个lib文件,往往还有一个def文件来列出dll中的接口。根据这个就可以判断了。
好了,这就是调用没有成功的原因,我本来已经加载的lib是一个静态lib, 其实它是一个动态lib
相关文章推荐
- 关于一个程序调用另外一个程序或者传值的小问题
- 关于一个普通程序启动另外一个程序的命令pm install
- 在vs2010中可以很方便的打包桌面程序和同一解决方案中一个项目引用另外一个项目的问题
- 关于面试中经常出现的根据一个随机数构造另外的随机数的解法
- 文件和文件夹被另外一个程序使用
- (转载+心得) 关于添加了一个lib之后的链接错误2005
- android一个项目引用另外一个项目和jar包引用
- 用PHP实现一个关于德州扑克算法的程序(一):发牌
- 关于一个oc写的命令行版的通讯录程序(代码贴过来无缩进,作为备忘,代码完成度:90%)
- 关于windows窗体FORM程序打包成一个安装文件
- 关于js中一个对象当做参数传递是按值传递还是按引用传递的个人看法
- 微信小程序--(5-1)点击列表item,把item上面显示的所有数据,传递到另外一个页面
- 一个程序启动另外一个程序的方法
- javasript dom 中获取元素类名 或者 改变类 引用另外一个类
- 发现一个很奇怪的现象--关于VB程序的内存占用
- jbuilder2006中web程序关于jdk版本的一个问题
- 一个关于位点的所在位置的程序
- 用PHP实现一个关于德州扑克算法的程序(二):排序
- 怎么实现一个站点的list列引用另外一个站点的list列数据?
- 如何一个android工程作为另外一个android工程的lib