JNI的开发Demo

即使是基于windows平台,在一般情况下,Java就够用了,或者单独的C++也够用,但由于一些第三方调用以及往系统底层调用的情形,我们往往避免不了互相调用。这不最近Java desktop application用到usb-key,需要调用它的库进行加密、文件读写,重拾了JNI技术,写个帖子留念下。

 

一般来说Java调用C++的话一般是通过JNI;而C++调用Java的话一般是靠C++启动jvm,在这个jvm环境里执行java class。这种互调几年以很流行,记得当时IBM还弄了一套专门的基于eclipse的插件工具(DTJCB:development tool for Java COM Bridge),它可以实现双向调用,能自动生成许多代码,功能很是强大,而且是前绑定,效率比较高,但不知为何后来不更新了。目前用的比较多的jacob,是基于后绑定的,个人感觉参数用起来很诡异,不习惯。

 

JNI(Java Native Interface),即Java本地化接口,下面谈谈它的一般开发步骤:

1.在java 类中写native方法,它就像定义abstract方法一样,不过就是把abstract换成native。

 

比如定义了类TestJNI和native方法

package org.csdn;

public class TestJNI

{

 static
 {
  System.loadLibrary("TestJNI");
 }

public native String restoreLicense(String content);

}

 

2.javah生成C端的头文件,注意这步有前提:注册了环境变量,包括JAVA_HOME,PATH,CLASSPATH;

在cmd进入TestJNI所在class目录,比如为【D:/workspace/Test/bin/org/csdn】,然后执行javah命令

D:/workspace/Test/bin/org/csdn>javah -classpath D:/workspace/Test/bin/org/csdn org.csdn.TestJNI

要注意这里的目录,以及包名

执行成功以后,会在【D:/workspace/Test/bin/org/csdn】目录下看到org_csdn_TestJNI.h这个C端的头文件,它包含一个接口:

/*
 * Class:     org_csdn_TestJNI

 * Method:    restoreLicense
 * Signature: (Ljava/lang/String;)Z
 */
JNIEXPORT jstring JNICALL Java_org_csdn_TestJNI_restoreLicense (JNIEnv *, jobject, jstring);

 

3.建立Win32 Dynamic-Link Library 的C++工程,工程名为TestJNI,并实现头文件。把org_csdn_TestJNI.h拷贝到工程目录下,然后添加类org_csdn_TestJNI.cpp实现它。org_csdn_TestJNI.cpp中的方法实现:

 

#include <jni.h>
#include "org_csdn_TestJNI.h"

JNIEXPORT jstring Java_org_csdn_TestJNI_restoreLicense(JNIEnv *env, jobject obj, jstring content)
{

....

return NewJString(env, 0);

}

可能会找不到jni.h头文件,需要去%JAVA_HOME%/include目录下拷贝jni.h以及%JAVA_HOME%/include/win32目录下拷贝jawt_md.h和jni_md.h,粘贴到%VISUALSTUDIO_HOME%/VC98/Include目录下去。

 

4.编译并构件C++工程TestJNI,生成TestJNI.dll,拷贝到Java工程TestJNI的根目录下,即可运行Java测试刚才的工作。

------------------------------------------------------------------------

附带几个JNI中常用类型转换的方法:

/**
LPCTSTR转换成jstring
*/
jstring NewJString(JNIEnv * env, LPCTSTR str)
{
    if (!env || !str)
        return 0;
    int slen = strlen(str);
    jchar * buffer = new jchar[slen];
    int len = MultiByteToWideChar(CP_ACP, 0, str, strlen(str), buffer, slen);
    if (len > 0 && len < slen)
        buffer[len] = 0;
    jstring js = env->NewString(buffer, len);
    delete [] buffer;
    return js;
}

 

/**
jstring转换成char*
*/
char* jstringTostring(JNIEnv* env, jstring jstr)
{
 char* rtn = NULL;
 jclass clsstring = env->FindClass("java/lang/String");
 jstring strencode = env->NewStringUTF("utf-8");
    jmethodID mid = env->GetMethodID(clsstring, "getBytes", "(Ljava/lang/String;)[B");
    jbyteArray barr= (jbyteArray)env->CallObjectMethod(jstr, mid, strencode);
    jsize alen = env->GetArrayLength(barr);
    jbyte* ba = env->GetByteArrayElements(barr, JNI_FALSE);
    if (alen > 0)
    {
  rtn = (char*)malloc(alen + 1);
  memcpy(rtn, ba, alen);
  rtn[alen] = 0;
 }
 env->ReleaseByteArrayElements(barr, ba, 0);
 return rtn;
}


另外
jboolean 可以直接用true和false。

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值