Как добавить аннотации Java в JNI SWIG API? - PullRequest
1 голос
/ 25 апреля 2019

Мы используем SWIG для создания JNI API между C ++ API и Java в Android.

Например, предположим, что наш класс C ++ имеет вид:

class TestAnnotation {

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

private:
    char* message = nullptr;
};

SWIG создает этот автоматически сгенерированный класс Java:

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 могут принимать / возвращать NULL String (автоматически сгенерированный код JNI ведет себя так, как ожидается в этом случае, и позволяет использовать jstring или null).

Мой вопрос таков: способен ли SWIG добавлять аннотации наподобие @Nullable или @NonNull для соответствия C ++ API (если нам нужно предоставить "подсказки" для SWIG, это такжеработа).

Таким образом, в этом случае желаемый автоматически сгенерированный 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.

1 Ответ

1 голос
/ 26 апреля 2019

Дайте пример вашего класса C ++ в файле с именем test.h, вы можете сгенерировать оболочку 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;
%}
...