mozilla / rust-android-gradle

Apache License 2.0
1.03k stars 67 forks source link

Unsatisfied link error System.loadLibrary("leaf"); #104

Open tuncatunc opened 2 years ago

tuncatunc commented 2 years ago

Hi,

I'l trying to integrate leaf library https://github.com/eycorsican/leaf put the leaf library at the same level as rust under samples/app setup the sdk and ndk directories

static {
        try{
            System.loadLibrary("leaf");
            System.out.println("lead loaded successfully");
        }
        catch(UnsatisfiedLinkError unsatisfiedLinkError)
        {
            System.out.println(unsatisfiedLinkError);
        }
    }

Throws java.lang.UnsatisfiedLinkError: dlopen failed: library "libstd-c0ded10767d3dcb3.so" not found

Screen Shot 2022-06-02 at 9 05 57 PM

Any idea is really appreciated

ncalexan commented 2 years ago

What is your crate_type? I expect you need dylib here; see https://mozilla.github.io/firefox-browser-architecture/experiments/2017-09-21-rust-on-android.html.

Edit: yes, I don't see a crate_type in https://github.com/eycorsican/leaf/blob/master/leaf/Cargo.toml.

tuncatunc commented 2 years ago

I added create-type to all libraries and run gradlew installDebug it still fails w/ unsatisfiedLinkError.

[lib] 
crate-type = ["lib", "staticlib", "cdylib"]

May be the android emulator doesn't have the libstd...so

Screen Shot 2022-06-03 at 7 35 40 PM
ncalexan commented 2 years ago

My guess is that libstd-....so is Rust's std library. You need to arrange for a .so (dynamically loaded library) that includes all of that functionality. Usually, with a cdylib, all of the Rust functionality is included in the single .so. Try:

crate_type = ["cdylib"]

by itself. After that, you'll need to use the appropriate version of ldd for Android, which looks to be called ndk-depends, to understand why your all-inclusive .so is asking for other .so files.

Good luck!

tuncatunc commented 2 years ago

I've changed create types to cdylib and it worked! Thanks a lot.

--crate-type=cdylib, #[crate_type = "cdylib"] - A dynamic system library will be produced. This is used when compiling a dynamic library to be loaded from another language. This output type will create .so files on Linux, .dylib files on macOS, and *.dll files on Windows.

https://doc.rust-lang.org/reference/linkage.html

tuncatunc commented 2 years ago
➜  app git:(master) ✗ nm ../leaf/target/aarch64-linux-android/debug/libleafffi.so build/rustJniLibs/android/arm64-v8a/libleafffi.so| grep nishtahir
000000000059e47c T Java_com_nishtahir_androidrust_LeafJni_leaf_1run_1with_1options
000000000059e47c T Java_com_nishtahir_androidrust_LeafJni_leaf_1run_1with_1options

I've Java_com_nishtahir_androidrust_LeafJni_leaf_1run_1with_1options in libleafffi.so however when I try to call it from android it throws

No implementation found for int com.nishtahir.androidrust.LeafJni.Java_com_nishtahir_androidrust_LeafJni_leaf_1run_1with_1options(short, java.lang.String, boolean, boolean, boolean, int, int) (tried Java_com_nishtahir_androidrust_LeafJni_Java_1com_1nishtahir_1androidrust_1LeafJni_1leaf_11run_11with_11options and Java_com_nishtahir_androidrust_LeafJni_Java_1com_1nishtahir_1androidrust_1LeafJni_1leaf_11run_11with_11options__SLjava_lang_String_2ZZZII)

This is LeafJni class, it has the native method decleration. Is there any way to query available methods in the library?

package com.nishtahir.androidrust;

public class LeafJni {

    // public static native int Java_com_nishtahir_androidrust_LeafJni_leaf_1run_1with_1options(
    public static native int Java_com_nishtahir_androidrust_LeafJni_leaf_1run_1with_1options(
            short rt_id,
            String config_path,
            boolean auto_reload,
            boolean multi_thread,
            boolean auto_threads,
            int threads,
            int stack_size
    );

    static {
        try {
            System.loadLibrary("leafffi");
            Java_com_nishtahir_androidrust_LeafJni_leaf_1run_1with_1options(
                    (short) 1,
                    "config.toml",
                    false,
                    false,
                    false,
                    1,
                    100000
            );
        } catch (UnsatisfiedLinkError unsatisfiedLinkError) {
            System.out.println(
                    "UnsatisfiedLinkError: " + unsatisfiedLinkError.getMessage()
            );
        }
    }
}
tuncatunc commented 2 years ago

Hi,

./gradlew installDebug generates apk without rust library.

Why could this happen?

ncalexan commented 2 years ago

Hi,

./gradlew installDebug generates apk without rust library.

Why could this happen?

See #85, which might be relevant. Also, libname and friends.