打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
寻找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所需要的运行时库。
标签: <无>
[全屏查看所有代码]
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;
}
}
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
通过JNI实现Java和C++的相互调用
JNI官方规范中文版——基本类型、字符串、数组
JNI攻略之十一――启动虚拟机调用java类
【转】Android JNI开发入门篇
JVMTI之HelloWorld - Trema & Colon - 博客大巴
JNI设计实践之路
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服