Итак, это крайний случай, который, кажется, не обнаруживается никаким поиском в Google.
У меня есть перечисление в Котлине;
package myapp
public enum State {
STATE_SUCCEEDED,
STATE_FROZEN,
STATE_WAITING,
STATE_IN_PROGRESS,
STATE_FAILED
}
Затем у меня есть объект, который содержит это перечисление как значение переменной-члена.
package myapp
class AppState (
val state: State
)
Затем в C я хочу создать экземпляр AppState
jclass cls = (*env)->FindClass(env, AppState_ClassPath);
if (cls == NULL) {
__android_log_print(ANDROID_LOG_INFO, "DEBUG", "AppState class is null");
}
jmethodID mid = (*env)->GetMethodID(env, cls, "<init>", "(Lmyapp/State;)V");
return (*env)->NewObject(
env,
cls,
mid,
enumState
);
Теперь, когда код C вызывается из Котлина, я получаю ошибку
JNI DETECTED ERROR IN APPLICATION: JNI NewStringUTF called with pending exception java.lang.NoSuchMethodError: no non-static method "Lmyapp/AppState;.<init>(Lmyapp/State;)V"
Я понимаю, почему получаю эту ошибку, поскольку у Enums нет открытого конструктора, но я не уверен в обходном пути. Как это перечисление следует добавить в подпись?
Большое спасибо!
Обновлено: (выход из javap)
public final class myapp.AppState {
public myapp.AppState(myapp.State);
descriptor: (Lmyapp/State;)V
public final myapp.State getState();
descriptor: ()Lmyapp/State;
}
Обновлено еще раз: (функция преобразования перечисления)
jobject
getState(JNIEnv* env, enum State state) {
char path[64];
char* stateName;
switch(state) {
case STATE_SUCCEEDED:
stateName = "STATE_SUCCEEDED";
break;
case STATE_FROZEN:
stateName = "STATE_FROZEN";
break;
case STATE_WAITING:
stateName = "STATE_WAITING";
break;
case STATE_IN_PROGRESS:
stateName = "STATE_IN_PROGRESS";
break;
default:
stateName = "STATE_FAILED";
};
snprintf(path, sizeof(path) - 1,"[L%s;", State_ClassPath);
jclass cls = (*env)->FindClass(env, State_ClassPath);
jfieldID fid = (*env)->GetStaticFieldID(env, cls , stateName, path);
jobject stateObj = (*env)->GetStaticObjectField(env, cls, fid);
return stateObj;
}
Конечно, я это понимаю, но как тогда передать значение перечисления через вызов метода?
Что здесь enumState? проект или целое число?
Невозможно воспроизвести в моей системе. Этот конструктор просто есть... Можете ли вы проверить файл класса на AppState с помощью javap -s?
«но как тогда передать значение перечисления через вызов метода?» Я показываю это в ответе, на который я дал ссылку (последняя строка с вызовом NewObject).
Это Котлин, поэтому javap -s не подойдет
@Botje Я получаю значение из объекта Enum в C, так что это jobject.
Я сделал именно это в своей системе. Скомпилировал с помощью kotlinc и запустил javap -s myapp/AppState.class.
Хорошо, я инженер C/C++, поэтому Kotlin для меня все еще новичок. Мне удалось вывести из javap. Добавил в основной пост для ясности.
Ладно, я немного дальше. GetMethodID больше не вызывает ошибок, но при передаче состояния я получаю JNI DETECTED ERROR IN APPLICATION: JNI GetStaticObjectField called with pending exception java.lang.NoSuchFieldError: no "[Lmyapp/State;" field "STATE_IN_PROGRESS" in class "Lmyapp/State;" or its superclasses. К основному вопросу добавлена функция получения перечисления.
[ в подписи подразумевает массив Java. Удалите этого персонажа.
И не забудьте проверить все ваши вызовы JNI на наличие ошибок и ожидающих исключений.





Ответом оказалась ошибочная [ в коде. Использование javap -s и копирование/вставка из вывода — самый безопасный способ избежать этой проблемы.
Вы не создаете экземпляры значений перечисления. Это статические поля класса перечисления. См., например. stackoverflow.com/questions/51729992/…