android - 无法解析相应的 JNI 函数 Java_com_mozilla_greetings_RustGreetings_greeting

标签 android rust java-native-interface

我正在尝试复制 this在 Android 应用程序中构建和使用 Rust 库的教程,我成功构建了库,并上传了生成的库 here

Android使用Java_<Package>_Class_function需要调用的函数主题是:

Java_com_mozilla_greetings_RustGreetings_greeting

我的安卓应用结构如下:

enter image description here

我的 JNI 包装器出现以下错误:

Cannot resolve corresponding JNI function Java_com_mozilla_greetings_RustGreetings_greeting

JNI 包装器是:

package com.mozilla.greetings;

public class RustGreetings {

    private static native String greeting(final String pattern);

    public String sayHello(String to) {
        return greeting(to);
    }
}

主类是:

package com.mozilla.greetings;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;

public class GreetingsActivity extends AppCompatActivity {

    static {
        System.loadLibrary("greetings");
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_greetings);

        RustGreetings g = new RustGreetings();
        String r = g.sayHello("world");
        ((TextView) findViewById(R.id.greetingField)).setText(r);
    }
}

最佳答案

我使用 JNA 解决了它,我认为它比 JNI 慢,我将在下面使用 JNA 编写我的解决方案,希望有人提供需要使用 JNI

进行修复

我的应用结构如下,使用kotlin:

  • 我将 libjnidispatch.so 添加到每个库构建文件夹中,这可以通过从 here 中提取所需的 android 体系结构来获得。 ,下载所需的jar,然后解压得到libjnidispatch.so
  • 我为 jna 创建了接口(interface)

JNA.kt

package com.mozilla.greetings

import com.sun.jna.Library

   interface JNA : Library {
      fun rust_greeting(pattern: String): String
   }
  1. 我为 jna 创建了包装器 RustGreetings.kt:

    package com.mozilla.greetings
    
    import com.sun.jna.Native
    
    class RustGreetings {
    
    fun sayHello(to: String): String =
            Native.loadLibrary<JNA>("greetings", JNA::class.java).rust_greeting(to)
    }
    
  2. 主要 Activity ,GreetingsActivity.kt:

    package com.mozilla.greetings
    
    import android.support.v7.app.AppCompatActivity
    import android.os.Bundle
    import kotlinx.android.synthetic.main.activity_greetings.*
    
    
    class GreetingsActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_greetings)
    
        val g = RustGreetings()
        val r = g.sayHello("Rust")
        greetingField.text = r
    }
    
    companion object {
        init {
            System.loadLibrary("greetings")
        }
    }
    }
    

注意: 为了避免使用 findViewById,我使用了 kotlin 扩展,如 here 所解释的那样并将以下内容添加到 build.gradle(模块):

apply plugin: 'kotlin-android-extensions'

更新

看起来这是一个 IDE 问题,与代码无关,应用程序已执行。 我用 Kotlin 重写了它,它也执行得很顺利,在我的 kotlin 代码下面:

GreetingsActivity.kt

package com.mozilla.greetings

import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import kotlinx.android.synthetic.main.activity_greetings.*

class GreetingsActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_greetings)

        val g = RustGreetings()
        val r = g.sayHello("My Rust")
        greetingField.text = r
    }

    companion object {

        init {
            System.loadLibrary("greetings")
        }
    }
}

RustGreetings.kt

package com.mozilla.greetings

class RustGreetings {

    private external fun greeting(pattern: String): String

    fun sayHello(to: String): String = greeting(to)
}

构建.gradle

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android-extensions'

apply plugin: 'kotlin-android'

apply plugin: 'kotlin-android-extensions'

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "com.mozilla.greetings"
        minSdkVersion 28
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}

activity_greetings.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".GreetingsActivity">

    <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Hello World!"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" android:id="@+id/greetingField"/>

</android.support.constraint.ConstraintLayout>

在结构和执行下面,apk 是 here :

enter image description here

关于android - 无法解析相应的 JNI 函数 Java_com_mozilla_greetings_RustGreetings_greeting,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53464954/

相关文章:

android - 如何用我自己的按钮类来固定按钮的宽度

android - 如何使用 aSmack 在 Android 设备上获取 Openfire 聊天记录?

generics - 为什么此生命周期不是 "expire"?

rust - 为什么这个特征 `impl` 被认为泄漏了私有(private)特征?

java - 从 Java 访问 iSeries 上的 RPG

java - 给定一个class文件,如何检测它是否使用JNI?

java - 如何在native中写/读直接的ByteBuffer?

android - Foursquare用户 checkin V2

android - 找不到Android Studio Gradle DSL方法: 'mavencentral()'

rust - 从消耗值中计算出生命周期以供引用