Мы используем SWIG для создания JNI API между API C++ и 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
может быть пустым, и методы get & set могут получать/возвращать пустую String
(автоматически сгенерированный код JNI ведет себя так, как ожидается в этом случае, и позволяет использовать jstring
или null
).
У меня вопрос: может ли SWIG добавлять аннотации, такие как @Nullable
или @NonNull
для соответствия API C++ (если нам нужно предоставить "подсказки" для 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.
Дайте вашему примеру класс 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;
%}
%typemap
с@Nullable
для каждого типа, который я использую (и если я хочу добавить@NonNull
это будет еще большей болью ). 2) Код не компилируется, так как отсутствует импорт дляandroid.support.annotation
.