C++ 和 java互相调用

1>:什么是JNI

    JNI的全称是Java Native Interface
    当java语言无法实现应用需求的时候,java允许在JVM中调用其他语言编写的代码比如C, C++,汇编等。
   

2>:基本规范:

  java中定义一个本地方法必须用Native 作为方法修饰
  调用本地方法时候必须先加载相关DLL
  相关DLL必须是导出的java中定义的本地方法。

3>:实例  

java本地代码 调用C/C++函数

package helloJNI;
public class helloJni {
	public native void helloJNI(String name);//java jvm 看到native声明时说明该函数来自其他语言
	public static void main(String[] args) {
		System.loadLibrary("helloJni");// VS生成的 动态库文件 helloJni.DLL 
		helloJni ldJni = new helloJni();
		ldJni.helloJNI("test Java JNI");
	}
}

4>: java端

创建类, 定义本地方法。
通过javah命令编译生成头文件。//给C++ 项目使用
	set JAVA_HOME="D:\Java\jdk1.8.0_111"
	set path=%JAVA_HOME%\bin;%path%
	set classpath=.;%classpath%;%JAVA_HOME%\lib
	javah helloJNI.helloTestJni //(javah 包名.文件名)

5>:C++端

vs2015中创建DLL项目
引入javah编译生成的头文件
添加项目头文件引用目录
	   D:\Java\jdk1.8.0_111\include
	   D:\Java\jdk1.8.0_111\include\win32
     在.cpp文件中实现函数主体 
把编译后的DLL文件拷贝到java项目根目录下 编译要注意32和64平台区别
	 System.loadLibrary("helloJni"); //helloJni.DLL

6>java 到 jni数据类型转换 传入参数 与接受返回值

 

    定义带有接口参数与返回值的本地方法

public native String echo(String content, boolean flag);
public native int calculateSqr(int x, int y);
public native float calculate(float a, float b);
public native double calculate(double a, double b);

   通过javah编译生成头文件

JNIEXPORT jstring JNICALL Java_com_gloomyfish_jni_echo_EchoJNIDemo_echo
  (JNIEnv * env, jobject obj, jstring param1, jboolean param2){  //读取参数
        const char* content = env->GetStringUTFChars(param1, 0);//
        Jsize size = env->GetStringUTFLength(param1);
	printf("size of %s: %d\n", content, size);
	env->ReleaseStringUTFChars(param1, content);
	
        //创建新字符串并返回
	const char* result = "this is call from JNI C++ side";
	jstring param3 = env->NewStringUTF(result);
	return param3;
  }

JNIEXPORT jint JNICALL Java_com_gloomyfish_jni_echo_EchoJNIDemo_calculateSqr
  (JNIEnv * env, jobject obj, jint a, jint b){
	int x = a;
	int y = b;
	printf("x = %d y = %d \n", x, y);
	int sum = sqrt(x*x + y*y);
	return sum;
  }

JNIEXPORT jfloat JNICALL Java_com_gloomyfish_jni_echo_EchoJNIDemo_calculate__FF
  (JNIEnv *, jobject, jfloat, jfloat);

JNIEXPORT jdouble JNICALL Java_com_gloomyfish_jni_echo_EchoJNIDemo_calculate__DD
  (JNIEnv *, jobject, jdouble, jdouble);

7>传递数组与返回数组

public native byte[] process(byte[] data, int width, int height);
public native int[] process(int[] pixels, int width, int height);
   
JNIEXPORT jbyteArray JNICALL Java_com_gloomyfish_jin_arraydemo_ArrayJNIDemo_process___3BII
  (JNIEnv * env, jobject obj, jbyteArray pixels, jint w, jint h){
	int width = w;
	int height = h;
	printf("w = %d h = %d\n", width, height);
	jbyte* input = env->GetByteArrayElements()
	int index = 0;
	for(int row = 0; row < height; row++)
		for(int col = 0; col < width; col++){
			int value = (int)(input[index]&0xff);
			jbyte v = (jbyte)(255 - value);
			env->SetByteArrayRegion(pixels, index, 1, &v);
			index++;
		}
	
	return pixels;
  }

JNIEXPORT jintArray JNICALL Java_com_gloomyfish_jin_arraydemo_ArrayJNIDemo_process___3III
  (JNIEnv *, jobject, jintArray, jint, jint){
  
  }

8>: 在C++中访问java类成员变量  

  用途: 1.用jni获取java中类成员变量 在C++中进行修改后置回java中 增强数据操作保密性.
           2.某些操作必须用C++函数,如操作硬件,获取数值后置回到java中,拓宽java应用边界。
  相关方法:
  JNI相关API
        getObjectClass
getFieldID
getXXXField(xxx -- 表示类型)
  
  public class TestAccessInstanceVarDemo {
  	private int number = 9;
	private String content = "i'm from Java";
	
	public native void changeVars();
	
	//.......
	}
  //----javah生成 函数
  JNIEXPORT void JNICALL Java_com_gloomyfish_jni_classvardemo_TestAccessInstanceVarDemo_changeVars
  (JNIEnv * env, jobject obj){
	
	jclass clazz = env->GetObjectClass(obj);//获取类
	jfieldID fieldID = env->GetFieldID(clazz, "number", "I");//获取字段 上面 private int number = 9; "I"代表字节码中字段类型
  
	jint number = env->GetIntField(obj, fieldID);//通过 obj对象 和 fieldID 真正获取对象字段值
	printf("number : %d", num);
	
	number = (int)pow(number, 2);
	
	env->SetIntField(obj, fieldID, number);//设置number值 回 java中
	
	//获取private String content 字段
	jfieldID sfID = env->GetFieldID(clazz, "content", "Ljava/lang/String:");
	jstring content = (jstring)env->GetObjectField(obj, sfID);
	const char* cc = env->GetStringUTFChars(content, 0);//转换
	printf("content: %s\n", cc);
	env->ReleaseStringUTFChars(content);//释放
  }

9>: 在C++中访问Java的相关方法:

  public class AccessMethodJNIDemo {
	public void callback() {
		System.out.println("i'm callback() method");
	}
	public void callback(String param) {
		System.out.println(param);
	}
	public double sum(double a, double b) {
		System.out.println("a = " + a + " b = " + b);
		double s = a+b;
		return s;
	}
	public native void showCallback();
	
	//......
  }
   //----javah生成 函数
  JNIEXPORT void JNICALL Java_com_gloomyfish_jni_methoddemo_AccessMethodJNIDemo_showCallback
  (JNIEnv *env, jobject obj){
  
	jclass clazz = env->GetObjectClass(obj);
	
	//获取java类中函数字段ID
	jmethodID callbackID = env->GetMethodID(clazz, "callback", "()V");//clazz 为类,  "callback"为函数名, "()V"为函数类型
	env->CallVoidMenthod(obj, callbackID);//调用 obj对象中 callbackID字段iD的函数 实现在C++中调用java类成员函数
	
	//callback with parameter
	jmethodID callback2ID = env->GetMethodID(clazz, "callback", "(Ljava/lang/String;)V")
	char param[] = "hello , I,m C++";
	jstring param1 = env->NewStringUTF(param);
	env->CallVoidMenthod(obj, callback2ID, param1);
	
	//sum
	jmethodID sumxy = env->GetMethodID(clazz, "sum", "(DD)D");
	jdouble result = env->CallDoubleMethod(obj, sumxy, 20.0, 30.0);
	printf("In C++ >> sum(20.0 30.0) = %f", result);
	return;
  }

  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值