Webrtc中Java层和C++层JNI对应规则和代码查找方法

1. WebRTC JNI接口文件生成

Webrtc 中,Java API是C++层的一层接口包装,但是没有像Android中那样,可以直接对应的找到Java层类
对应的C++层的JNI接口文件。

1. Webrtc中Java类中的注解

在Webrtc中,Java层使用注解的方式来标记需要进行JNI接口生成的头文件和函数选项:
用到的注解:

  1. @JNINamespace(“webrtc::jni”) 标记生成的头文件中的函数声明位于哪个命名空间,
    这个表示生成的函数形式为
namespace webrtc {
    namespace jni {
      ///函数...  
    }
}

  1. @NativeClassQualifiedName(“CPPClass::InnerClass”) 制定要调用的目标对象的方法,这个表示要调用的是CPPClass::InnerClass的本地方法(CPPClass指的是对应的包含生成的.h文件的.cpp/.cc文件中的类 CPPclass)

没有指定NativeClassQualifiedName的时候,调用的就是include 了生成的头文件的源文件的同名方法实现;

    @NativeClassQualifiedName("CPPClass::InnerClass")
    private native double nativeMethodOtherP0(long nativePtr);

对应调用c++层的

JNI_GENERATOR_EXPORT jdouble
    Java_org_chromium_example_jni_1generator_SampleForTests_nativeMethodOtherP0(JNIEnv*
    env, jobject jcaller,
    jlong nativePtr) {
    //指定调用用CPPClass::InnerClass中的方法
  CPPClass::InnerClass* native =
      reinterpret_cast<CPPClass::InnerClass*>(nativePtr);
  CHECK_NATIVE_PTR(env, jcaller, native, "MethodOtherP0", 0);
  //调用方法
  return native->MethodOtherP0(env, base::android::JavaParamRef<jobject>(env,
      jcaller));
}
  1. @CalledByNative(“InnerClass”) 指定该标记对象是由native向Java层调用的,参数告诉底层该方法属于哪一个类中的方法(底层需要获取Java层的包名路径来调用该方法)。 比如这个表示底层应该调用的是java层的InnerClass中的方法。

2. JNI头文件生成和代码跟踪方法

上面讲的Java层的注解只是一个标记,并不是用Java的注解处理器来进行处理的,而是使用Python脚本来解析和生成文件,类,函数声明和函数实现的。

  1. JNI接口的头文件生成是使用文件:
    src\base\android\jni_generator\jni_generator.py
    来进行解析和生成的。

  2. 生成的文件为 “java_name” + _jni.h
    比如Java文件为AudioTest, 那么如果有JNINamespace注解,那就会生成一个AudioTest_jni.h文件

  3. 调用跟踪方法:
    比如:

  • 1.java层:
@org.webrtc.JNINamespace("webrtc::jni") //首先有这个注解,命名空间为webrtc::jni
public class AudioTrack extends org.webrtc.MediaStreamTrack {
  public AudioTrack(long nativeTrack) {
    super(nativeTrack);
  }

 ...
  public void setVolume(double volume) {
    nativeSetVolume(super.nativeTrack, volume);
  }

  private static native void nativeSetVolume(long track, double volume); //找这个native方法
}
  • 2.生成的对应头文件为"AudioTrack_jni.h", 那么就找那个文件include了AudioTrack_jni.h:

这个只生成头文件,源文件需要自己实现,我们只需要找到对应的源文件就可以知道调用的对象是那个函数;

//src\sdk\android\src\jni\pc\audiotrack.cc
#include "api/mediastreaminterface.h"
#include "sdk/android/generated_peerconnection_jni/jni/AudioTrack_jni.h"

namespace webrtc {
namespace jni {

//调用的native方法就是这个
static void JNI_AudioTrack_SetVolume(JNIEnv*,
                                     const JavaParamRef<jclass>&,
                                     jlong j_p,
                                     jdouble volume) {
  rtc::scoped_refptr<AudioSourceInterface> source(
      reinterpret_cast<AudioTrackInterface*>(j_p)->GetSource());
  source->SetVolume(volume);
}

}  // namespace jni
}  // namespace webrtc

2. 生成规则

  1. 一般默认生成的头文件和Java的函数所在类的报名/类型/函数名拼接规则相匹配
  2. 在WebRTC中,也是同样适用,但是在没有生成的前提下,我们发现我们所调用的函数名字并不适应于上述规则,这个是因为在匹配生成的时候,也同时生成了一个简单的Native接口,作为JNI接口的转换,该转换接口就是我们在生成之前找到的源码中看到的函数接口,规则是:

JNI_ + "class_name" + "Method_name()" //注意,method匹配的方法去掉了native前缀的大驼峰形式;

比如:

package org.chromium.example.jni_generator;
@JNINamespace("base::android")
class SampleForTests {
   	private native void nativeSetNonPODDatatype(Rect rect);
}

会生成为

namespace base {
namespace android {
//转换的简单匹配接口,我们在生成之前看到的接口就是这个,原文件中会对这个接口进行实现;
static void JNI_SampleForTests_SetNonPODDatatype(JNIEnv* env, const
    base::android::JavaParamRef<jobject>& jcaller,
    const base::android::JavaParamRef<jobject>& rect);

//这个是生成的JNI规则匹配接口
JNI_GENERATOR_EXPORT void
    Java_org_chromium_example_jni_1generator_SampleForTests_nativeSetNonPODDatatype(JNIEnv*
    env, jobject jcaller,
    jobject rect) {
    //接口中默认调用了生成的转换的简单匹配接口
  return JNI_SampleForTests_SetNonPODDatatype(env,
      base::android::JavaParamRef<jobject>(env, jcaller),
      base::android::JavaParamRef<jobject>(env, rect));
}

}
}

3. 总结

代码跟踪流程可以总结如下:

  1. 比如Java类是AudioTest, 其中有一个native方法 nativeTest:
@JNINamespace("base::android")
public class AudioTest {
 public void nativeTest();
}
  1. 找include了 AudioTest_jni.h 的源文件;
  2. 找到之后, 就可找到调用的目标函数: JNI_AudioTest_Test();
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值