zoukankan      html  css  js  c++  java
  • 通过JNI实现Java和C++的相互调用(转)

    通过JNI实现JavaC++的相互调用

    一、Java调用C++DLL

    1.    创建Java文件

    创建名为TestNativeJava文件,注意包名。

    package org.druze.test;

    publicclass TestNative {

        publicnativevoid sayHello();

        publicvoid sayHello2(){

           System.out.println("Say Hello From Java");

        }

    }

    如代码所示,对于sayHello方法声明为native,这一部分将由C++的动态库来实现。

    2.    生成class文件

    使用javac org/druze/test/TestNative.java生成class文件

    注意:执行该命令在org所在目录执行。

    3.    使用javah命令生成相应的C++头文件

    使用javah org.druze.test.TestNative生成名为

    org_druze_test_TestNative.h的头文件

    注意:执行该命令在org所在目录执行。

    该头文件的内容如下:

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

    #include <jni.h>

    /* Header for class org_druze_test_TestNative */

    #ifndef _Included_org_druze_test_TestNative

    #define _Included_org_druze_test_TestNative

    #ifdef __cplusplus

    extern "C" {

    #endif

    /*

     * Class:     org_druze_test_TestNative

     * Method:    sayHello

     * Signature: ()V

     */

    JNIEXPORT void JNICALL Java_org_druze_test_TestNative_sayHello

     (JNIEnv *, jobject);

    #ifdef __cplusplus

    }

    #endif

    #endif

    4.    创建C++解决方案

    此处以VS2008为例。

    新建一个VC++Win32项目,选择如图所示的控制台应用程序。项目名称为NativeCode

    点击确定后,再点击下一步,出现该页面,应用程序类型选择DLL,附加选项选择DLL

    5.    创建号工程之后,将org_druze_test_TestNative.h导入到工程里面,并创建名为source.cpp的源代码,内容如下:

    #include"org_druze_test_TestNative.h"  

    #include<iostream>  

    using namespace std;  

    JNIEXPORT void JNICALL Java_org_druze_test_TestNative_sayHello(JNIEnv *env, jobject obj)

    {  

        cout<<"Hello World!"<<endl;  

    6.    在工具->选项->项目和解决方案->VC++目录菜单中,平台选择Win32,选择“显示以下内容的目录”为“包含文件”,导入jni.hjni_md.h的路径。

    7.    编译,生成NativeCode.dll,并将其copy到环境变量PATH的路径下。

    8.    修改TestNative.java

    package org.druze.test;

    publicclass TestNative {

        publicnativevoid sayHello();

        publicstaticvoid main(String[] args) {

            // 加载动态连接库DLL,如果没有找到的话,则会在运行时报错  

            System.loadLibrary("NativeCode");  

              

            TestNative tnt = new TestNative();  

                  

            tnt.sayHello();  

        }

        publicvoid sayHello2(){

           System.out.println("Say Hello From Java");

        }

    }

    运行,显示“Hello World! 

    9.    注意头文件jni.hjni_md.h可以直接导入到工程中也可以。

    10.注意NativeCode.dll必须放置在java命令能访问的路径中。

    二、C++调用Java

    1.创建TestNative2.Java

    package org.druze.test;

    publicclass TestNative2 {

        publicstaticvoid testPrint(){

           System.out.println("this is from static method");

        }

        publicstaticint testReturn(){

           return 22;

        }

        publicstaticint testInput(int number){

           return 22+number;

        }

        publicint testInstance(int number){

           System.out.println("this is from instance method");

           return 11+number;

        }

    }

    2.VS2008中创建win32控制台的应用程序,命名为NativeCode2,在向导中选择空项目。

    3. 在工具->选项->项目和解决方案->VC++目录菜单中,平台选择Win32,选择“显示以下内容的目录”为“包含文件”,导入jni.hjni_md.h的路径。直接把jni.hjni_md.h导入到工程中。

    4. 在工具->选项->项目和解决方案->VC++目录菜单中,平台选择Win32,选择“显示以下内容的目录”为“包含文件”,导入jvm.lib的路径,并在项目->NativeCode2属性->配置属性->链接器->命令行中添加jvm.lib(这一步或者使用#pragma comment(lib,"jvm.lib")来代替)。或者将直接将jvm.lib添加到工程中。

    5.创建Test.cpp

    #include <jni.h>

    #include <iostream>

    using namespace std;

    int main()

    {

        JavaVMOption options[1];

        JNIEnv * env;

        JavaVM * jvm;

        JavaVMInitArgs vm_args;

        options[0].optionString = "-Djava.class.path=.";

        vm_args.version = JNI_VERSION_1_6;

        vm_args.nOptions = 1;

        vm_args.options = options;

        vm_args.ignoreUnrecognized = JNI_TRUE;

        long status = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);

        if (status == JNI_ERR)

        {

            cout<<"Can not create JVM"<<endl;

            return -1;

        }

        printf("Created JVM"n");

        jclass cls = env->FindClass("org/druze/test/TestNative2");

        printf("getCls"n");

         cout<<cls<<endl;

        if (cls !=0)

        {

            jmethodID mid = env->GetStaticMethodID(cls, "testReturn", "()I");

            printf("getMid"n");

            if (mid !=0)

            {

                printf("testReturn"n");

                int result=env->CallStaticIntMethod(cls, mid);

                printf("call over result=%d"n",result);

            }

            mid = env->GetStaticMethodID(cls, "testPrint", "()V");

            if (mid !=0)

            {

                printf("testPrint"n");

                env->CallStaticVoidMethod(cls, mid);

            }

            mid = env->GetStaticMethodID(cls, "testInput", "(I)I");

            if (mid !=0)

            {

                printf("testInput"n");

                int result=env->CallStaticIntMethod(cls, mid,22);

                printf("call over result=%d"n",result);

            }

            mid = env->GetMethodID(cls,"<init>","()V");

            if (mid != 0)//获取方法成功

            {

                printf("ctro!=0"n");

                jobject obj=env->NewObject(cls, mid);

                printf("new object"n");

                mid = env->GetMethodID(cls, "testInstance","(I)I");

                if (mid!=0)//获取方法成功

                {

                    printf("methodID!=0"n");

                    jint result=env->CallIntMethod( obj, mid,22);

                    cout<<result<<endl;

                }

            }

        }

        jvm->DestroyJavaVM();

        system("Pause");

        return 0;

    }

    6.jvm.dll目录添加到PATH环境变量中,将org/druze/test/TestNative2复制到debug目录下执行。

    7.头文件和库文件的配置VC6VC2008类似,菜单名称有所改变。

    VC6中,配置头文件和库文件的目录在,工具(Tools)->选项(Options)->目录(Directories)里面的头文件”Include files”和库文件”Library files”.添加相应的目录

    工程(Project)->设置(Setting)->链接(Link)->object/module library后面添加jvm.lib

    CodeBlocksProject->Build options->Linker setting and Search directories中配置相应路径。

    8.按如下结构组织可不用配置jvm.dll到环境变量中

    创建存放目录Run(下面的文件目录在JDK安装目录中都能找倒):

    Run(手工建立目录)

    ----bin(手工建立目录)

          ----classic(手工建立目录)

                ----jvm.dll(文件,JDK安装目录中有)

                ----自己的JAR包,如果是class文件把包目录和文件一起拷贝过来

                     如果是jar文件,需要在options[1].optionString = "-Djava.class.path=.;./swt.jar";中设置

                ----JniC.exe,C调用JAVA的程序

          ----hpi.dll(文件,JDK安装目录中有)

          ----ioser12.dll(文件,JDK安装目录中有)

          ----java.dll(文件,JDK安装目录中有)

          ----net.dll(文件,JDK安装目录中有)

          ----verify.dll(文件,JDK安装目录中有)

         ----zip.dll(文件,JDK安装目录中有)

    ----lib(手工建立目录)

          ----zi(目录,JDK安装目录中有,全部拷贝过来)

          ----rt.jar(文件,JDK安装目录中有)

          ----tzmappings(文件,JDK安装目录中有)

    三、JNI代码分析(待续)

  • 相关阅读:
    状态压缩 + 暴力 HDOJ 4770 Lights Against Dudely
    简单几何(推公式) UVA 11646 Athletics Track
    简单几何(四边形形状) UVA 11800 Determine the Shape
    简单几何(求交点) UVA 11437 Triangle Fun
    计算几何模板
    简单几何(相对运动距离最值) UVA 11796 Dog Distance
    简单几何(求划分区域) LA 3263 That Nice Euler Circuit
    覆盖的面积 HDU
    Desert King 最小比率生成树 (好题)
    约会安排 (区间合并)毒瘤题
  • 原文地址:https://www.cnblogs.com/GeneralXU/p/1850957.html
Copyright © 2011-2022 走看看