引用:jni调用dll,http://blog.sina.com.cn/s/blog_4bb52a1601012x8j.html
引用:UnsatisfiedLinkError ,http://stackoverflow.com/questions/9984961/jni-unsatisfied-link-error-cant-find-dependent-libraries
引用:包头的问题,http://1985wanggang.blog.163.com/blog/static/7763833201101011210338/
今天因为项目需要,java工程调用原来C编写的一个dll(msc.dll)。折腾了半天终于打通了,现在把流程和中间遇到的问题记录下来。
一、JAVA的JNI主要有以下几步:
1、编写java代码(CallMSC.java),定义要引用的dll中的函数
2、用javac编译CallMSC.java生成CallMSC.class。
3、用javah编译CallMSC.class,生成CallMSC.h,用于VS实现调用dll。
4、VS创建dll工程,生成jni.dll,实现CallMSC.h中的函数,并调用msc.dll。
5、java工程集成并调用msc.dll。
二、工程代码如下:
1、CallMSC.java
package com.iflytekWS.jni.callmsc;
public class CallMSC{
static
{
System.load("d://JNI//BIN//msc.dll");
System.load("d://JNI//BIN//jni.dll");
}
public native int MSPLogin(String usr,String pwd, String params);
public native int MSPLogout();
public native String MSPSearch(String params, String text);
public native int getErrCode();
}
2、生成的CallMSC.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_iflytekWS_jni_callmsc_CallMSC */
#ifndef _Included_com_iflytekWS_jni_callmsc_CallMSC
#define _Included_com_iflytekWS_jni_callmsc_CallMSC
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_iflytekWS_jni_callmsc_CallMSC
* Method: MSPLogin
* Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL Java_com_iflytekWS_jni_callmsc_CallMSC_MSPLogin
(JNIEnv *, jobject, jstring, jstring, jstring);
/*
* Class: com_iflytekWS_jni_callmsc_CallMSC
* Method: MSPLogout
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_iflytekWS_jni_callmsc_CallMSC_MSPLogout
(JNIEnv *, jobject);
/*
* Class: com_iflytekWS_jni_callmsc_CallMSC
* Method: MSPSearch
* Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_iflytekWS_jni_callmsc_CallMSC_MSPSearch
(JNIEnv *, jobject, jstring, jstring);
/*
* Class: com_iflytekWS_jni_callmsc_CallMSC
* Method: getErrCode
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_iflytekWS_jni_callmsc_CallMSC_getErrCode
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
3、CallMSC.cpp
#include "CallMSC.h"
#include "msp_common.h"
jint errCode = 0;
JNIEXPORT jint JNICALL Java_com_iflytekWS_jni_callmsc_CallMSC_MSPLogin
(JNIEnv * env, jobject jobj, jstring jusr,jstring jpwd,jstring jstr){
const char* usr = (env)->GetStringUTFChars(jusr, 0);
const char* pwd = (env)->GetStringUTFChars(jpwd, 0);
const char* params = (env)->GetStringUTFChars(jstr, 0);
jint ret = 0;
ret = MSPLogin(usr, pwd, params);
env->ReleaseStringUTFChars(jusr, usr);
env->ReleaseStringUTFChars(jpwd, pwd);
env->ReleaseStringUTFChars(jstr, params);
errCode = 0;
return ret;
}
JNIEXPORT jint JNICALL Java_com_iflytekWS_jni_callmsc_CallMSC_MSPLogout
(JNIEnv *, jobject){
jint ret = 0;
ret = MSPLogout();
errCode = 0;
return ret;
}
JNIEXPORT jstring JNICALL Java_com_iflytekWS_jni_callmsc_CallMSC_MSPSearch
(JNIEnv * env, jobject jobj, jstring jparam, jstring jtxt){
const char* params = (env)->GetStringUTFChars(jparam, 0);
const char* text = (env)->GetStringUTFChars(jtxt, 0);
unsigned int textlength = (unsigned int )env->GetStringUTFLength(jtxt);
int ret = 0;
const char* result = MSPSearch(params, text, &textlength, &ret);
errCode = (jint) ret;
jstring jrst = env->NewStringUTF(result);
env->ReleaseStringUTFChars(jparam, params);
env->ReleaseStringUTFChars(jtxt, text);
return jrst;
}
JNIEXPORT jint JNICALL Java_com_iflytekWS_jni_callmsc_CallMSC_getErrCode
(JNIEnv *, jobject){
return errCode;
}
三、使用JNI过程中遇到的问题及注意点。
1、CallMSC.java,有package时javah命令的使用。
一开始没有添加package,在CallMSC.java所在目录下很顺利使用javac和javah命令,
后来发现要有包名,添加后使用javah命令一直无法成功。提示如下,
D:\test\source\com\iflytekWS\jni\callmsc>javah CallMSC
错误:无法访问 CallMSC
错误的类文件: .\CallMSC.class
类文件包含错误的类: com.iflytekWS.jni.callmsc.CallMSC
请删除该文件或确保该文件位于正确的类路径子目录中。
这时将目录定位到整个包所在的根目录下解决。
D:\test\source\com\iflytekWS\jni\callmsc>cd D:\test\source\
D:\test\source>javah -classpath . com.iflytekWS.jni.callmsc.CallMSC
2、JNI中jstring与const char* 相互转换时,注意GetStringUTFChars与ReleaseStringUTFChars需要配套使用。
3、Dll工程需要的jni.h可以在java JDK/include中找到,需要加载的msc.dll,msc.lib及相应头文件(本文略去)。
4、java工程调用时提示UnsatisfiedLinkError (Can't find dependent libraries)的问题。
JNI调用的dll依赖其他dll缺失,需要load进来,一开始以为和C++中调dll一样自动加载,后发现没有load msc.dll,需要手动load,System.load要指定绝对路径。load时要注意dll所依赖的库,及其引用顺序。