JNI:C調用java輸出hello,xxx

首先在同一路徑下創建兩個文件夾: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 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章