走在架构师的大道上 Jack.Wang's home

Java, C++, linux c, C#.net 技术,软件架构,领域建模,IT 项目管理 Dict.CN 在线词典, 英语学习, 在线翻译

BlogJava 首页 新随笔 联系 聚合 管理
  195 Posts :: 3 Stories :: 728 Comments :: 0 Trackbacks
 

         JavaC++JNI编程小结
                               --- jack 于湖大

 1.       什么是 JNI

    JNIJava Native Interface的缩写。从Java 1.1开始,JNI标准成为java平台的一部分,它允许Java和其他语言进行交互。JNI一开始为CC++而设计的,但是它并不妨碍你使用其他语言,只要调用约定受支持就可以了。

      使用java与本地已编译的代码交互,通常会丧失平台可移植性。但是,有些情况下这样做是可以接受的,甚至是必须的,比如,使用一些旧的库,与硬件、操作系统进行交互,或者为了提高程序的性能。

   关于 JNI 的用法很简单,有点像 java 里的 reflect 的工作机制,有兴趣的朋友可以参看更详细的书

2.       JNI 开发步骤

l          编写带有native声明的方法的java

l          使用javac IDE(JBuilder,eclipse)编译所编写的java

l          使用javah -jni java类名生成扩展名为h的头文件

l          使用C++ 实现本地方法,对调用签名可用 javap –s –p [类全名] 查看(开发 C++ 动态链接库本例是用的 VC6

注意要从 JDK下面的 include 文件夹中把 jni.h jni_md.h 两个文件 copy 到你的 VC 工程里

l          Java load 动态链接库文件,调用 native 方法

3.       开发实例

1.        编写 Java : (我的 IDE eclipse)

/**

 * Jack.Wang

 */

package org.jm.jni;

import java.util.ArrayList;

/**

 * @author Jack.Wang

 * @time Mar 1, 2008

 */

public class BackgroundProcess {

   static {

        System.loadLibrary("org_jm_jni_BackgroundProcess");

}

// 三个 native 方法和一个 int 变量

    public native boolean checkValid();

    public native void processData(BackgroundProcess bg);

    public native void processGarbage(String[] bg);

    public int num = 5;

    // C++ 中可以调用的方法

    public String backProcess(ArrayList<String> p) {

        System.out.println("这是 Java 里的方法,在 C++ 中调用。");

        System.out.println("这个方法,是 java native checkValid 方法调用的。");

        return "look up process ->" + p;

    }

    public static void main(String[] args) {

        String[] array = new String[4];

        array[0] = "jack";

        array[1] = "maggie";

        array[2] = "rocket";

        array[3] = "tom";

        BackgroundProcess bgP = new BackgroundProcess();

        // 调用 C++ DLL 中定义的方法。

        bgP.checkValid();// 该方法回调 java 中的 backProcess 方法

        bgP.processData(bgP);

        bgP.processGarbage(array);

        // C++ DLL 改变了该变量

        System.out.println("number 现在的值是: " + bgP.num);

    }

}

2.        生成 C++ 的头文件(javah 命令生成,用javap –s –p [类全名] 命令查看java 方法签名

/* DO NOT EDIT THIS FILE - it is machine generated */

#include "jni.h"

/* Header for class org_jm_jni_BackgroundProcess */

#ifndef _Included_org_jm_jni_BackgroundProcess

#define _Included_org_jm_jni_BackgroundProcess

#ifdef __cplusplus

extern "C" {

#endif

/*

 * Class:     org_jm_jni_BackgroundProcess

 * Method:    checkValid

 * Signature: ()Z

 */

JNIEXPORT jboolean JNICALL Java_org_jm_jni_BackgroundProcess_checkValid

 (JNIEnv *, jobject);

/*

 * Class:     org_jm_jni_BackgroundProcess

 * Method:    processData

 * Signature: (Lorg/jm/jni/BackgroundProcess;)V

 */

JNIEXPORT void JNICALL Java_org_jm_jni_BackgroundProcess_processData

 (JNIEnv *, jobject, jobject);

/*

 * Class:     org_jm_jni_BackgroundProcess

 * Method:    processGarbage

 * Signature: ([Ljava/lang/String;)V

 */

JNIEXPORT void JNICALL Java_org_jm_jni_BackgroundProcess_processGarbage

 (JNIEnv *, jobject, jobjectArray);

#ifdef __cplusplus

}

#endif

#endif

3.        开发 C++ DLL 的原文件 (记得要加入 jni.h jni_md.h 两个文件)

发布 DLL 文件, 我是配置了 path 环境变量

#include "org_jm_jni_BackgroundProcess.h"

#include <iostream.h>

#include <windows.h>

#include "string.h"

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;

}

//char* to jstring

jstring stoJstring(JNIEnv* env, const char* pat)

{

       jclass strClass = env->FindClass("Ljava/lang/String;");

       jmethodID ctorID = env->GetMethodID(strClass, "<init>", "([BLjava/lang/String;)V");

       jbyteArray bytes = env->NewByteArray(strlen(pat));

       env->SetByteArrayRegion(bytes, 0, strlen(pat), (jbyte*)pat);

       jstring encoding = env->NewStringUTF("utf-8");

       return (jstring)env->NewObject(strClass, ctorID, bytes, encoding);

}

/*

* Class:     org_jm_jni_BackgroundProcess

* Method:    checkValid

* Signature: ()Z

*/

JNIEXPORT jboolean JNICALL Java_org_jm_jni_BackgroundProcess_checkValid

(JNIEnv *env, jobject obj){

jclass bgpClass=env->GetObjectClass(obj);

jmethodID methodId=env->GetMethodID(bgpClass,"backProcess","(Ljava/util/ArrayList;)Ljava/lang/String;");

jobject str=env->CallObjectMethod(obj,methodId,NULL);

jfieldID fieldId=env->GetFieldID(bgpClass,"num","I");

jint number=env->GetIntField(obj,fieldId);

cout << "number 值是: " <<number << endl;

env->SetIntField(obj,fieldId,100L);

return 1;    

}

/*

* Class:     org_jm_jni_BackgroundProcess

* Method:    processData

* Signature: (Lorg/jm/jni/BackgroundProcess;)V

*/

JNIEXPORT void JNICALL Java_org_jm_jni_BackgroundProcess_processData

(JNIEnv *env, jobject, jobject){

cout<< "this function do nothing " << endl;

}

/*

* Class:     org_jm_jni_BackgroundProcess

* Method:    processGarbage

* Signature: ([Ljava/lang/String;)V

*/

JNIEXPORT void JNICALL Java_org_jm_jni_BackgroundProcess_processGarbage

(JNIEnv *env, jobject, jobjectArray array){

jint size=env->GetArrayLength(array);

cout << "数组大小是: " << size << endl;

jstring tempObj=NULL;

    char *pszSTR1 = NULL;

for(int i=0;i<size;i++){

           cout << "current value is : " << i << endl;

           tempObj=(jstring)env->GetObjectArrayElement(array,i);

           const char * chars =env->GetStringUTFChars(tempObj, 0); 

    cout << chars << endl; 

   }

}

4.        现在你可以在 Java C++ 之间互调了

 





本博客为学习交流用,凡未注明引用的均为本人作品,转载请注明出处,如有版权问题请及时通知。由于博客时间仓促,错误之处敬请谅解,有任何意见可给我留言,愿共同学习进步。
posted on 2008-03-02 08:23 Jack.Wang 阅读(8921) 评论(4)  编辑  收藏 所属分类: 开发技术

Feedback

# re: Java与C++之JNI编程小结 2008-03-02 14:53 xifu
田里影院  回复  更多评论
  

# re: Java与C++之JNI编程小结 2008-03-03 12:29 Jack.Wang
有问题可以讨论  回复  更多评论
  

# re: Java与C++之JNI编程小结 2008-03-03 12:29 Jack.Wang
@xifu
什么意思  回复  更多评论
  

# re: Java与C++之JNI编程小结 2008-03-07 11:52 rocket
两个OO语言写出来的process式方法。。。
jack,写完你就不能用OO重构一下吗,呵呵  回复  更多评论
  


只有注册用户登录后才能发表评论。


网站导航: