分享

寻找C调用Java接口可行性时写的一个测试小例子。

 wusiqi111 2017-02-16
寻找C调用Java接口可行性时写的一个测试小例子。

其输出为
E:\xx>jni.exe
main start
World
Result : Hello
LENGTH: 3
XXXXXXXXXX: 3
PResult : a
PResult : b
PResult : c
Zirconi
19


注:
其中C语言需要使用类似(*env)->XXXX(env, A,B…)之类的写法

C++则是env->(A,B…)的写法

其中编译参数在Win32下为:
gcc -Wall jnis.c -o jni.exe  -I "C:\\Program Files\\Java\\jdk1.7.0_45\\include" -I "C:\\Program Files\\Java\\jdk1.7.0_45\\include\\win32" -L "C:\\Program Files\\Java\\jdk1.7.0_45\\lib" -ljvm -std=c99

需要使用-I加入jdk下的include和include下的平台相关文件夹作为头文件包含目录
-L加入ljvm连接指令所需要的jvm链接库的位置

在运行时需要确保PATH下有C:\Program Files\Java\jre7\bin\client,其中包含了jvm所需要的运行时库。
标签: <无>

代码片段(3)[全屏查看所有代码]

1. [代码][C/C++]代码     

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#include <stdio.h>
#include <jni.h>
#include <string.h>
 
/*创建Java Virtual Machine, 其中唯一一个Option的值为jar包所在位置。其中路径分隔符在Win32下为“;”, Linux下为“:”*/
JNIEnv* create_vm(JavaVM ** jvm) {
    JNIEnv *env;
    JavaVMInitArgs vm_args;
    JavaVMOption options;
    options.optionString = "-Djava.class.path=.;E:\\xx\\DemoDemo.jar";
    vm_args.version = JNI_VERSION_1_6;
    vm_args.nOptions = 1;
    vm_args.options = &options;
    vm_args.ignoreUnrecognized = 0;
     
    int ret = JNI_CreateJavaVM(jvm, (void**)&env, &vm_args);
    if(ret < 0)
        printf("\nUnable to Launch JVM\n");    
    return env;
}
 
int main(int argc, char* argv[])
{
    printf("main start\n");
    JNIEnv *env;
    JavaVM * jvm;
    env = create_vm(&jvm);
    if (env == NULL)
    {
        printf("JVM NULL\n");
        return 1;
    }  
     
    //预先准备DemoDemo类的引用,以及Demo对象的引用
    jclass jcHBaseAbstractLayer = NULL;
jclass jcEntity = NULL;
    jobject jobDemo = NULL;
    jobject jobEntity = NULL;
//声明所需方法的引用
//其中jmiHBaseAbstractLayerCons为类的默认构造函数
//jmiDemo为Demo函数,jmiListGet为getString函数jmiListSize为getSize函数
    //jmethodID jmiDemoCons = NULL;
    jmethodID jmiHBaseAbstractLayerCons = NULL;
    jmethodID jmiDemo = NULL;
    jmethodID jmiListGet = NULL;
    jmethodID jmiListSize = NULL;
jmethodID jmiDisplayEntity = NULL;
    //1. 寻找类,FindClass   com/demo/DemoDemo, 包.类 分隔符用“/”
    jcHBaseAbstractLayer = (*env)->FindClass(env, "com/demo/DemoDemo");
jcEntity = (*env)->FindClass(env, "com/demo/Entity");
 
    if(jcHBaseAbstractLayer != NULL || jcEntity == NULL)
    {
        /*2. 找到所需要的方法,参数是静态方法则使用函数GetStaticMethodID获取ID*/
        jmiDemo = (*env)->GetMethodID(env, jcHBaseAbstractLayer, "Demo", "()Ljava/lang/String;");
        jmiListGet = (*env)->GetMethodID(env, jcHBaseAbstractLayer, "getString","(I)Ljava/lang/String;");
        jmiListSize = (*env)->GetMethodID(env, jcHBaseAbstractLayer, "getSize", "()I");
        jmiDisplayEntity = (*env)->GetMethodID(env, jcHBaseAbstractLayer, "displayEntity", "(Lcom/demo/Entity;)V");
 
        if(jmiDemo == NULL)
            printf("jmiDemo\n");
        if(jmiListSize == NULL)
            printf("jmiListSize\n");
        if(jmiListGet == NULL)
            printf("jmiListGet\n");    
        if(jmiDisplayEntity == NULL)
            printf("jmiDisplayEntity\n");  
 
        //3. 生成对象,此处有两种方法生成对象,第二种可以指定构造函数
        //jobDemo = (*env)->AllocObject(env, jcHBaseAbstractLayer);
        jmiHBaseAbstractLayerCons = (*env)->GetMethodID(env, jcHBaseAbstractLayer, "<init>", "()V");
        jobDemo = (*env)->NewObject(env, jcHBaseAbstractLayer, jmiHBaseAbstractLayerCons); 
        if(jobDemo == NULL)
            printf("jobDEMOERROR\n");
             
        /*4 .调用对应方法,若是静态方法可直接调用而不需生成对象,使用CallStaticObjectMethod函数调用。参数依次是 jvm环境,对象引用,方法引用,即调用某jvm下的某object的某方法。起返回值基本是jint,jstring或者jobject之类。其中jstring需要调用函数来转换成C风格字符串,最后还需释放。*/
 
        jstring result = (jstring)(*env)->CallObjectMethod(env, jobDemo, jmiDemo);
        const char* str = (*env)->GetStringUTFChars(env, result, 0);
        printf("Result : %s\n", str);
        (*env)->ReleaseStringUTFChars(env, result, 0);
 
        jint x = (jint)(*env)->CallObjectMethod(env, jobDemo, jmiListSize);
        printf("LENGTH: %d\n", (int)x);
 
//直接获取对象属性,似乎不受Java访问保护的限制。同时类似的有SetObjectField函数来设置对象属性。
        jint c = (jint)(*env)->GetIntField(env, jobDemo, (*env)->GetFieldID(env, jcHBaseAbstractLayer, "size", "I"));
        printf("XXXXXXXXXX: %d\n", (int)c);
        for(int p = 0; p < x; ++p)
        {
            jstring res = (jstring)(*env)->CallObjectMethod(env, jobDemo, jmiListGet, p);
            const char* str1 = (*env)->GetStringUTFChars(env, res, 0);
            printf("PResult : %s\n", str1);
            (*env)->ReleaseStringUTFChars(env, res, 0);     
        }
 
        //SetObjectField   测试新建一个对象并设置属性并当做参数传入所需的方法,并调用该方法       
        jobEntity = (*env)->AllocObject(env, jcEntity);
        (*env)->SetObjectField(env, jobEntity, (*env)->GetFieldID(env, jcEntity, "name", "Ljava/lang/String;"), (*env)->NewStringUTF(env, "Zirconi"));
        (*env)->SetIntField(env, jobEntity, (*env)->GetFieldID(env, jcEntity, "age", "I"), (jint)19);
 
        (*env)->CallObjectMethod(env, jobDemo, jmiDisplayEntity, jobEntity);
    }
    else
    {
        printf("FINDERROR\n");
        (*jvm)->DestroyJavaVM(jvm);
    }
    (*jvm)->DestroyJavaVM(jvm);
    return 0;
}

2. [代码]DemoDemo.java     跳至 [1] [2] [3] [全屏预览]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package com.demo;
 
import java.util.ArrayList;
import java.util.List;
 
public class DemoDemo {
    List<String> l;
    int size;
//默认构造函数,负责初始化一个字符串链表和它的长度这两个属性
    public DemoDemo() {
        l = new ArrayList<String>();
        l.add("a");
        l.add("b");
        l.add("c");
        this.size = l.size();
    }
//调用方法测试
    public String Demo() {
        System.out.println("World");
        return "Hello";
    }
    public int getSize() {
        return size;
    }
    public String getString(int i) {
        return l.get(i);
}   
public void displayEntity(Entity e)
    {
        System.out.println(e.getName());
        System.out.println(e.getAge());
    }
}

3. [代码]Entity.java     

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.demo;
public class Entity {
    String name;
    int age;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
}

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多