如何向 JNI SWIG API 添加 Java 注释?

How to add Java annotations to JNI SWIG API?

我们正在使用 SWIG 在 C++ API 到 Android 中的 Java 之间创建 JNI API。

例如,假设我们的 C++ class 是:

class TestAnnotation {

public:
    void setMessage(char * message);
    char * getMessage();

private:
    char* message = nullptr;
};

SWIG 生成这个自动生成的 Java class:

public class TestAnnotation {
  ...

  public void setMessage(String message) {
    myJNI.TestAnnotation_setMessage(swigCPtr, this, message);
  }

  public String getMessage() {
    return myJNI.TestAnnotation_getMessage(swigCPtr, this);
  }
}

如您所见,message 可以为 null,并且 get 和 set 方法有可能 receive/return 为 null String(JNI 自动生成的代码的行为符合预期在这种情况下,允许使用 jstringnull).

我的问题是:SWIG 是否能够添加像 @Nullable@NonNull 这样的注释来匹配 C++ API(如果我们需要向 SWIG 提供 "hints",这也可以。

所以在这种情况下,所需的自动生成 Java API 将是:

public class TestAnnotation {
  ...

  public void setMessage(@Nullable String message) {
    myJNI.TestAnnotation_setMessage(swigCPtr, this, message);
  }

  @Nullable
  public String getMessage() {
    return myJNI.TestAnnotation_getMessage(swigCPtr, this);
  }
}

这很重要,因为我们将此 Java API 与 Kotlin 一起使用,并且缺少注释使得使用 Kotlin 智能功能变得更加困难。

在一个名为 test.h 的文件中给出你的示例 C++ class 你可以使用以下语法生成一个带有你想要的注释的 Java 包装器:

%module test

%javamethodmodifiers TestAnnotation::getMessage() %{
  @Nullable
  public%};

%typemap(jstype) char *message "@Nullable String";

%include "test.h"

鉴于命名侧重于其他用例,这有点违反直觉,但仍然是完全明智的用法。

您当然可以通过不命名其中的参数来使输入的类型映射不那么具体(例如 %typame(jstype) char * "...")。

并且您需要使用另一个类型映射来设置导入:

%typemap(javaimports) TestAnnotation %{
import android.support.annotation;
%}

可以通过以下方式使其更通用:

%typemap(javaimports) SWIGTYPE %{
import android.support.annotation;
%}