JNI用C构建复杂对象并返回
JAVA类
- Account.java
- Person.java
- PersonManager.java
- PersonTest.java
C文件
- PersonManager.cpp
- jni_PersonManager.h
- jni.h
- jni_md.h
PS:jni.h和jni_md.h在jdk的include文件下
文件关系以及实现目标
- Account为普通的java类
- Person中有一个属性为Account(对象内嵌套对象)
- 目的:使用jni构建Person以及Account对象,然后调用set方法把Account赋给Person并返回
- Person内含有Account属性,通过调用C来构建Person对象并返回接收
遇到的问题
- 直接用给参数赋值的方法给对象参数赋值不成功,需要添加set方法并通过C调用set方法
2. 在C中获取set方法时提示找不到该方法,当方法参数为自定义对象时不能用"(jni/Account;)V"这个方法签名,需要使用"(Ljava/lang/Object;)V"然后在java中定义形参类型为Object,然后在赋值时强转为对应所需要的类型 - **
查看方法签名很重要
使用 javap -s Person.class命令解析出该类中方法的方法签名 然后把签名复制到c中
**
4. 把java jni类编译为头文件时,如果该文件内引用了其他类,需要用 javac *java -h jni
命令全部编译,不然会报找不到类的错误
详细代码实现
Account.java
package jni;
public class Account {
public int usrname;
public String password;
}
Person.java
package jni;
public class Person {
public String name;
public int age;
public Account account;
public Account getAccount() {
return account;
}
public void setAccount(Account account) {
this.account = account;
}
}
PersonManager.java
package jni;
public class PersonManager {
static {
System.load("C:\\Users\\User\\source\\repos\\Dll5\\x64\\Debug\\Dll5.dll");
}
public native static String test();
public native static Person getPerson();
}
PersonTest.java
package jni;
public class PersonTest {
public static void main(String[] args) {
System.out.println(PersonManager.test());
Person p= PersonManager.getPerson();
System.out.println("p.name="+p.name);
System.out.println("p.age="+p.age);
if(p.account!=null) {
System.out.println("p.account.usrname="+p.account.usrname);
System.out.println("p.account.password="+p.account.password);
}
}
}
jni_PersonManager.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include "jni.h"
/* Header for class jni_PersonManager */
#ifndef _Included_jni_PersonManager
#define _Included_jni_PersonManager
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: jni_PersonManager
* Method: test
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_jni_PersonManager_test
(JNIEnv *, jclass);
/*
* Class: jni_PersonManager
* Method: getPerson
* Signature: ()Ljni/Person;
*/
JNIEXPORT jobject JNICALL Java_jni_PersonManager_getPerson
(JNIEnv *, jclass);
#ifdef __cplusplus
}
#endif
#endif
PersonManager.cpp
/* DO NOT EDIT THIS FILE - it is machine generated */
#include "pch.h"
#include "jni.h"
#include "jni_PersonManager.h"
/*
* Class: jni_PersonManager
* Method: test
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_jni_PersonManager_test(JNIEnv *env, jclass cls) {
return env->NewStringUTF("Hello");
}
/*
* Class: jni_PersonManager
* Method: getPerson1
* Signature: ()Ljni/Person;
*/
JNIEXPORT jobject JNICALL Java_jni_PersonManager_getPerson(JNIEnv *env, jclass cls) {
/*
* account类的信息获取
*/
jclass m_cls_a = env->FindClass("jni/Account");
jmethodID m_mid_a = env->GetMethodID(m_cls_a, "<init>", "()V");
/*
* account类指定变量名和类型
*/
jfieldID m_fid_a_1 = env->GetFieldID(m_cls_a, "usrname", "I");
jfieldID m_fid_a_2 = env->GetFieldID(m_cls_a, "password", "Ljava/lang/String;");
/*
* account类创建对象
*/
jobject m_obj_a = env->NewObject(m_cls_a, m_mid_a);
/*
* account类对象变量赋值
*/
env->SetIntField(m_obj_a, m_fid_a_1, 123456);
env->SetObjectField(m_obj_a, m_fid_a_2, env->NewStringUTF("pwd1"));
/*
* person类的信息获取
*/
jclass m_cls_p = env->FindClass("jni/Person");
jmethodID m_mid_p = env->GetMethodID(m_cls_p, "<init>", "()V");
/*
* person类指定变量名和类型
*/
jfieldID m_fid_p_1 = env->GetFieldID(m_cls_p, "name", "Ljava/lang/String;");
jfieldID m_fid_p_2 = env->GetFieldID(m_cls_p, "age", "I");
/*
* person类获取setAccount方法id
*/
jmethodID setAccountId = env->GetMethodID(m_cls_p, "setAccount","(Ljni/Account;)V");
/*
* person类创建对象
*/
jobject m_obj_p = env->NewObject(m_cls_p, m_mid_p);
/*
* person类对象变量赋值
*/
env->SetObjectField(m_obj_p, m_fid_p_1, env->NewStringUTF("xiaoming"));
env->SetIntField(m_obj_p, m_fid_p_2, 26);
/*
* 调用person的setAccount方法
*/
//int result = 50;
//if (setAccountId!=0) {
// result= env->CallIntMethod(m_obj_p,setAccountId);
//}
if (setAccountId != 0) {
env->CallVoidMethod(m_obj_p, setAccountId,m_obj_a);
}
return m_obj_p;
}
java传String到c++
jstring sIp;(传过来的参数)
const char *str;
str=env->GetStringUTFChars(sIp,false)