您的位置:首页 > 编程语言 > C语言/C++

通过JNI实现Java和C++的相互调用

2012-12-19 22:46 597 查看
通过JNI实现Java和C++的相互调用
一、从Java调用C++的DLL

1. 创建Java文件

创建名为TestNative的Java文件,注意包名。

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.h和jni_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.h和jni_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.h和jni_md.h的路径。或直接把jni.h和jni_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.头文件和库文件的配置VC6和VC2008类似,菜单名称有所改变。

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

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

CodeBlocks在Project->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代码分析(待续)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: