上一篇文章讲了c/c++与java之间如何传递参数,但是有些时候c层会传递过来一个实体类,最开始,我是把实体类里面的参数都拆出来,一个一个传递到java层去,这样实现上没任何问题,但是太过繁琐。就去找了直接传递实体类的方法。
传递基础类型的方法,这里就不再赘述,有需要的可以看我上一篇博客。这里就在它的基础上进行讲解。
1.GetMethodID
jniobj->JNI_recLeft = env->GetMethodID(jniobj->g_class, "recLeft",
"(ILcom/arcvideo/rtcmessage/model/RtcClientModel;)V");
在这里调用了java里面一个recLeft方法,然后recLeft方法传递了一个RtcClientModel的实体类,这里就需要把它的类型名称写完整,从包名com开始,最前面要加上“L”跟“Ljava/langString”比较类似。
2.生成jobject
static jobject getRtcClientModel(RTCCLIENTMODEL* client){
MVLOG("RtcMessageJNI getRtcClientModel is start");
jclass jcInfo = jniobj->g_class_rtc_client_model;
jfieldID jfcid = jniobj->g_ThreadEnv->GetFieldID(jcInfo, "cid", "Ljava/lang/String;");//这里通过GetFieldID获取到实体类中的成员变量
jfieldID jfextInfo = jniobj->g_ThreadEnv->GetFieldID(jcInfo, "extInfo", "Ljava/lang/String;");
jobject joInfo = jniobj->g_ThreadEnv->AllocObject(jcInfo);//这里生成一个jobject对象
if(client == MNull){
MVLOG("RtcMessageJNI getRtcClientModel client is null");
return joInfo;
}
jstring jscid = jniobj->g_ThreadEnv->NewStringUTF(client->cid);//这里获取到jstring类型的参数值
jstring jsextInfo = jniobj->g_ThreadEnv->NewStringUTF(client->extInfo);
jniobj->g_ThreadEnv->SetObjectField(joInfo, jfcid, jscid);//这里把参数值设置到对应jobject的对应成员变量中去
jniobj->g_ThreadEnv->SetObjectField(joInfo, jfextInfo, jsextInfo);
MVLOG("RtcMessageJNI getRtcClientModel is success");
return joInfo;
}
这里首先要获取到jclass对象
jclass jsRtcClientModel = env->FindClass(DL_CLASS_NAME_RTC_CLIENT_MODEL);
jniobj->g_class_rtc_client_model = (jclass)env->NewGlobalRef(jsRtcClientModel);//这里把它设置为全局变量
其他的在代码注释中有讲到,这样就获取到了jobject。最后把获取到的jobject对象传递到CallVoidMethod()方法中去,这样就传递到了java层去了。
3.java层
package com.arcvideo.rtcmessage.model;
import java.io.Serializable;
public class RtcClientModel implements Serializable {
public String cid;
public String extInfo;
public ConnectInfo connectInfo;
public String getCid() {
return cid;
}
public void setCid(String cid) {
this.cid = cid;
}
public String getExtInfo() {
return extInfo;
}
public void setExtInfo(String extInfo) {
this.extInfo = extInfo;
}
public ConnectInfo getConnectInfo() {
return connectInfo;
}
public void setConnectInfo(ConnectInfo connectInfo) {
this.connectInfo = connectInfo;
}
}
首先定义好,需要调用的实体类。
public void recLeft(int sessionId, RtcClientModel client) {}
定义好要被c层调用的java方法,里面写好,刚才定义的java实体类。这样就大功告成了。
这里有个注意点,就是,获取jclass最好是在主线程中获取到,然后通过设置为全局变量,再来使用,否则有可能发生class not find的异常。因为两个线程里面,所用到的classloader可能不是同一个(加载基础类型是不会有问题的)。