JNI初体验

因为需要接入统一的安全服务,调用验证码接口,对方是使用UDP协议进行通信,并且不提供http service调用接口,没有提供客户端包,丢了一个C的协议和client包过来,本想用java socket来自己实现协议,但是协议甚至麻烦,一看就想死,无奈考虑JNI调用实现。

JAVA的定义的接口如下:

public class VerifyCoder {

	static {
		try {
			System.loadLibrary("vc");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public native ImageCode getCoderImage(Service[] services,int timeout,int appid,String clientIP,long uin,int type,String filename);
	
	public native ImageCode getCoderBytes(Service[] services,int timeout,int appid,String clientIP,long uin,int type);
	
	public native int vefiryCoder(Service[] services,int timeout,int appid,String clientIP,String code,String sig);

}

接口:
public native ImageCode getCoderImage(Service[] services,int timeout,int appid,String clientIP,long uin,int type,String filename);
可用于指定文件存储参数,用于生成验证码图片,返回图片绝对路径。理论上该filename可以实用sessionid作为临时名称,或者考虑实用tmpnam生成。

接口:
public native ImageCode getCoderBytes(Service[] services,int timeout,int appid,String clientIP,long uin,int type);
可用于获取验证码的二进制数据数组。

接口:
public native int vefiryCoder(Service[] services,int timeout,int appid,String clientIP,String code,String sig);
主要是用签名和用户填写的验验证码进行校验,返回标志位。

利用javah VerifyCode生成头文件,如下:
#include <jni.h>
/* Header for class com_corey_verifycode_VerifyCoder */

#ifndef _Included_com_corey_verifycode_VerifyCoder
#define _Included_com_corey_verifycode_VerifyCoder
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_qq_verifycode_VerifyCoder
 * Method:    getCoderImage
 * Signature: ([Lcom/qq/verifycode/Service;IILjava/lang/String;JILjava/lang/String;)Lcom/qq/verifycode/ImageCode;
 */
JNIEXPORT jobject JNICALL Java_com_qq_verifycode_VerifyCoder_getCoderImage
  (JNIEnv *, jobject, jobjectArray, jint, jint, jstring, jlong, jint, jstring);

/*
 * Class:     com_qq_verifycode_VerifyCoder
 * Method:    getCoderBytes
 * Signature: ([Lcom/corey/verifycode/Service;IILjava/lang/String;JI)Lcom/qq/verifycode/ImageCode;
 */
JNIEXPORT jobject JNICALL Java_com_qq_verifycode_VerifyCoder_getCoderBytes
  (JNIEnv *, jobject, jobjectArray, jint, jint, jstring, jlong, jint);

/*
 * Class:     com_qq_verifycode_VerifyCoder
 * Method:    vefiryCoder
 * Signature: ([Lcom/corey/verifycode/Service;IILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)I
 */
JNIEXPORT jint JNICALL Java_com_corey_verifycode_VerifyCoder_vefiryCoder
  (JNIEnv *, jobject, jobjectArray, jint, jint, jstring, jstring, jstring);

#ifdef __cplusplus
}
#endif
#endif


其中env是函数调用指针集合,提供了很多函数,jobject是this对象,后续则是参数。
数组处理:
jsize serviceLength=(env)->GetArrayLength(services);
	stInit.iSvrNum = serviceLength;
	for(int i=0;i<serviceLength;i++){
		jobject service=(env)->GetObjectArrayElement(services,i);
		jclass serviceClass=(env)->FindClass("com/qq/verifycode/Service");
		jfieldID ipFieldID=(env)->GetFieldID(serviceClass,"ip","Ljava/lang/String;");
		jfieldID portFieldID=(env)->GetFieldID(serviceClass,"port","I");	
		jint port=(env)->GetIntField(service,portFieldID);
		stInit.stRemoteSvr[i].usSvrPort = port;
		jstring jip=(jstring)(env)->GetObjectField(service,ipFieldID);
		char* ip=(char*)(env)->GetStringUTFChars(jip,NULL);
		strncpy(stInit.stRemoteSvr[i].aszIp, ip, sizeof(stInit.stRemoteSvr[i].aszIp) - 1);
		env->ReleaseStringUTFChars(jip,ip);
	}

java对象的构建:

	jclass imageCodeClass=(env)->FindClass("com/qq/verifycode/ImageCode");
        jfieldID imagePathFieldID=(env)->GetFieldID(imageCodeClass,"imagePath","Ljava/lang/String;");
	jfieldID sigFieldID=(env)->GetFieldID(imageCodeClass,"sig","Ljava/lang/String;");
	jmethodID construction_id=(env)->GetMethodID(imageCodeClass,"<init>","()V");
	jobject imageCode = (env)->NewObject(imageCodeClass, construction_id);

java对象的字段和方法的调用:
env->SetObjectField(imageCode,imagePathFieldID,(env)->NewStringUTF(""));
env->SetObjectField(imageCode,sigFieldID,(env)->NewStringUTF("getCaptcha error"));


字符串的转换和释放:
char * clientIP =(char*)env->GetStringUTFChars(jclientIP,NULL);
env->ReleaseStringUTFChars(jclientIP,clientIP);

byte数组和char数组转换:
	char* data=(char*)stOut.aucPicBuffer;
	jbyteArray bytes=0;
	bytes=(env)->NewByteArray(stOut.usPicData);
	if(bytes!=NULL){
		(env)->SetByteArrayRegion(bytes,0,stOut.usPicData,(jbyte*)data);
	}



你可能感兴趣的:(java,String,jni,service,Class,construction)