Jni之在c++中调用java代码

来源:互联网 发布:网络电视没信号怎么调 编辑:程序博客网 时间:2024/06/06 00:27

第一步:完成java代码

public class JniMain {private static int staticIntField=300;static{System.loadLibrary("JniFunc");}public static native JniTest createObject();public static void  main(String []args){System.out.println("调用本地方法");JniTest jniObject=createObject();//利用本地方法生成java对象jniObject.callTest();}}
public class JniTest {private int intField;public JniTest(int num){this.intField=num;System.out.println("调用JNItest对象的构造方法:intField="+intField);}public int callByNative(int num){System.out.println("jniTest对象的callByNative调用="+num);return num;}public void callTest(){System.out.println("callTest被调用="+intField);}}

第二步:利用javah命令生成c++头文件

/* DO NOT EDIT THIS FILE - it is machine generated */#include "jni.h"/* Header for class com_jni_JniMain */#ifndef _Included_com_jni_JniMain#define _Included_com_jni_JniMain#ifdef __cplusplusextern "C" {#endif/* * Class:     com_jni_JniMain * Method:    createObject * Signature: ()Lcom/jni/JniTest; */JNIEXPORT jobject JNICALL Java_com_jni_JniMain_createObject  (JNIEnv *, jclass);//由于是static静态方法,所以传的参数为jclass类型#ifdef __cplusplus}#endif#endif


第三步:完成c++代码,要在vs中项目属性里的包含目录中添加jdk的相关c/c++文件的目录

#include "com_jni_JniMain.h"#include<stdio.h>JNIEXPORT jobject JNICALL Java_com_jni_JniMain_createObject(JNIEnv *env, jclass jclassParams){jclass targetClass;jmethodID mid;jobject newObject;jstring helloStr;jfieldID fid;jint staticIntField;jint result;//参数分别指的是包含静态成员的类,成员变量名,成员变量的签名(可以通过javap -s -p 类名命令来获取)printf("本地方法开始!\n");fid=env->GetStaticFieldID(jclassParams,"staticIntField","I");//根据类及成员的字段ID来获取成员变量的值staticIntField=env->GetStaticIntField(jclassParams,fid);printf("获取JniFuncMain类的staticIntField值=%d\n",staticIntField);//获取指定类名的jclass对象targetClass=env->FindClass("com/jni/JniTest");//包名+类名//查找指定的方法的methodID,根据jclass对象、方法名(构造函数的方法名为<init>)、方法签名mid=env->GetMethodID(targetClass,"<init>","(I)V");printf("生成JniTest对象\n");//利用构造函数创建对象、最后为构造函数的参数newObject=env->NewObject(targetClass,mid,100);mid=env->GetMethodID(targetClass,"callByNative","(I)I");result=env->CallIntMethod(newObject,mid,200);fid=env->GetFieldID(targetClass,"intField","I");//设定字段的值env->SetIntField(newObject,fid,result);return newObject;}

从代码来看:要调用静态方法或静态成员变量:首先利用JNIEnv对象来查找到相应的类的jclass类型->然后在获取方法或成员ID,这里利用变量签名和方法签名->然后在利用jclass对象调用方法或对数据进行操作

而使用非静态方法则需要多一个查找并调用构造函数的过程

可以使用javap反编译命令来获取成员或方法签名,实现要先编译java文件


第四步:利用vs的命令提示工具生成dll共享库,利用其cl命令



第五步:执行得到结果


如果是纯c++调用jni则需要自己加载jvm,其余大致相同,不过需多加在一个lib库,如下所示

#include<jni.h>int main(){JNIEnv *env;JavaVM *vm;JavaVMInitArgs vm_args;JavaVMOption options[1];jint res;jclass cls;jmethodID mid;jstring jstr;jclass stringClass;jobjectArray args;//设置java虚拟机选项options[0].optionString="-Djava.class.path=.";vm_args.version=0x00010008;//在jni.h文件中可找到该值vm_args.options=options;vm_args.nOptions=1;vm_args.ignoreUnrecognized=JNI_TRUE;//生成java虚拟机res=JNI_CreateJavaVM(&vm,(void**)&env,&vm_args);cls=env->FindClass("InvocationApiTest");mid=env->GetStaticMethodID(cls,"main","([Ljava/lang/String;)V");jstr=env->NewStringUTF("hello invocationApiTest!");stringClass=env->FindClass("java/lang/String");//获取String类jclass实例args=env->NewObjectArray(1,stringClass,jstr);//创建String数组env->CallStaticVoidMethod(cls,mid,args);//调用main方法vm->DestroyJavaVM();//关闭jvmreturn 0;}


0 0
原创粉丝点击