JNI:C调用java输出hello,xxx

来源:互联网 发布:php与java的区别 编辑:程序博客网 时间:2024/06/08 09:50

首先在同一路径下创建两个文件夹:c和java,分别用来保存c代码和java代码。

1.编写java代码(Hello.java)

package com.test.base64;

public class Hello{

public String hello(String name){

return "hello,"+name;

}

}

2.编译java代码

javac Hello.java  -----> Hello.class 


3.编写C代码(test.c)

在C/C++中调用Java的方法一般分为五个步骤:初始化虚拟机、获取类、获取类的方法、创建类对象、调用方法和退出虚拟机。

#include <stdio.h>

#include "jni.h"

#include <string.h>

/** 
* 初始化jvm 
*/  
JNIEnv* create_vm() {  
        JavaVM* jvm;  
        JNIEnv* env;  
        JavaVMInitArgs args;  
        JavaVMOption options[1];  
        args.version = JNI_VERSION_1_6;  
        args.nOptions = 1;  
        options[0].optionString = "-Djava.class.path=../java";  
        args.options = options;  
        args.ignoreUnrecognized = JNI_FALSE;  
        JNI_CreateJavaVM(&jvm, &env, &args);  
        return env;  
}

/** 
* 根据全限定类名来获取类的定义 
*/  
jclass create_class(JNIEnv* env,char *className){  
        jclass cls = (*env)->FindClass(env,className);  
        if(cls == 0){  
                printf("class-[%s] find error\n",className);  
                return;  
        }  
        return cls;  
}

/** 
* 通过无参构造函数来获取对应类的实例 
*/  
jobject getInstance(JNIEnv* env, jclass obj_class)  
{   
        jmethodID construction_id = (*env)->GetMethodID(env,obj_class, "<init>", "()V");  
        jobject obj = (*env)->NewObject(env,obj_class, construction_id);  
        if(obj == 0){  
                printf("java class instance failed\n");  
                return;  
        }  
        return obj;   
}   

/** 
* 根据类\方法名\返回值\参数获取类中对应的方法定义 
*/  
jmethodID get_method(JNIEnv* env,jclass cls,char *methodName,char *key){  
        jmethodID mid = (*env)->GetMethodID(env,cls,methodName,key);  
        if(mid == 0){  
                printf("method-%s is not found\n",methodName);  
                return;  
        }  
        return mid;  

/** 
* 转换c中的字符串为java.lang.String,这个方法是从网上找到的,感谢原作者<a href="http://home.cnblogs.com/u/liangwind/">天末凉风</a> 
*/  
jstring stoJstring(JNIEnv* env, const char* pat)  
{  
        jclass strClass = (*env)->FindClass(env,"Ljava/lang/String;");  
        jmethodID ctorID = (*env)->GetMethodID(env,strClass, "<init>", "([BLjava/lang/String;)V");  
        jbyteArray bytes = (*env)->NewByteArray(env,strlen(pat));  
        (*env)->SetByteArrayRegion(env,bytes, 0, strlen(pat), (jbyte*)pat);  
        jstring encoding = (*env)->NewStringUTF(env,"utf-8");  
        return (jstring)(*env)->NewObject(env,strClass, ctorID, bytes, encoding);  
}  

void invoke(){  
        JNIEnv* env = create_vm(); //初始化java虚拟机  
        jclass cls = create_class(env,"com/test/base64/Hello");//根据类名找到对应的类  
        jobject obj = getInstance(env,cls);//然后根据类获取对应的实例  
        jmethodID hello = get_method(env,cls,"hello","(Ljava/lang/String;)Ljava/lang/String;");//根据类\方法名和签名获取到对应的方法  
        jstring name_str =  (*env)->CallObjectMethod(env,obj,hello,stoJstring(env,"xxx"));//传入参数调用方法  
        const char* pname = (*env)->GetStringUTFChars(env,name_str, NULL);//将返回的java字符串转换为c字符串  
        printf("the result is:%s\n",pname);//打印出调用的结果  
}

int main(int argc, char **argv) {  
        invoke();  
}  

4.编译C代码

gcc -o test test.c -L/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/amd64/server -ljvm   //根据自己的情况链接libjvm.so库

test.c ----> test  

5 执行

./test 

原创粉丝点击