`

C/C++调用Java代码(属性和方法)

 
阅读更多

back>>

1. JNIEnv对象
     对于本地函数

JNIEXPORT void JNICALL Java_video1_TestNative_sayHello(JNIEnv * env, jobject obj){
    cout<<"Hello Native Test !"<<endl;
}

     JNIEnv类型代表Java环境。通过这个JNIEnv*指针,就可以对Java端的代码进行操作。如,创建Java类得对象,调用Java对象的方法,获取Java对象的属性等。

     JNIEnv的指针会被JNI传送到本地方法的实现函数中来对Java端的代码进行操作
     JNIEnv类中的函数:
     NewObject/NewString/New<TYPE>Array
     Get/Set<TYPE>Field
     Get/SetStatic<TYPE>Field
     Call<TYPE>Method/CallStatic<TYPE>Method

2. Java数据类型与C/C++数据类型的对应关系

Java类型		别名  		本地类型  		字节(bit)
boolean		jboolean	        unsigned char   	8, unsigned
byte      		jbyte		signed char    	8
char      		jchar		        unsigned short    16, unsigned
short		jshort		short    		16
int			jint		        long     		32
long      		jlong		        __int64    	64
float      		jfloat		float    		32
double  		jdouble		double   		64
void      		void		     				n/a  
Object		_jobject	        *jobject

 

3. 获取jclass

    为了能够在C/C++使用Java类,jni.h头文件中专门定义了jclass类型来表示Java中的Class类

    jclass的取得:
    JNIEnv类中有如下几个简单的函数可以取得jclass
    jclass FindClass(const char* clsName)
    jclass GetObjectClass(jobject obj)
    jclass GetSuperClass(jclass obj)
    FindClass 会在classpath系统环境变量下寻找类,需要传入完整的类名,注意包与包之间是用"/"而不是"."来分割
如:jclass cls_string= env->FindClass("java/lang/String");

 

4. 本地代码访问Java类中的属性与方法
    JNI在jni.h头文件中定义了jfieldID,jmethodID类表示Java端的属性和方法
    在访问或设置Java属性的时候,首先就要现在本地代码中取得代表Java属性的jfieldID,然后才能在本地代码中进行Java属性操作。
    同样,在需要调用Java端的方法时,也需要取得代表方法的jmethodID才能进行Java方法调用
    JNIEnv获取相应的fieldID和jmethodID的方法:
    GetFieldID/GetMethodID
    GetStaticFieldID/GetStaticMethodID
    GetMethodID也可以取得构造函数的jmethodID。创建Java对象时调用指定的构造函数。
    如:env->GetMethodID(data_Clazz,"<int>","()V")

 

5. sign签名

    对于 jfieldID GetFieldID(jclass clazz, const char *name, const char *sign)
    clazz代表该属性所在的类,name表示方法名称,sign是签名
    例如TestNative类中有两个重载方法:

package video1;
public class TestNative{
    public void methodTest(int i){
        System.out.println(i);
    }
    public void methodTest(double d){
        System.out.println(d);
    }
}
/*
在C/C++代码中调用其中一个methodTest方法:
首先取得要调用方法所在的类
jclass clazz_TestNative = env->FindClass("video1/TestNative");
//取得jmethodID
jmethodID id_func = env->GetMethodID(clazz_TestNative,"methodTest","");
sign用于指定取得的属性/方法的类型
如果sign指定为(I)V,则取回void methodTest(int)的methodID
如果sign指定为(D)V,则取回void methodTest(double)的methodID
*/

    签名sign

 

用来表示要取得的属性/方法的类型
类型            相应的签名
boolean        Z
byte              B
char              C
short             S
int                  I
long               L
float               F
double           D
void               V
object            L用/分隔包的完整类名:   Ljava/lang/String;
Array             [签名          [I      [Ljava/lang/Object;
Method         (参数1类型签名 参数2类型签名···)返回值类型签名

     使用javap命令来产生签名

     javap -s -p [full class Name]
     -s 表示输出签名信息
     -p 同-private,输出包括private访问权限的成员信息
     例子:

C:\E\java\workspaces\myeclipseblue\JNITest\bin>javap -s -private video1.TestNative
Compiled from "TestNative.java"
public class video1.TestNative extends java.lang.Object{
public java.lang.String name;
  Signature: Ljava/lang/String;
public video1.TestNative();
  Signature: ()V
public int signTest(int, java.util.Date, int[]);
  Signature: (ILjava/util/Date;[I)I
public native void sayHello();
  Signature: ()V
public static void main(java.lang.String[]);
  Signature: ([Ljava/lang/String;)V
} 

6. 本地方法调用Java方法的完整示例:

    - TestNative.java

package video1;

import java.util.Date;

public class TestNative {
	public String name="Test";
	public int number =100;
	public int signTest(int i,Date date,int[] arr){
		System.out.println("Sign Test");
		return 0;
	}
	//native关键字修饰的方法,其内容是C/C++编写的,java中不必为它编写具体的实现
	public native void sayHello();
	public static void main(String[] args) {
		System.loadLibrary("NativeCode");
		TestNative tn = new TestNative();
		tn.sayHello();
	}
}

    - C/C++代码

#include "video1_TestNative.h"
#include <iostream>
using namespace std;
JNIEXPORT void JNICALL Java_video1_TestNative_sayHello(JNIEnv * env, jobject obj){
	cout<<"Hello Native Test !"<<endl;
	//因为test不是静态函数,所以传进来的就是调用这个函数的对象
	//否则就传入一个jclass对象表示native()方法所在的类
	jclass native_clazz = env->GetObjectClass(obj);

	//得到jfieldID
	jfieldID fieldID_prop = env->GetFieldID(native_clazz,"name","Ljava/lang/String;");
	jfieldID fieldID_num = env->GetFieldID(native_clazz,"number","I");

	//得到jmethodID
	jmethodID methodID_func=env->GetMethodID(native_clazz,"signTest","(ILjava/util/Date;[I)I");
	//调用signTest方法
	env->CallIntMethod(obj,methodID_func,1L,NULL,NULL);

	//得到name属性
	jobject name = env->GetObjectField(obj,fieldID_name);
	//得到number属性
	jint number= env->GetIntField(obj,fieldID_num); 

	cout<<number<<endl;//100
	//修改number属性的值
	env->SetIntField(obj,fieldID_num,18880L);  
	number= env->GetIntField(obj,fieldID_num);  
	cout<<number<<endl;//18880
 }

    图解签名:

    - 编译source.cpp,执行TestNative.java类。

 

 

  • 大小: 12.1 KB
分享到:
评论

相关推荐

    JNI技术手册 c/c++调用java

    通过以上详细的步骤和技术要点,我们可以看到,无论是Java调用C/C++还是C/C++调用Java,都需要仔细地处理数据类型转换、异常处理以及性能优化等问题。掌握这些技术细节,对于开发高效稳定的跨语言应用程序至关重要。

    在C或C++中调用JAVA方法

    // 查找并调用Java类和方法... jvm-&gt;DestroyJavaVM(); return 0; } ``` 在实际应用中,可能会遇到诸如类型转换、内存管理、线程同步等问题。例如,C/C++和Java的数据类型不完全匹配,需要使用JNI的类型映射...

    ndk源码基于eclipse开发c/c++/java

    NDK是一组工具,用于在Android平台上编译C和C++代码,生成原生库,这些库可以直接被Android应用程序(APK)中的Java代码调用。NDK的主要用途包括:提升性能、使用已有的C/C++库、以及处理CPU密集型任务,如图形处理...

    Android 调用C++代码和C++代码调用源码.zip

    除了Java调用C++,C++也可以反向调用Java代码。这需要通过`env-&gt;FindClass()`, `env-&gt;GetMethodID()`等JNI API获取Java类和方法的ID,然后使用`env-&gt;Call*Method()`进行调用。这种方法适用于处理回调或者异步操作。 ...

    JNI中C代码调用使用java属性和方法

    本知识点详细介绍了如何在C/C++代码中调用Java中的属性和方法。 首先,JNI使用时需注意几个关键点,包括Java与本地方法的命名映射、JVM类型签名以及如何处理基本数据类型与对象类型。JNI方法的命名规则为“Java_包...

    NDK开发之C语言调用java方法和获取属性

    NDK提供了对JNI的支持,使得开发者可以在C/C++代码中调用Java类的方法和访问其属性。 1. 调用Java方法: - **创建JNI函数**: 在C/C++代码中,你需要定义一个JNI函数,这个函数将作为Java方法的本地实现。函数签名...

    Android开发,JNI和Java、Kotlin代码的互相调用以及CMakeLists的常用属性使用

    7. **C/C++调用Java或Kotlin**:在C/C++代码中,使用`JNIEnv*`指针和类的`jclass`引用来调用Java或Kotlin方法。例如,使用`CallVoidMethod()`来调用无返回值的方法。 在CMakeLists.txt中,还可以设置其他属性,如...

    计算机笔试题c/c++,java,百度,腾讯

    在计算机科学领域,尤其是C/C++、Java和C#这些编程语言,笔试题通常涵盖数据结构、算法、操作系统、计算机网络、数据库等多个方面。本资料包集合了来自互联网,包括百度、腾讯等知名企业的笔试题目,旨在帮助求职者...

    android中本地代码调用上层java的实例

    本实例主要探讨如何在Android的本地代码(C/C++)中调用上层Java代码,实现混合编程。这种方式常用于优化性能、利用已有的C库或者实现特定的硬件接口。 1. **JNI(Java Native Interface)**: JNI是Java平台标准...

    Android代码调用C++

    在Android平台上,有时候为了利用C或C++的高效性能或者重用已有的C/C++库,开发者需要在Java代码中调用C++代码。这种技术被称为JNI(Java Native Interface),它是Android系统提供的一种机制,允许Java代码和其他...

    android引入c/c++本地加密安全方式代码

    2. Java层调用:在Java代码中,先获取Keystore实例,然后加载或生成所需的密钥,最后调用JNI方法将密钥传递给C++。 ```java public class KeyManager { public native void setKeyStore(KeyStore keyStore); ...

    0854考研复试 综合面试速成(1):C/C++/Java常识 Akira37.pdf

    ### 0854考研复试综合面试速成(1):C/C++/Java常识 #### C语言与C++语言的基础对比 - **C语言**: - 面向过程,强调算法和数据结构。 - 程序设计侧重于如何通过一系列步骤处理输入并产生输出。 - 不具备类、...

    Android JNI 断点调试C++

    在Android开发中,JNI(Java Native Interface)是一个关键的组件,允许Java代码调用本地(C/C++)代码,反之亦然。这对于性能敏感的应用、底层库的集成以及利用现有C/C++库是非常有用的。本教程将聚焦于如何在...

    c/c++完整视频教程(四)——–数据库(MySQL,Oracle)

    根据提供的文件信息,我们可以推断出本视频教程的第四部分主要关注的是如何在C/C++环境中操作和使用数据库,特别是MySQL和Oracle这两种广泛使用的数据库管理系统。下面将详细展开这一主题的相关知识点。 ### C/C++...

    Ubuntu下使用Eclipse开发C/C++

    在项目中创建头文件(如`hello.h`)和源代码文件(如`hello.c`和`main.c`),编写相应的C代码。例如,在`hello.c`中定义一个函数`say_hello()`,在`main.c`中调用此函数。 ##### 2.2 编译与运行 在Eclipse中,通过...

    Java面向对象编程:从C++到Java—理解面向对象

    Java提供了一种名为“本地方法”(Native Method)的机制来实现C/C++代码的调用,但这一过程相对复杂。相比之下,在C/C++中,通过`extern "C"`声明就可以轻松地使用C语言的函数。尽管如此,为了减少移植工作的复杂性,...

    JNI编程(二) —— 让C++和Java相互调用(2)

    在函数中,我们可以使用JNI接口访问Java对象的属性和方法,如获取或设置字段值,调用其他Java方法等。 例如,C++代码可能如下: ```cpp #include "MyJavaClass.h" JNIEXPORT void JNICALL Java_MyJavaClass_...

    Android JNI native调用 java层demo TESTJNI.zip

    在Android开发中,JNI(Java Native Interface)是一个关键的组件,它允许Java代码与其他语言写的代码进行交互,尤其是C和C++。JNI在许多场景下非常有用,例如优化性能、利用硬件特性、接入第三方库等。本文将深入...

    NetBetBeans 编写Java调用DLL代码

    JNI允许Java代码与本地代码(如C++或C)交互,从而利用C/C++库,例如DLL(动态链接库)在Windows系统上。本教程将深入探讨如何使用NetBeans IDE来编写Java程序,以便调用DLL。 首先,理解JNI的基本概念至关重要。...

Global site tag (gtag.js) - Google Analytics