一步一步教会你JAVA中调用C++
装载自:http://blog.csdn.net/chenjin_zhong/article/details/5870305
一、JNI简介
JNI:Java Native Interface,是Java语言提供的一种通用接口,用于Java代码与本地化代码的交互。所谓本地化代码是指直接编译成的与机器相关的二进制代码,而非Java字节码之类的中间代码。Windows下面的可执行文件,DLL等,Linux下面的可执行文件和SO文件等,都是二进制代码。
JNI允许Java语言编写的程序与其他语言编写的程序库(DLL, SO)或可执行文件进行互操作,包括汇编、C、C++。JNI产生的原因在于以下几种需求:
(1)、你的应用程序需要使用系统相关的功能,而Java代码不支持或是难以办到。这个比较典型的是实现托盘图标,有几种现成的方案都是用的JNI做的,名字好像是叫做TrayIcon和StayOnTop。当然啦,如果是用的Java1.6,那就要另当别论了。
(2)、已有其他语言写好的类库或程序,希望Java程序可以使用它们。
(3)、出于更高的性能要求,希望使用汇编或是C/C++语言来实现部分功能。
下图出自JNI Tutorial,展示了JNI的地位:
二.在JAVA中调用C++的基本步骤
(1)、编写带有native方法的java类
(2)、使用javac命令编译所编写的java类
(3)、使用javah命令处理类文件,生成C/C++头文件
(4)、使用C/C++实现本地方法
(5)、将C/C++编写的文件生成动态连接库
(6)把生成的.dll库放到c:/windows/system32目录下
下面详解这些步骤:
(1)不用说了,就是在java中写一个带有native的方法。如:private native void sum(int x, int y);
(2)进入类所在的目录,用javac进行编译,生成.class文件。
(3)这一步很重要,很多时候都生不成c++的头文件,总是提示找不到相应的类,这时,你得检查所配置的环境变量.如果还是不行,就使用下面的命令:javah -classpath . jni com.chnic.service.business,这个命令一般情况下都会好使。
com.chnic.service是包名,business是类名。测试的类的目录是:C:/Documents and Settings/Administrator/workspace/JNI2/src/com/chnic/service下。这样你编译生成的C++头文件会出现在src目录下。
(4)打开VC++6.0建立Win32 Dynamic-Link Library.然后把你刚才生成的头文件copy到工程的目录下。例如我新建的工作目录是:D:/Program Files/Microsoft Visual Studio/MyProjects/FruitFactory, 同时还要把jni.h,jni_md.h复制到这个目录下,因为你的C++头文件中包含了这两个头文件。它们可以从jdk目录中找到,C:/Program Files/Java/jdk1.6.0_21/include目录下和C:/Program Files/Java/jdk1.6.0_21/include/win32目录下。然后你就可以在C++中实现你想要的功能了。
(5)编译,运行,生成动态链接库,例如:Business.dll
(6)然后把动态链接库放到c:/windows/system32下。这样在java中就可以执行C++中的函数了。
示例演示:
package com.chnic.service;
public class Business {
public Business(){}
static {
System.loadLibrary("FruitFactory");
}
public native double getPrice(String name);
public native Order getOrder(String name,int amount);
public native Order getRamdomOrder();
public native static void analyzeOrder(Order order);
public void notification(){
System.out.println("Got a notification");
}
public static void notificationByStatic(){
System.out.println("Got a notification in a static method");
}
}
java代码:
package com.chnic.service;
public class Order {
private String name="Fruit";
private double price;
private int amount=30;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public int getAmount() {
return amount;
}
public void setAmount(int amount) {
this.amount = amount;
}
}
c++代码:
#include <iostream.h>
#include <string.h>
#include "com_chnic_service_Business.h"
jobject getInstance(JNIEnv* env,jclass obj_class);
JNIEXPORT jdouble JNICALL Java_com_chnic_service_Business_getPrice
(JNIEnv* env, jobject obj, jstring name){
const char* pname=env->GetStringUTFChars(name,NULL);
if(strcmp(pname,"Apple")==0){
env->ReleaseStringUTFChars(name,pname);
cout<<"After release:"<<pname<<endl;
return 1.2;
}
else{
env->ReleaseStringUTFChars(name,pname);
cout<<"After release:"<<pname<<endl;
return 2.1;
}
}
JNIEXPORT jobject JNICALL Java_com_chnic_service_Business_getOrder
(JNIEnv* env, jobject obj, jstring name, jint amount){
jclass order_class=env->FindClass("com/chnic/service/Order");
jobject order=getInstance(env,order_class);
jmethodID setName_method=env->GetMethodID(order_class,"setName","(Ljava/lang/String;)V");
env->CallVoidMethod(order,setName_method,name);
jmethodID setAmount_method=env->GetMethodID(order_class,"setAmount","(I)V");
env->CallVoidMethod(order,setAmount_method,amount);
return order;
}
JNIEXPORT jobject JNICALL Java_com_chnic_service_Business_getRamdomOrder
(JNIEnv* env, jobject obj){
jclass business_class = env->GetObjectClass(obj);
jobject business_obj = getInstance(env, business_class);
jmethodID notification_method = env->GetMethodID(business_class, "notification", "()V");
env->CallVoidMethod(business_obj, notification_method);
jclass order_class=env->FindClass("com/chnic/service/Order");
jobject order=getInstance(env,order_class);
jfieldID amount_field=env->GetFieldID(order_class,"amount","I");
jint amount=env->GetIntField(order,amount_field);
cout<<"amount:"<<amount<<endl;
return order;
}
JNIEXPORT void JNICALL Java_com_chnic_service_Business_analyzeOrder
(JNIEnv* env, jclass cls, jobject obj){
jclass order_class = env->GetObjectClass(obj);
jmethodID getName_method = env->GetMethodID(order_class, "getName", "()Ljava/lang/String;");
jstring name_str = static_cast<jstring>(env->CallObjectMethod(obj, getName_method));
const char* pname = env->GetStringUTFChars(name_str, NULL);
cout << "Name in Java_com_chnic_service_Business_analyzeOrder: " << pname << endl;
jmethodID notification_method_static = env->GetStaticMethodID(cls, "notificationByStatic", "()V");
env->CallStaticVoidMethod(cls, notification_method_static);
}
jobject getInstance(JNIEnv* env, jclass obj_class)
{
jmethodID construction_id = env->GetMethodID(obj_class, "<init>", "()V");
//得到构造方法的ID
jobject obj = env->NewObject(obj_class, construction_id);
//根据构造方法得到相应的类的对象
return obj;
}
主要解释一下C++中的方法:
GetStringUTFChars:把字符串类型(jstring)转换成char。
ReleaseStringUTFChars:释放字符串空间。因为创建时需要分配内存,所以释放一下。
FindClass:根据类名找到相应的类对象。需要完整的包名+类名。
GetObjectClass:传入的参数是对象,根据对象找到相应的class.
GetFieldID,GetMethodID:找到相应的成员变量与成员方法的ID。由于对成员变量的取值与设置值分成两个步骤,第一步是得到相应的ID,第二步是根据ID号取值或设置值。传入的参数有:class,成员变量(方法名),变量(方法签名)。签名可由:javap -s 类名(business)得到。
GetIntField得到相应变量的值,传入的参数是obj,与变量的id.
GetStaticIntField得到静态变量的值。传入的参数是class,变量的id.
SetIntField设置变量的值。
SetStaticIntField设置静态变量的值。
GetObjectField,SetObjectField如果想得到字符串的值,与设置字符串的值。如:
jfieldID fid;//store the field ID
jstring jstr;
const char* str;
jclass cls=env->GetObjectClass(obj);//get class
fid=env->GetFieldID(cls,"s","Ljava/lang/String;");
if(fid==NULL){
return;
}
jstr=(jstring)(env->GetObjectField(obj,fid));//分为两步,第一步得到的是field
//的id,第二步才能得到field的值
str=env->GetStringUTFChars(jstr,NULL);//转换成char类型
if(str==NULL){
return;
}
cout<<"In C:"<<endl;
cout<<"c.s="<<str<<endl;
//创建一个string然后赋值给field
jstr=env->NewStringUTF("123");
if(jstr==NULL){
return;
}
env->SetObjectField(obj,fid,jstr);//给这个field赋值
CallVoidMethod:调用非静态方法,传入的参数是obj,方法的ID。
CallStaticVoidMethod:调用的是静态方法,传入的参数是class,方法的ID。
NewStringUTF(string str):用来构造一下字符串对象
关于JNI基本的内容就介绍到这了。
一步一步教会你JAVA中调用C++相关推荐
- java中调用python
在Java中调用Python </h1><div class="clear"></div><div class="postBod ...
- java 调用 go_实践总结:在 Java 中调用 Go 代码
在 Java 中调用 Go 的大致过程如下go --> cgo --> jna --> java 整个过程要解决的问题主要两个:数据类型在两种语言中如何转化 何时清理无用的数据 下面 ...
- 在Java中调用Python,java面试题,java初级笔试题
写在最前面,我总结出了很多互联网公司的面试题及答案,并整理成了文档,以及各种学习的进阶学习资料,免费分享给大家.扫码加微信好友进[程序员面试学习交流群],免费领取.也欢迎各位一起在群里探讨技术. 写在 ...
- 在Java中调用Python
写在前面 参考:https://www.cnblogs.com/nuccch/p/8435693.html 在微服务架构大行其道的今天,对于将程序进行嵌套调用的做法其实并不可取,甚至显得有些愚蠢.当然 ...
- 如何在java中调用js方法
[java] view plain copy/* * 加载脚本引擎,并在java中调用js方法 */ public void test2() { ScriptEngineManager manager ...
- java 中调用 Matlab 的函数
一.matlab版本必须支持java 在command 模式下面运行deploytool,如果支持该命令即可使用 二.matlab中function的书写 %定义一个函数operation(a,b), ...
- java执行python脚本_使用Runtime.getRuntime().exec()在java中调用python脚本
举例有一个Python脚本叫test.py,现在想要在Java里调用这个脚本.假定这个test.py里面使用了拓展的包,使得pythoninterpreter之类内嵌的编译器无法使用,那么只能采用ja ...
- java oracle sql 参数_oracle pl/sql之在java中调用带有输入输出参数的oracle存储过程...
只需注意一点输出参数是用CallableStatement里面的registerOutParameter方法注册进去 存储过程: import java.sql.CallableStatement; ...
- 如何通过JNI在Java中调用C库函数
使用Java语言进行开发时,可能由于处理速度.硬件控制或者复用既有的C/C++模块等方面的原因,需要Java层与使用C/C++编写的应用.模块或库进行交互,共同完成某些任务.在两者之间充当连接桥梁作用 ...
最新文章
- HttpHandler与HttpModule区别
- HDU 2191 - 悼念512汶川大地震遇难同胞——珍惜现在,感恩生活 (多重背包)
- @产品部 -- 腾讯策划部是如何培养用户的《王者荣耀》“瘾”的
- 软件设计模式—控制反转
- HDU - 5788 Level Up(主席树+dfs序+树状数组)
- nginx 二进制包安装mysql_二进制安装mysql5.7
- 图像分割——迭代式阈值分割
- edit with idle 没反应_搬个家,猫咪不吃不喝甚至猝死?可能是你没做好“前戏”...
- 《Android游戏编程入门经典》——14.4节问与答
- html5在线加密,HTML技巧——加密网页
- SpringBoot整合ureport2
- mysql能上传程序吗_利用mysql上传和执行文件
- 计算机智能的技术的应用,计算机人工智能技术的应用与发展(1)
- 小程序 获取地理位置
- glassfish插件_Maven嵌入式Glassfish插件-未启动
- 用友U8案例教程销售管理后台配置
- c语言字符串atoi函数,C++_C语言中一些将字符串转换为数字的函数小结,C语言atoi()函数:将字符串转换 - phpStudy...
- 好年货不用多等 拼多多30亿红包聚焦全国全球尖货好物
- #### mysql联合索引 注意事项 ####
- 蚂蚁金服开源-SofaRpc源码学习篇
热门文章
- excel2016html,教大家Excel2016表格数据要怎么添加迷你图
- 便签加密设置取消指纹解密
- 固态硬盘多大合适 php,固态硬盘(SSD)显示容量为何比真实容量小?
- (转载)如何设计一个百万级用户的抽奖系统?
- 华为智慧屏v65鸿蒙系统评测,【华为智慧屏V65评测】从荣耀智慧屏到华为智慧屏 大屏时代已经拉开-中关村在线...
- 越读越有味的句子 绝对经典语录 人生感悟格言
- 计算机应用网线接口亮红灯,网线插在电脑上网口灯不亮是为什么?
- xbox手柄接收器驱动_新手有什么PC电脑手柄推荐?简单易懂5分钟教会你做出选择...
- 学历高 机器学习_找一份机器学习的工作,学历有多重要?
- 【C语言】sizeof和strlen的区别