Перечисления в списке параметров подписи JNI GetMethodID

Итак, это крайний случай, который, кажется, не обнаруживается никаким поиском в 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;
}

Вы не создаете экземпляры значений перечисления. Это статические поля класса перечисления. См., например. stackoverflow.com/questions/51729992/…

Michael 28.06.2024 10:48

Конечно, я это понимаю, но как тогда передать значение перечисления через вызов метода?

Lee Sylvester 28.06.2024 11:25

Что здесь enumState? проект или целое число?

Botje 28.06.2024 11:26

Невозможно воспроизвести в моей системе. Этот конструктор просто есть... Можете ли вы проверить файл класса на AppState с помощью javap -s?

Botje 28.06.2024 11:51

«но как тогда передать значение перечисления через вызов метода?» Я показываю это в ответе, на который я дал ссылку (последняя строка с вызовом NewObject).

Michael 28.06.2024 11:59

Это Котлин, поэтому javap -s не подойдет

Lee Sylvester 28.06.2024 12:14

@Botje Я получаю значение из объекта Enum в C, так что это jobject.

Lee Sylvester 28.06.2024 12:22

Я сделал именно это в своей системе. Скомпилировал с помощью kotlinc и запустил javap -s myapp/AppState.class.

Botje 28.06.2024 12:24

Хорошо, я инженер C/C++, поэтому Kotlin для меня все еще новичок. Мне удалось вывести из javap. Добавил в основной пост для ясности.

Lee Sylvester 28.06.2024 12:52

Ладно, я немного дальше. 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. К основному вопросу добавлена ​​функция получения перечисления.

Lee Sylvester 28.06.2024 13:15
[ в подписи подразумевает массив Java. Удалите этого персонажа.
Michael 28.06.2024 14:08

И не забудьте проверить все ваши вызовы JNI на наличие ошибок и ожидающих исключений.

Andrew Henle 29.06.2024 23:29
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
12
52
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Ответом оказалась ошибочная [ в коде. Использование javap -s и копирование/вставка из вывода — самый безопасный способ избежать этой проблемы.

Другие вопросы по теме