Что будет после именования $ и Android JNI? - PullRequest
0 голосов
/ 09 апреля 2020

Когда я пытаюсь вызвать функцию JNI из Android, я получаю сообщение об ошибке из-за неожиданного суффикса, который появляется в сигнатуре функции.

Класс Kotlin равен org.dicekeys.crypto.seeded.PublicKey и Я вызываю stati c метод constructFromJsonJNI, который должен вызывать метод JNI с именем Java_org_dicekeys_crypto_seeded_PublicKey_constructJNI. Вместо этого он ищет Java_org_dicekeys_crypto_seeded_PublicKey_constructJNI_00024seeded_1debug (модуль называется "seedded", а IML подразумевает, что Andrdoid Studio присвоило имя "seeded_debug". Я понятия не имею, откуда взялся 00024. Возможно, ха sh?)

Несоответствие приводит к этому исключению, которое является распространенным исключением, когда вы не загружаете модуль (он загружен), не используете имя, которое ожидает JNI (это соответствует проверке в последних инструментах), или когда вы забыли загрузить библиотеку (это работало всего за день или два за go до того, как что-то испортилось. - она ​​загружается):

java.lang.UnsatisfiedLinkError: No implementation found for long org.dicekeys.crypto.seeded.PublicKey.constructJNI$seeded_debug(java.lang.String) (tried Java_org_dicekeys_crypto_seeded_PublicKey_constructJNI_00024seeded_1debug and Java_org_dicekeys_crypto_seeded_PublicKey_constructJNI_00024seeded_1debug__Ljava_lang_String_2)

Библиотеки действительно компилируются, последний язык Kotlin инструменты сообщают о правильной связи между моими внешними функциями и моими реализациями JNI, и все это работало до тех пор, пока go.

Я уже пытался удалить все сборки, файлы .iml и т. д. c , и восстановление с нуля без удачи.

Соответствующие разделы Gradle:

android {

    ndkVersion '21.0.6113669'

    compileSdkVersion 29
    buildToolsVersion "29.0.2"

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
            signingConfig signingConfigs.release
            debuggable = false
        }
        debug {
            debuggable true
            initWith debug
            jniDebuggable false
            signingConfig signingConfigs.debug
        }
    }

...
    defaultConfig {
        minSdkVersion 19
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        consumerProguardFiles 'consumer-rules.pro'

        externalNativeBuild {
            cmake {
                cppFlags "-std=c++11"
            }
        }
    }
...
    externalNativeBuild {
        cmake {
            version "3.15.0+"
            path file('src/main/cpp/CMakeLists.txt')
        }
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }


    kotlinOptions {
        jvmTarget = JavaVersion.VERSION_1_8.toString()
    }
}
...
dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'androidx.core:core-ktx:1.2.0'
    testImplementation 'junit:junit:4.13'
    androidTestImplementation 'androidx.test.ext:junit:1.1.1'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'

    implementation 'com.google.zxing:core:3.4.0'
}

1 Ответ

2 голосов
/ 09 апреля 2020

Для тех, кто переживает потерянные часы, которые я сделал из-за сопоставления Kotlin сопутствующего объекта @ JvmStati c функций с C именами функций в JNI.

Я отметил свои функции JNI внутренними ( которая создает красивую пару internal external). По-видимому, добавление внутренних изменений в требуемую функцию JNI приводит к добавлению $, который становится 00024. Текущие инструменты Android Studio (3.6.2 от 19 марта 2020 г.) не учитывают это, генерируют неправильные имена функций или помечают проблема с именами.

Я исправил, сделав функции private external вместо internal external, так как мой вариант использования позволял это. Если бы мне нужно было internal, чтобы другие классы в моем модуле могли получить к нему доступ, я бы, скорее всего, просто добавил функцию-обертку рядом с приватной внешней, которая могла бы предоставлять приватную функцию другому коду в моем модуле.

...