fzyzcjy / flutter_rust_bridge

Flutter/Dart <-> Rust binding generator, feature-rich, but seamless and simple.
https://fzyzcjy.github.io/flutter_rust_bridge/
MIT License
4.08k stars 277 forks source link

`jniLibs` folder missing while trying to solve `"libc++_shared.so" not found` errors #2209

Closed zhpixel517 closed 1 month ago

zhpixel517 commented 1 month ago

Describe the bug

I've been trying to use the cpal crate on Android, but I am getting this error:

ArgumentError (Invalid argument(s): Failed to load dynamic library 'librust_lib_flutter_rust_test.so': dlopen failed: cannot locate symbol "__cxa_pure_virtual" referenced by "/data/app/~~LZ8AQs1ioV6ixGg4V_mDQA==/com.example.flutter_rust_test-9HkSZUPzs692QJUdLW2hCw==/lib/arm64/librust_lib_flutter_rust_test.so"...)

I know that this error is the same as this previous issue, but I have tried the suggestions in that issue here. That links to a 404 github page, but I was able to find the correct link for it here and add this code to my build.rs:

#[allow(dead_code)]
fn add_lib(name: impl AsRef<str>, _static: bool)
{
    #[cfg(not(feature = "test"))]
    println!(
        "cargo:rustc-link-lib={}{}",
        if _static { "static=" } else { "" },
        name.as_ref()
    );
}

fn main()
{
    let target = std::env::var("TARGET").expect("ERR: Could not check the target for the build.");

    if target.contains("android") {
        add_lib("c++_shared", false);
    }
}

this does not fix the error, but it changes it to this:

ArgumentError (Invalid argument(s): Failed to load dynamic library 'librust_lib_flutter_rust_test.so': dlopen failed: library "libc++_shared.so" not found: needed by /data/app/~~Ro6Lz7UAxhMyGMngCR07Kg==/com.example.flutter_rust_test-9hgSZf2OndGa1e0rYsmBMA==/lib/arm64/librust_lib_flutter_rust_test.so in namespace clns-4)

I searched through the documentation and I followed instructions on solving these kinds of errors here, by replacing the code in build.rs to this:

fn main() {
    #[cfg(target_os = "android")]
    println!("cargo:rustc-link-lib=c++_shared");
}

I started to follow instructions:

Then, in each jniLibs architecture directory, put the corresponding libc++_shared.so from the Android NDK. libc++_shared.so is typically located in $ANDROID_NDK/toolchains/llvm/prebuilt/. You will have to search for it, as it's different for each operating system.

however, I don't have any folder in my project called jniLibs, my android folder looks like this:

android/
   - app/
       - src/
           - debug/
           - main/
           - profile/

furthermore, the contents of ANDROID_NDK/toolchains/llvm/prebuilt just have a folder called darwin-x86_64 which has a bunch of random stuff in it. ANDROID_NDK is ~/Library/Android/sdk/ndk/27.0.12.077973/.

I tried these solutions to no success:

would this be something to take up with the cpal people instead?

Steps to reproduce

Create a new project with flutter_rust_bridge_codegen create, add cpal to cargo, and run this:

let host = cpal::default_host();

    let input_device = host.default_input_device().unwrap();
    let output_device = host.default_output_device().unwrap();

    let input_config = cpal::StreamConfig {
        channels: 1,
        sample_rate: cpal::SampleRate(48000),
        buffer_size: cpal::BufferSize::Default,
    };
    // let output_config: cpal::StreamConfig = input_config.clone();
    let output_config = cpal::StreamConfig {
        channels: 1,
        sample_rate: cpal::SampleRate(48000),
        buffer_size: cpal::BufferSize::Default,
    };

    let input_stream = input_device
        .build_input_stream(
            &input_config,
            move |data: &[f32], _: &_| {
            },
            move |err| {
                eprintln!("There was an input error: {:?}", err);
            },
            None,
        )
        .unwrap();

Logs

zacharyhaslam@MacBook-Air-208 flutter_rust_test % RUST_LOG=debug flutter_rust_bridge_codegen generate
[2024-07-17T19:37:02.913Z DEBUG /Users/zacharyhaslam/.cargo/registry/src/index.crates.io-6f17d22bba15001f/flutter_rust_bridge_codegen-2.1.0/src/main.rs:24] cli=Cli { verbose: false, command: Generate(GenerateCommandArgs { watch: false, primary: GenerateCommandArgsPrimary { config_file: None, rust_input: None, dart_output: None, c_output: None, duplicated_c_output: None, rust_root: None, rust_output: None, dart_entrypoint_class_name: None, dart_format_line_length: None, dart_preamble: None, rust_preamble: None, no_dart_enums_style: false, no_add_mod_to_lib: false, llvm_path: None, llvm_compiler_opts: None, dart_root: None, no_build_runner: false, extra_headers: None, no_web: false, no_deps_check: false, default_external_library_loader_web_prefix: None, no_dart3: false, full_dep: false, local: false, enable_lifetime: false, type_64bit_int: false, no_default_dart_async: false, stop_on_error: false, dump: None, dump_all: false } }) }
[2024-07-17T19:37:02.916Z DEBUG /Users/zacharyhaslam/.cargo/registry/src/index.crates.io-6f17d22bba15001f/flutter_rust_bridge_codegen-2.1.0/src/library/codegen/config/config_parser.rs:51] Found config file flutter_rust_bridge.yaml
[2024-07-17T19:37:02.919Z DEBUG /Users/zacharyhaslam/.cargo/registry/src/index.crates.io-6f17d22bba15001f/flutter_rust_bridge_codegen-2.1.0/src/library/codegen/mod.rs:23] config=Config { base_dir: Some(""), rust_input: Some("crate::api, crate::cpal"), dart_output: Some("lib/src/rust"), c_output: None, duplicated_c_output: None, rust_root: Some("rust/"), rust_output: None, dart_entrypoint_class_name: None, dart_format_line_length: None, dart_preamble: None, rust_preamble: None, dart_enums_style: None, add_mod_to_lib: None, llvm_path: None, llvm_compiler_opts: None, dart_root: None, build_runner: None, extra_headers: None, web: None, deps_check: None, dart3: None, full_dep: None, local: None, default_external_library_loader_web_prefix: None, dart_type_rename: None, enable_lifetime: None, type_64bit_int: None, default_dart_async: None, stop_on_error: None, dump: None, dump_all: None } meta_config=MetaConfig { watch: false }
[2024-07-17T19:37:02.920Z DEBUG /Users/zacharyhaslam/.cargo/registry/src/index.crates.io-6f17d22bba15001f/flutter_rust_bridge_codegen-2.1.0/src/library/codegen/config/internal_config_parser/mod.rs:33] InternalConfig.parse base_dir="/Users/zacharyhaslam/FlutterApplications/flutter_rust_test"
[2024-07-17T19:37:03.550Z DEBUG /Users/zacharyhaslam/.cargo/registry/src/index.crates.io-6f17d22bba15001f/flutter_rust_bridge_codegen-2.1.0/src/library/codegen/mod.rs:26] internal_config=InternalConfig { controller: ControllerInternalConfig { watch: false, watching_paths: ["/Users/zacharyhaslam/FlutterApplications/flutter_rust_test/rust/src"], exclude_paths: ["/Users/zacharyhaslam/FlutterApplications/flutter_rust_test/rust/src/frb_generated.rs"], max_count: None }, preparer: PreparerInternalConfig { dart_root: "/Users/zacharyhaslam/FlutterApplications/flutter_rust_test", deps_check: true, needs_ffigen: false }, parser: ParserInternalConfig { hir: ParserHirInternalConfig { rust_input_namespace_pack: RustInputNamespacePack { rust_input_namespace_prefixes: [Namespace { joined_path: "crate::api" }, Namespace { joined_path: "crate::cpal" }], rust_output_path_namespace: Namespace { joined_path: "crate::frb_generated" } }, rust_crate_dir: "/Users/zacharyhaslam/FlutterApplications/flutter_rust_test/rust", third_party_crate_names: [] }, mir: ParserMirInternalConfig { rust_input_namespace_pack: RustInputNamespacePack { rust_input_namespace_prefixes: [Namespace { joined_path: "crate::api" }, Namespace { joined_path: "crate::cpal" }], rust_output_path_namespace: Namespace { joined_path: "crate::frb_generated" } }, force_codec_mode_pack: Some(CodecModePack { dart2rust: Pde, rust2dart: Pde }), default_stream_sink_codec: Sse, default_rust_opaque_codec: Moi, stop_on_error: false, enable_lifetime: false, type_64bit_int: false, default_dart_async: true } }, generator: GeneratorInternalConfig { api_dart: GeneratorApiDartInternalConfig { dart_enums_style: true, dart3: true, dart_decl_base_output_path: "/Users/zacharyhaslam/FlutterApplications/flutter_rust_test/lib/src/rust", dart_impl_output_path: TargetOrCommonMap { common: "/Users/zacharyhaslam/FlutterApplications/flutter_rust_test/lib/src/rust/frb_generated.dart", io: "/Users/zacharyhaslam/FlutterApplications/flutter_rust_test/lib/src/rust/frb_generated.io.dart", web: "/Users/zacharyhaslam/FlutterApplications/flutter_rust_test/lib/src/rust/frb_generated.web.dart" }, dart_entrypoint_class_name: "RustLib", dart_preamble: "", dart_type_rename: {} }, wire: GeneratorWireInternalConfig { dart: GeneratorWireDartInternalConfig { has_ffigen: false, web_enabled: true, llvm_path: ["/opt/homebrew/opt/llvm", "/usr/local/opt/llvm", "/usr/lib/llvm-9", "/usr/lib/llvm-10", "/usr/lib/llvm-11", "/usr/lib/llvm-12", "/usr/lib/llvm-13", "/usr/lib/llvm-14", "/usr/lib/", "/usr/lib64/", "C:/Program Files/llvm", "C:/msys64/mingw64"], llvm_compiler_opts: "", dart_root: "/Users/zacharyhaslam/FlutterApplications/flutter_rust_test", extra_headers: "", dart_impl_output_path: TargetOrCommonMap { common: "/Users/zacharyhaslam/FlutterApplications/flutter_rust_test/lib/src/rust/frb_generated.dart", io: "/Users/zacharyhaslam/FlutterApplications/flutter_rust_test/lib/src/rust/frb_generated.io.dart", web: "/Users/zacharyhaslam/FlutterApplications/flutter_rust_test/lib/src/rust/frb_generated.web.dart" }, dart_output_class_name_pack: DartOutputClassNamePack { entrypoint_class_name: "RustLib", api_class_name: "RustLibApi", api_impl_class_name: "RustLibApiImpl", api_impl_platform_class_name: "RustLibApiImplPlatform", wire_class_name: "RustLibWire", wasm_module_name: "RustLibWasmModule" }, default_external_library_loader: GeneratorWireDartDefaultExternalLibraryLoaderInternalConfig { stem: "rust_lib_flutter_rust_test", io_directory: "rust/target/release/", web_prefix: "pkg/" }, c_symbol_prefix: "frbgen_flutter_rust_test_" }, rust: GeneratorWireRustInternalConfig { rust_crate_dir: "/Users/zacharyhaslam/FlutterApplications/flutter_rust_test/rust", web_enabled: true, rust_output_path: "/Users/zacharyhaslam/FlutterApplications/flutter_rust_test/rust/src/frb_generated.rs", c_symbol_prefix: "frbgen_flutter_rust_test_", has_ffigen: false, default_stream_sink_codec: Sse, default_rust_opaque_codec: Moi, rust_preamble: "" }, c: GeneratorWireCInternalConfig { enable: false, rust_crate_dir: "/Users/zacharyhaslam/FlutterApplications/flutter_rust_test/rust", rust_output_path: "/Users/zacharyhaslam/FlutterApplications/flutter_rust_test/rust/src/frb_generated.rs", c_output_path: None, c_symbol_prefix: "frbgen_flutter_rust_test_" } } }, polisher: PolisherInternalConfig { duplicated_c_output_path: [], dart_format_line_length: 80, add_mod_to_lib: true, build_runner: true, web_enabled: true, dart_root: "/Users/zacharyhaslam/FlutterApplications/flutter_rust_test", rust_crate_dir: "/Users/zacharyhaslam/FlutterApplications/flutter_rust_test/rust", rust_output_path: "/Users/zacharyhaslam/FlutterApplications/flutter_rust_test/rust/src/frb_generated.rs", c_output_path: None, enable_auto_upgrade: true }, dumper: DumperInternalConfig { dump_contents: [], dump_directory: "/Users/zacharyhaslam/FlutterApplications/flutter_rust_test/rust/target/frb_dump" } }
[2024-07-17T19:37:03.552Z DEBUG /Users/zacharyhaslam/.cargo/registry/src/index.crates.io-6f17d22bba15001f/flutter_rust_bridge_codegen-2.1.0/src/library/utils/dart_repository/dart_repo.rs:22] Guessing toolchain the runner is run into
[2024-07-17T19:37:03.553Z DEBUG /Users/zacharyhaslam/.cargo/registry/src/index.crates.io-6f17d22bba15001f/flutter_rust_bridge_codegen-2.1.0/src/library/commands/command_runner.rs:129] execute command: bin=sh args="-c \"flutter\" \"--version\"" current_dir=None cmd="sh" "-c" "\"flutter\" \"--version\""
[2024-07-17T19:37:04.189Z DEBUG /Users/zacharyhaslam/.cargo/registry/src/index.crates.io-6f17d22bba15001f/flutter_rust_bridge_codegen-2.1.0/src/library/commands/command_runner.rs:140] command="sh" "-c" "\"flutter\" \"--version\"" stdout=Flutter 3.22.2 • channel stable • https://github.com/flutter/flutter.git
Framework • revision 761747bfc5 (6 weeks ago) • 2024-06-05 22:15:13 +0200
Engine • revision edd8546116
Tools • Dart 3.4.3 • DevTools 2.34.3
 stderr=
[2024-07-17T19:37:04.190Z DEBUG /Users/zacharyhaslam/.cargo/registry/src/index.crates.io-6f17d22bba15001f/flutter_rust_bridge_codegen-2.1.0/src/library/commands/cargo_expand/mod.rs:26] run_cargo_expand manifest_dir= rust_crate_dir="/Users/zacharyhaslam/FlutterApplications/flutter_rust_test/rust"
[2024-07-17T19:37:04.190Z DEBUG /Users/zacharyhaslam/.cargo/registry/src/index.crates.io-6f17d22bba15001f/flutter_rust_bridge_codegen-2.1.0/src/library/commands/cargo_expand/real.rs:60] Running cargo expand in '"/Users/zacharyhaslam/FlutterApplications/flutter_rust_test/rust"'
[2024-07-17T19:37:04.190Z DEBUG /Users/zacharyhaslam/.cargo/registry/src/index.crates.io-6f17d22bba15001f/flutter_rust_bridge_codegen-2.1.0/src/library/commands/command_runner.rs:129] execute command: bin=cargo args="expand --lib --theme=none --ugly" current_dir=Some("/Users/zacharyhaslam/FlutterApplications/flutter_rust_test/rust") cmd=cd "/Users/zacharyhaslam/FlutterApplications/flutter_rust_test/rust" && RUSTFLAGS="--cfg frb_expand" "cargo" "expand" "--lib" "--theme=none" "--ugly"
[2024-07-17T19:37:04.965Z DEBUG /Users/zacharyhaslam/.cargo/registry/src/index.crates.io-6f17d22bba15001f/flutter_rust_bridge_codegen-2.1.0/src/library/commands/command_runner.rs:140] command=cd "/Users/zacharyhaslam/FlutterApplications/flutter_rust_test/rust" && RUSTFLAGS="--cfg frb_expand" "cargo" "expand" "--lib" "--theme=none" "--ugly" stdout=#![feature(prelude_import)]
#[prelude_import]
use std::prelude::rust_2021::*;
#[macro_use]
extern crate std;
pub mod api {

    pub mod simple {
        use cpal::traits::{DeviceTrait, HostTrait, StreamTrait};
        use log::*;
        use rtrb::RingBuffer;
        use std::env;
        use std::net::UdpSocket;
        use std::thread;
        use std::time::{Duration, SystemTime, UNIX_EPOCH};
        #[doc = "frb_encoded(235b6672622873796e63295d)"]
        pub fn greet(name: String) -> String {
            {
                let res =
                    ::alloc::fmt::format(format_args!("Hello, {0}!", name));
                res
            }
        }
        pub fn hello(a: String) -> String {
            { ::std::io::_print(format_args!("Hello was called\n")); };
            {
                let lvl = ::log::Level::Info;
                if lvl <= ::log::STATIC_MAX_LEVEL && lvl <= ::log::max_level()
                        {
                        ::log::__private_api::log(format_args!("Hello was called"),
                            lvl,
                            &("rust_lib_flutter_rust_test::api::simple",
                                    "rust_lib_flutter_rust_test::api::simple",
                                    ::log::__private_api::loc()), ());
                    }
            };
            {
                let lvl = ::log::Level::Debug;
                if lvl <= ::log::STATIC_MAX_LEVEL && lvl <= ::log::max_level()
                        {
                        ::log::__private_api::log(format_args!("Hello was called!"),
                            lvl,
                            &("rust_lib_flutter_rust_test::api::simple",
                                    "rust_lib_flutter_rust_test::api::simple",
                                    ::log::__private_api::loc()), ());
                    }
            };
            a.repeat(2)
        }
        pub fn loopback_audio() {
            const BUFFER_SIZE: usize = 1024;
            const RINGBUFFER_SIZE: usize = BUFFER_SIZE * 2;
            let (mut prod, mut cons) =
                RingBuffer::<f32>::new(RINGBUFFER_SIZE);
            let host = cpal::default_host();
            let input_device = host.default_input_device().unwrap();
            let output_device = host.default_output_device().unwrap();
            let input_config =
                cpal::StreamConfig {
                    channels: 1,
                    sample_rate: cpal::SampleRate(48000),
                    buffer_size: cpal::BufferSize::Default,
                };
            let output_config =
                cpal::StreamConfig {
                    channels: 1,
                    sample_rate: cpal::SampleRate(48000),
                    buffer_size: cpal::BufferSize::Default,
                };
            let input_stream =
                input_device.build_input_stream(&input_config,
                        move |data: &[f32], _: &_|
                            {
                                if let Ok(chunk) = prod.write_chunk_uninit(BUFFER_SIZE) {
                                        chunk.fill_from_iter(data.to_owned());
                                    }
                            },
                        move |err|
                            {
                                {
                                    ::std::io::_eprint(format_args!("There was an input error: {0:?}\n",
                                            err));
                                };
                            }, None).unwrap();
        }
        pub fn sender_side(addr: &str) {
            let socket =
                UdpSocket::bind("0.0.0.0:37069").expect("Couldn't bind!");
            let mut counter = 0;
            loop {
                let start = SystemTime::now();
                let since_epoch = start.duration_since(UNIX_EPOCH).unwrap();
                socket.send_to(&since_epoch.as_millis().to_le_bytes(),
                        addr).unwrap();
                counter += 1;
                {
                    ::std::io::_print(format_args!("Sent packet {0}\n",
                            counter));
                };
                thread::sleep(Duration::from_secs(1));
            }
        }
        #[doc = "frb_encoded(235b66726228696e6974295d)"]
        pub fn init_app() {
            env::set_var("RUST_BACKTRACE", "1");
            flutter_rust_bridge::setup_default_user_utils();
        }
    }
}
mod frb_generated {
    #![allow(non_camel_case_types, unused, non_snake_case, clippy ::
    needless_return, clippy :: redundant_closure_call, clippy ::
    redundant_closure, clippy :: useless_conversion, clippy :: unit_arg,
    clippy :: unused_unit, clippy :: double_parens, clippy :: let_and_return,
    clippy :: too_many_arguments, clippy :: match_single_binding, clippy ::
    clone_on_copy, clippy :: let_unit_value, clippy :: deref_addrof, clippy ::
    explicit_auto_deref, clippy :: borrow_deref_ref, clippy ::
    needless_borrow)]
    use flutter_rust_bridge::for_generated::byteorder::{
        NativeEndian, ReadBytesExt, WriteBytesExt,
    };
    use flutter_rust_bridge::for_generated::{
        transform_result_dco, Lifetimeable, Lockable,
    };
    use flutter_rust_bridge::{Handler, IntoIntoDart};
    #[doc(hidden)]
    pub(crate) struct FrbWrapper<T>(T);
    impl<T: Clone> Clone for FrbWrapper<T> {
        fn clone(&self) -> Self { FrbWrapper(self.0.clone()) }
    }
    impl<T: PartialEq> PartialEq for FrbWrapper<T> {
        fn eq(&self, other: &Self) -> bool { self.0.eq(&other.0) }
    }
    impl<T: Eq> Eq for FrbWrapper<T> {}
    impl<T: std::hash::Hash> std::hash::Hash for FrbWrapper<T> {
        fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
            self.0.hash(state)
        }
    }
    impl<T> From<T> for FrbWrapper<T> {
        fn from(t: T) -> Self { FrbWrapper(t) }
    }
    use std::collections::HashMap;
    use std::marker::PhantomData;
    use std::sync::Arc;
    pub struct MoiArc<T: ?Sized + MoiArcValue> {
        object_id: Option<ObjectId>,
        value: Option<Arc<T>>,
        _phantom: PhantomData<T>,
    }
    #[automatically_derived]
    impl<T: ::core::fmt::Debug + ?Sized + MoiArcValue> ::core::fmt::Debug for
        MoiArc<T> {
        #[inline]
        fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
            ::core::fmt::Formatter::debug_struct_field3_finish(f, "MoiArc",
                "object_id", &self.object_id, "value", &self.value,
                "_phantom", &&self._phantom)
        }
    }
    impl<T: ?Sized + MoiArcValue> Drop for MoiArc<T> {
        fn drop(&mut self) {
            if let Some(object_id) = self.object_id {
                    Self::decrement_strong_count(object_id);
                }
        }
    }
    impl<T: ?Sized + MoiArcValue> AsRef<T> for MoiArc<T> {
        fn as_ref(&self) -> &T { self.value.as_ref().unwrap().as_ref() }
    }
    impl<T: ?Sized + MoiArcValue>
        ::flutter_rust_bridge::for_generated::BaseArc<T> for MoiArc<T> {
        fn new(value: T) -> Self where T: Sized {
            let mut pool = T::get_pool().write().unwrap();
            let object_id = pool.id_generator.next_id();
            let value = Arc::new(value);
            let old_value =
                pool.map.insert(object_id,
                    MoiArcPoolValue { ref_count: 1, value: value.clone() });
            if !old_value.is_none() {
                    ::core::panicking::panic("assertion failed: old_value.is_none()")
                };
            Self {
                object_id: Some(object_id),
                value: Some(value),
                _phantom: PhantomData,
            }
        }
        fn try_unwrap(mut self) -> Result<T, Self> where T: Sized {
            let pool = &mut T::get_pool().write().unwrap();
            if pool.map.get(&self.object_id.unwrap()).unwrap().ref_count == 1
                    {
                    Self::decrement_strong_count_raw(self.object_id.unwrap(),
                        pool);
                    self.object_id.take().unwrap();
                    Ok(Arc::into_inner(self.value.take().unwrap()).unwrap())
                } else { Err(self) }
        }
        fn into_inner(self) -> Option<T> where T: Sized {
            self.try_unwrap().ok()
        }
        fn into_raw(mut self) -> usize { self.object_id.take().unwrap() }
    }
    impl<T: ?Sized + MoiArcValue> Clone for MoiArc<T> {
        fn clone(&self) -> Self {
            Self::increment_strong_count(self.object_id.unwrap());
            Self {
                object_id: self.object_id,
                value: self.value.clone(),
                _phantom: PhantomData,
            }
        }
    }
    impl<T: ?Sized + MoiArcValue> MoiArc<T> {
        pub(crate) fn from_raw(raw: usize) -> Self where T: Sized {
            let map = &T::get_pool().read().unwrap().map;
            Self {
                object_id: Some(raw),
                value: Some(map.get(&raw).unwrap().value.clone()),
                _phantom: PhantomData,
            }
        }
        pub fn increment_strong_count(raw: usize) {
            let map = &mut T::get_pool().write().unwrap().map;
            map.get_mut(&raw).unwrap().ref_count += 1;
        }
        pub fn decrement_strong_count(raw: usize) {
            let mut pool = T::get_pool().write().unwrap();
            let object = Self::decrement_strong_count_raw(raw, &mut pool);
            drop(pool);
            drop(object);
        }
        fn decrement_strong_count_raw(raw: usize,
            pool: &mut MoiArcPoolInner<T>) -> Option<MoiArcPoolValue<T>> {
            let value = pool.map.get_mut(&raw).unwrap();
            value.ref_count -= 1;
            if value.ref_count == 0 { pool.map.remove(&raw) } else { None }
        }
    }
    pub trait MoiArcValue: 'static {
        fn get_pool()
        -> &'static MoiArcPool<Self>;
    }
    type ObjectId = usize;
    pub type MoiArcPool<T> = std::sync::RwLock<MoiArcPoolInner<T>>;
    pub struct MoiArcPoolInner<T: ?Sized> {
        map: HashMap<ObjectId, MoiArcPoolValue<T>>,
        id_generator: IdGenerator,
    }
    impl<T: ?Sized> Default for MoiArcPoolInner<T> {
        fn default() -> Self {
            Self { map: HashMap::new(), id_generator: Default::default() }
        }
    }
    struct IdGenerator {
        next_id: ObjectId,
    }
    impl Default for IdGenerator {
        fn default() -> Self { Self { next_id: Self::MIN_ID } }
    }
    impl IdGenerator {
        const MIN_ID: ObjectId = 1;
        const MAX_ID: ObjectId = 2147483600;
        fn next_id(&mut self) -> ObjectId {
            let ans = self.next_id;
            self.next_id =
                if self.next_id >= Self::MAX_ID {
                        Self::MIN_ID
                    } else { self.next_id + 1 };
            ans
        }
    }
    impl<T: ?Sized> MoiArcPoolInner<T> {}
    struct MoiArcPoolValue<T: ?Sized> {
        ref_count: i32,
        value: Arc<T>,
    }
    use ::flutter_rust_bridge::for_generated::decode_rust_opaque_nom;
    fn decode_rust_opaque_moi<T: MoiArcValue + Send + Sync>(ptr: usize)
        -> RustOpaqueMoi<T> {
        RustOpaqueMoi::from_arc(MoiArc::<T>::from_raw(ptr))
    }
    use ::flutter_rust_bridge::for_generated::StdArc;
    use ::flutter_rust_bridge::RustOpaqueNom;
    /// Please refer to `RustOpaque` for doc.
    pub type RustOpaqueMoi<T> =
        ::flutter_rust_bridge::for_generated::RustOpaqueBase<T, MoiArc<T>>;
    /// A wrapper to support [arbitrary Rust types](https://cjycode.com/flutter_rust_bridge/guides/types/arbitrary).
    pub type RustOpaque<T> = RustOpaqueMoi<T>;
    use ::flutter_rust_bridge::RustAutoOpaqueNom;
    /// Please refer to `RustAutoOpaque` for doc.
    pub type RustAutoOpaqueMoi<T> =
        ::flutter_rust_bridge::for_generated::RustAutoOpaqueBase<T,
        MoiArc<::flutter_rust_bridge::for_generated::RustAutoOpaqueInner<T>>>;
    /// Usually this is unneeded, and just write down arbitrary types.
    /// However, when you need arbitrary types at places that are not supported yet,
    /// use `RustOpaqueOpaque<YourArbitraryType>`.
    pub type RustAutoOpaque<T> = RustAutoOpaqueMoi<T>;
    pub trait CstDecode<T> {
        fn cst_decode(self)
        -> T;
    }
    impl<T, S> CstDecode<Option<T>> for *mut S where *mut S: CstDecode<T> {
        fn cst_decode(self) -> Option<T> {
            (!self.is_null()).then(|| self.cst_decode())
        }
    }
    pub trait SseDecode {
        fn sse_decode(deserializer:
            &mut ::flutter_rust_bridge::for_generated::SseDeserializer)
        -> Self;
    }
    pub trait SseEncode {
        fn sse_encode(self,
        serializer: &mut ::flutter_rust_bridge::for_generated::SseSerializer);
    }
    fn transform_result_sse<T, E>(raw: Result<T, E>)
        ->
            Result<::flutter_rust_bridge::for_generated::Rust2DartMessageSse,
            ::flutter_rust_bridge::for_generated::Rust2DartMessageSse> where
        T: SseEncode, E: SseEncode {
        use ::flutter_rust_bridge::for_generated::{Rust2DartAction, SseCodec};
        match raw {
            Ok(raw) =>
                Ok(SseCodec::encode(Rust2DartAction::Success,
                        |serializer| { raw.sse_encode(serializer) })),
            Err(raw) =>
                Err(SseCodec::encode(Rust2DartAction::Error,
                        |serializer| { raw.sse_encode(serializer) })),
        }
    }
    pub struct StreamSink<T,
        Rust2DartCodec: ::flutter_rust_bridge::for_generated::BaseCodec =
        ::flutter_rust_bridge::for_generated::SseCodec> {
        base: ::flutter_rust_bridge::for_generated::StreamSinkBase<T,
        Rust2DartCodec>,
    }
    #[automatically_derived]
    impl<T: ::core::clone::Clone, Rust2DartCodec: ::core::clone::Clone +
        ::flutter_rust_bridge::for_generated::BaseCodec> ::core::clone::Clone
        for StreamSink<T, Rust2DartCodec> {
        #[inline]
        fn clone(&self) -> StreamSink<T, Rust2DartCodec> {
            StreamSink { base: ::core::clone::Clone::clone(&self.base) }
        }
    }
    impl<T, Rust2DartCodec: ::flutter_rust_bridge::for_generated::BaseCodec>
        StreamSink<T, Rust2DartCodec> {
        pub fn deserialize(raw: String) -> Self {
            Self {
                base: ::flutter_rust_bridge::for_generated::StreamSinkBase::deserialize(raw),
            }
        }
    }
    impl<T> StreamSink<T, ::flutter_rust_bridge::for_generated::DcoCodec> {
        pub fn add<T2>(&self, value: T)
            -> Result<(), ::flutter_rust_bridge::Rust2DartSendError> where
            T: ::flutter_rust_bridge::IntoIntoDart<T2>,
            T2: ::flutter_rust_bridge::IntoDart {
            self.add_raw(::flutter_rust_bridge::for_generated::Rust2DartAction::Success,
                value)
        }
        pub fn add_error<TR, T2>(&self, value: TR)
            -> Result<(), ::flutter_rust_bridge::Rust2DartSendError> where
            TR: ::flutter_rust_bridge::IntoIntoDart<T2>,
            T2: ::flutter_rust_bridge::IntoDart {
            self.add_raw(::flutter_rust_bridge::for_generated::Rust2DartAction::Error,
                value)
        }
        fn add_raw<TR,
            T2>(&self,
            action: ::flutter_rust_bridge::for_generated::Rust2DartAction,
            value: TR)
            -> Result<(), ::flutter_rust_bridge::Rust2DartSendError> where
            TR: ::flutter_rust_bridge::IntoIntoDart<T2>,
            T2: ::flutter_rust_bridge::IntoDart {
            self.base.add_raw(::flutter_rust_bridge::for_generated::DcoCodec::encode(action,
                    value.into_into_dart()))
        }
    }
    impl<T> StreamSink<T, ::flutter_rust_bridge::for_generated::SseCodec>
        where T: SseEncode {
        pub fn add(&self, value: T)
            -> Result<(), ::flutter_rust_bridge::Rust2DartSendError> {
            self.add_raw(::flutter_rust_bridge::for_generated::Rust2DartAction::Success,
                value)
        }
        pub fn add_error<TR: SseEncode>(&self, value: TR)
            -> Result<(), ::flutter_rust_bridge::Rust2DartSendError> {
            self.add_raw(::flutter_rust_bridge::for_generated::Rust2DartAction::Error,
                value)
        }
        pub fn add_raw<TR: SseEncode>(&self,
            action: ::flutter_rust_bridge::for_generated::Rust2DartAction,
            value: TR)
            -> Result<(), ::flutter_rust_bridge::Rust2DartSendError> {
            self.base.add_raw(::flutter_rust_bridge::for_generated::SseCodec::encode(action,
                    |serializer| value.sse_encode(serializer)))
        }
    }
    impl<T, Rust2DartCodec: ::flutter_rust_bridge::for_generated::BaseCodec>
        ::flutter_rust_bridge::IntoIntoDart<StreamSink<T, Rust2DartCodec>> for
        StreamSink<T, Rust2DartCodec> {
        fn into_into_dart(self) -> StreamSink<T, Rust2DartCodec> {
            ::core::panicking::panic("internal error: entered unreachable code")
        }
    }
    impl<T, Rust2DartCodec: ::flutter_rust_bridge::for_generated::BaseCodec>
        ::flutter_rust_bridge::IntoDart for StreamSink<T, Rust2DartCodec> {
        fn into_dart(self) -> ::flutter_rust_bridge::for_generated::DartAbi {
            ::core::panicking::panic("internal error: entered unreachable code")
        }
    }
    pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_VERSION: &str = "2.1.0";
    pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 =
        970588621;
    #[allow(missing_copy_implementations)]
    #[allow(non_camel_case_types)]
    #[allow(dead_code)]
    pub struct FLUTTER_RUST_BRIDGE_HANDLER {
        __private_field: (),
    }
    #[doc(hidden)]
    pub static FLUTTER_RUST_BRIDGE_HANDLER: FLUTTER_RUST_BRIDGE_HANDLER =
        FLUTTER_RUST_BRIDGE_HANDLER { __private_field: () };
    impl ::lazy_static::__Deref for FLUTTER_RUST_BRIDGE_HANDLER {
        type Target =
            ::flutter_rust_bridge::DefaultHandler<::flutter_rust_bridge::for_generated::SimpleThreadPool>;
        fn deref(&self)
            ->
                &::flutter_rust_bridge::DefaultHandler<::flutter_rust_bridge::for_generated::SimpleThreadPool> {
            #[inline(always)]
            fn __static_ref_initialize()
                ->
                    ::flutter_rust_bridge::DefaultHandler<::flutter_rust_bridge::for_generated::SimpleThreadPool> {
                {
                    match (&FLUTTER_RUST_BRIDGE_CODEGEN_VERSION,
                            &flutter_rust_bridge::for_generated::FLUTTER_RUST_BRIDGE_RUNTIME_VERSION)
                        {
                        (left_val, right_val) => {
                            if !(*left_val == *right_val) {
                                    let kind = ::core::panicking::AssertKind::Eq;
                                    ::core::panicking::assert_failed(kind, &*left_val,
                                        &*right_val,
                                        ::core::option::Option::Some(format_args!("Please ensure flutter_rust_bridge\'s codegen ({0}) and runtime ({1}) versions are the same",
                                                FLUTTER_RUST_BRIDGE_CODEGEN_VERSION,
                                                flutter_rust_bridge::for_generated::FLUTTER_RUST_BRIDGE_RUNTIME_VERSION)));
                                }
                        }
                    };
                    ::flutter_rust_bridge::DefaultHandler::new_simple(Default::default())
                }
            }
            #[inline(always)]
            fn __stability()
                ->
                    &'static ::flutter_rust_bridge::DefaultHandler<::flutter_rust_bridge::for_generated::SimpleThreadPool> {
                static LAZY:
                    ::lazy_static::lazy::Lazy<::flutter_rust_bridge::DefaultHandler<::flutter_rust_bridge::for_generated::SimpleThreadPool>>
                    =
                    ::lazy_static::lazy::Lazy::INIT;
                LAZY.get(__static_ref_initialize)
            }
            __stability()
        }
    }
    impl ::lazy_static::LazyStatic for FLUTTER_RUST_BRIDGE_HANDLER {
        fn initialize(lazy: &Self) { let _ = &**lazy; }
    }
    fn wire__crate__api__simple__greet_impl(ptr_:
            flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr,
        rust_vec_len_: i32, data_len_: i32)
        -> flutter_rust_bridge::for_generated::WireSyncRust2DartSse {
        FLUTTER_RUST_BRIDGE_HANDLER.wrap_sync::<flutter_rust_bridge::for_generated::SseCodec,
            _>(flutter_rust_bridge::for_generated::TaskInfo {
                debug_name: "greet",
                port: None,
                mode: flutter_rust_bridge::for_generated::FfiCallMode::Sync,
            },
            move ||
                {
                    let message =
                        unsafe {
                            flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire(ptr_,
                                rust_vec_len_, data_len_)
                        };
                    let mut deserializer =
                        flutter_rust_bridge::for_generated::SseDeserializer::new(message);
                    let api_name = <String>::sse_decode(&mut deserializer);
                    deserializer.end();
                    transform_result_sse::<_,
                            ()>((move ||
                                    {
                                        let output_ok =
                                            Result::<_, ()>::Ok(crate::api::simple::greet(api_name))?;
                                        Ok(output_ok)
                                    })())
                })
    }
    fn wire__crate__api__simple__hello_impl(port_:
            flutter_rust_bridge::for_generated::MessagePort,
        ptr_:
            flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr,
        rust_vec_len_: i32, data_len_: i32) {
        FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::<flutter_rust_bridge::for_generated::SseCodec,
            _,
            _>(flutter_rust_bridge::for_generated::TaskInfo {
                debug_name: "hello",
                port: Some(port_),
                mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal,
            },
            move ||
                {
                    let message =
                        unsafe {
                            flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire(ptr_,
                                rust_vec_len_, data_len_)
                        };
                    let mut deserializer =
                        flutter_rust_bridge::for_generated::SseDeserializer::new(message);
                    let api_a = <String>::sse_decode(&mut deserializer);
                    deserializer.end();
                    move |context|
                        {
                            transform_result_sse::<_,
                                    ()>((move ||
                                            {
                                                let output_ok =
                                                    Result::<_, ()>::Ok(crate::api::simple::hello(api_a))?;
                                                Ok(output_ok)
                                            })())
                        }
                })
    }
    fn wire__crate__api__simple__init_app_impl(port_:
            flutter_rust_bridge::for_generated::MessagePort,
        ptr_:
            flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr,
        rust_vec_len_: i32, data_len_: i32) {
        FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::<flutter_rust_bridge::for_generated::SseCodec,
            _,
            _>(flutter_rust_bridge::for_generated::TaskInfo {
                debug_name: "init_app",
                port: Some(port_),
                mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal,
            },
            move ||
                {
                    let message =
                        unsafe {
                            flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire(ptr_,
                                rust_vec_len_, data_len_)
                        };
                    let mut deserializer =
                        flutter_rust_bridge::for_generated::SseDeserializer::new(message);
                    deserializer.end();
                    move |context|
                        {
                            transform_result_sse::<_,
                                    ()>((move ||
                                            {
                                                let output_ok =
                                                    Result::<_, ()>::Ok({ crate::api::simple::init_app(); })?;
                                                Ok(output_ok)
                                            })())
                        }
                })
    }
    fn wire__crate__api__simple__loopback_audio_impl(port_:
            flutter_rust_bridge::for_generated::MessagePort,
        ptr_:
            flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr,
        rust_vec_len_: i32, data_len_: i32) {
        FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::<flutter_rust_bridge::for_generated::SseCodec,
            _,
            _>(flutter_rust_bridge::for_generated::TaskInfo {
                debug_name: "loopback_audio",
                port: Some(port_),
                mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal,
            },
            move ||
                {
                    let message =
                        unsafe {
                            flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire(ptr_,
                                rust_vec_len_, data_len_)
                        };
                    let mut deserializer =
                        flutter_rust_bridge::for_generated::SseDeserializer::new(message);
                    deserializer.end();
                    move |context|
                        {
                            transform_result_sse::<_,
                                    ()>((move ||
                                            {
                                                let output_ok =
                                                    Result::<_,
                                                                ()>::Ok({ crate::api::simple::loopback_audio(); })?;
                                                Ok(output_ok)
                                            })())
                        }
                })
    }
    fn wire__crate__api__simple__sender_side_impl(port_:
            flutter_rust_bridge::for_generated::MessagePort,
        ptr_:
            flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr,
        rust_vec_len_: i32, data_len_: i32) {
        FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::<flutter_rust_bridge::for_generated::SseCodec,
            _,
            _>(flutter_rust_bridge::for_generated::TaskInfo {
                debug_name: "sender_side",
                port: Some(port_),
                mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal,
            },
            move ||
                {
                    let message =
                        unsafe {
                            flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire(ptr_,
                                rust_vec_len_, data_len_)
                        };
                    let mut deserializer =
                        flutter_rust_bridge::for_generated::SseDeserializer::new(message);
                    let api_addr = <String>::sse_decode(&mut deserializer);
                    deserializer.end();
                    move |context|
                        {
                            transform_result_sse::<_,
                                    ()>((move ||
                                            {
                                                let output_ok =
                                                    Result::<_,
                                                                ()>::Ok({ crate::api::simple::sender_side(&api_addr); })?;
                                                Ok(output_ok)
                                            })())
                        }
                })
    }
    impl SseDecode for String {
        fn sse_decode(deserializer:
                &mut flutter_rust_bridge::for_generated::SseDeserializer)
            -> Self {
            let mut inner = <Vec<u8>>::sse_decode(deserializer);
            return String::from_utf8(inner).unwrap();
        }
    }
    impl SseDecode for Vec<u8> {
        fn sse_decode(deserializer:
                &mut flutter_rust_bridge::for_generated::SseDeserializer)
            -> Self {
            let mut len_ = <i32>::sse_decode(deserializer);
            let mut ans_ = ::alloc::vec::Vec::new();
            for idx_ in 0..len_ { ans_.push(<u8>::sse_decode(deserializer)); }
            return ans_;
        }
    }
    impl SseDecode for u8 {
        fn sse_decode(deserializer:
                &mut flutter_rust_bridge::for_generated::SseDeserializer)
            -> Self {
            deserializer.cursor.read_u8().unwrap()
        }
    }
    impl SseDecode for () {
        fn sse_decode(deserializer:
                &mut flutter_rust_bridge::for_generated::SseDeserializer)
            -> Self {}
    }
    impl SseDecode for i32 {
        fn sse_decode(deserializer:
                &mut flutter_rust_bridge::for_generated::SseDeserializer)
            -> Self {
            deserializer.cursor.read_i32::<NativeEndian>().unwrap()
        }
    }
    impl SseDecode for bool {
        fn sse_decode(deserializer:
                &mut flutter_rust_bridge::for_generated::SseDeserializer)
            -> Self {
            deserializer.cursor.read_u8().unwrap() != 0
        }
    }
    fn pde_ffi_dispatcher_primary_impl(func_id: i32,
        port: flutter_rust_bridge::for_generated::MessagePort,
        ptr:
            flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr,
        rust_vec_len: i32, data_len: i32) {
        match func_id {
            2 =>
                wire__crate__api__simple__hello_impl(port, ptr, rust_vec_len,
                    data_len),
            3 =>
                wire__crate__api__simple__init_app_impl(port, ptr,
                    rust_vec_len, data_len),
            4 =>
                wire__crate__api__simple__loopback_audio_impl(port, ptr,
                    rust_vec_len, data_len),
            5 =>
                wire__crate__api__simple__sender_side_impl(port, ptr,
                    rust_vec_len, data_len),
            _ =>
                ::core::panicking::panic("internal error: entered unreachable code"),
        }
    }
    fn pde_ffi_dispatcher_sync_impl(func_id: i32,
        ptr:
            flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr,
        rust_vec_len: i32, data_len: i32)
        -> flutter_rust_bridge::for_generated::WireSyncRust2DartSse {
        match func_id {
            1 =>
                wire__crate__api__simple__greet_impl(ptr, rust_vec_len,
                    data_len),
            _ =>
                ::core::panicking::panic("internal error: entered unreachable code"),
        }
    }
    impl SseEncode for String {
        fn sse_encode(self,
            serializer:
                &mut flutter_rust_bridge::for_generated::SseSerializer) {
            <Vec<u8>>::sse_encode(self.into_bytes(), serializer);
        }
    }
    impl SseEncode for Vec<u8> {
        fn sse_encode(self,
            serializer:
                &mut flutter_rust_bridge::for_generated::SseSerializer) {
            <i32>::sse_encode(self.len() as _, serializer);
            for item in self { <u8>::sse_encode(item, serializer); }
        }
    }
    impl SseEncode for u8 {
        fn sse_encode(self,
            serializer:
                &mut flutter_rust_bridge::for_generated::SseSerializer) {
            serializer.cursor.write_u8(self).unwrap();
        }
    }
    impl SseEncode for () {
        fn sse_encode(self,
            serializer:
                &mut flutter_rust_bridge::for_generated::SseSerializer) {}
    }
    impl SseEncode for i32 {
        fn sse_encode(self,
            serializer:
                &mut flutter_rust_bridge::for_generated::SseSerializer) {
            serializer.cursor.write_i32::<NativeEndian>(self).unwrap();
        }
    }
    impl SseEncode for bool {
        fn sse_encode(self,
            serializer:
                &mut flutter_rust_bridge::for_generated::SseSerializer) {
            serializer.cursor.write_u8(self as _).unwrap();
        }
    }
    #[cfg(not(target_family = "wasm"))]
    mod io {
        use super::*;
        use flutter_rust_bridge::for_generated::byteorder::{
            NativeEndian, ReadBytesExt, WriteBytesExt,
        };
        use flutter_rust_bridge::for_generated::{
            transform_result_dco, Lifetimeable, Lockable,
        };
        use flutter_rust_bridge::{Handler, IntoIntoDart};
        pub trait NewWithNullPtr {
            fn new_with_null_ptr()
            -> Self;
        }
        impl<T> NewWithNullPtr for *mut T {
            fn new_with_null_ptr() -> Self { std::ptr::null_mut() }
        }
        #[no_mangle]
        pub extern "C" fn frb_get_rust_content_hash() -> i32 {
            FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH
        }
        #[no_mangle]
        pub extern "C" fn frb_pde_ffi_dispatcher_primary(func_id: i32,
            port_: i64, ptr_: *mut u8, rust_vec_len_: i32, data_len_: i32) {
            pde_ffi_dispatcher_primary_impl(func_id, port_, ptr_,
                rust_vec_len_, data_len_)
        }
        #[no_mangle]
        pub extern "C" fn frb_pde_ffi_dispatcher_sync(func_id: i32,
            ptr_: *mut u8, rust_vec_len_: i32, data_len_: i32)
            -> ::flutter_rust_bridge::for_generated::WireSyncRust2DartSse {
            pde_ffi_dispatcher_sync_impl(func_id, ptr_, rust_vec_len_,
                data_len_)
        }
        #[no_mangle]
        pub extern "C" fn dart_fn_deliver_output(call_id: i32, ptr_: *mut u8,
            rust_vec_len_: i32, data_len_: i32) {
            let message =
                unsafe {
                    ::flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire(ptr_,
                        rust_vec_len_, data_len_)
                };
            FLUTTER_RUST_BRIDGE_HANDLER.dart_fn_handle_output(call_id,
                message)
        }
    }
    #[cfg(not(target_family = "wasm"))]
    pub use io::*;
}
 stderr=   Compiling rust_lib_flutter_rust_test v0.1.0 (/Users/zacharyhaslam/FlutterApplications/flutter_rust_test/rust)
warning: unused import: `StreamTrait`
 --> src/api/simple.rs:1:44
  |
1 | use cpal::traits::{DeviceTrait, HostTrait, StreamTrait};
  |                                            ^^^^^^^^^^^
  |
  = note: `#[warn(unused_imports)]` on by default
    Finished dev [unoptimized + debuginfo] target(s) in 0.66s

[2024-07-17T19:37:04.981Z DEBUG /Users/zacharyhaslam/.cargo/registry/src/index.crates.io-6f17d22bba15001f/flutter_rust_bridge_codegen-2.1.0/src/library/codegen/parser/mir/parser/function/real/mod.rs:139] parse_function function name: "greet"
[2024-07-17T19:37:04.982Z DEBUG /Users/zacharyhaslam/.cargo/registry/src/index.crates.io-6f17d22bba15001f/flutter_rust_bridge_codegen-2.1.0/src/library/codegen/parser/mir/parser/function/real/lifetime.rs:36] parse_function_lifetime name=greet inputs_lifetimes=[[]] output_lifetimes=[] ans=ParseFunctionLifetimeOutput { needs_extend_lifetime_per_arg: [false] }
[2024-07-17T19:37:04.982Z DEBUG /Users/zacharyhaslam/.cargo/registry/src/index.crates.io-6f17d22bba15001f/flutter_rust_bridge_codegen-2.1.0/src/library/codegen/parser/mir/parser/ty/ty.rs:12] TypeParserWithContext.parse_type ty=String ans=Delegate(String)
[2024-07-17T19:37:04.982Z DEBUG /Users/zacharyhaslam/.cargo/registry/src/index.crates.io-6f17d22bba15001f/flutter_rust_bridge_codegen-2.1.0/src/library/codegen/parser/mir/parser/ty/ty.rs:12] TypeParserWithContext.parse_type ty=String ans=Delegate(String)
[2024-07-17T19:37:04.982Z DEBUG /Users/zacharyhaslam/.cargo/registry/src/index.crates.io-6f17d22bba15001f/flutter_rust_bridge_codegen-2.1.0/src/library/codegen/parser/mir/parser/function/real/mod.rs:139] parse_function function name: "hello"
[2024-07-17T19:37:04.982Z DEBUG /Users/zacharyhaslam/.cargo/registry/src/index.crates.io-6f17d22bba15001f/flutter_rust_bridge_codegen-2.1.0/src/library/codegen/parser/mir/parser/function/real/lifetime.rs:36] parse_function_lifetime name=hello inputs_lifetimes=[[]] output_lifetimes=[] ans=ParseFunctionLifetimeOutput { needs_extend_lifetime_per_arg: [false] }
[2024-07-17T19:37:04.982Z DEBUG /Users/zacharyhaslam/.cargo/registry/src/index.crates.io-6f17d22bba15001f/flutter_rust_bridge_codegen-2.1.0/src/library/codegen/parser/mir/parser/ty/ty.rs:12] TypeParserWithContext.parse_type ty=String ans=Delegate(String)
[2024-07-17T19:37:04.982Z DEBUG /Users/zacharyhaslam/.cargo/registry/src/index.crates.io-6f17d22bba15001f/flutter_rust_bridge_codegen-2.1.0/src/library/codegen/parser/mir/parser/ty/ty.rs:12] TypeParserWithContext.parse_type ty=String ans=Delegate(String)
[2024-07-17T19:37:04.982Z DEBUG /Users/zacharyhaslam/.cargo/registry/src/index.crates.io-6f17d22bba15001f/flutter_rust_bridge_codegen-2.1.0/src/library/codegen/parser/mir/parser/function/real/mod.rs:139] parse_function function name: "init_app"
[2024-07-17T19:37:04.982Z DEBUG /Users/zacharyhaslam/.cargo/registry/src/index.crates.io-6f17d22bba15001f/flutter_rust_bridge_codegen-2.1.0/src/library/codegen/parser/mir/parser/function/real/lifetime.rs:36] parse_function_lifetime name=init_app inputs_lifetimes=[] output_lifetimes=[] ans=ParseFunctionLifetimeOutput { needs_extend_lifetime_per_arg: [] }
[2024-07-17T19:37:04.982Z DEBUG /Users/zacharyhaslam/.cargo/registry/src/index.crates.io-6f17d22bba15001f/flutter_rust_bridge_codegen-2.1.0/src/library/codegen/parser/mir/parser/function/real/mod.rs:139] parse_function function name: "loopback_audio"
[2024-07-17T19:37:04.982Z DEBUG /Users/zacharyhaslam/.cargo/registry/src/index.crates.io-6f17d22bba15001f/flutter_rust_bridge_codegen-2.1.0/src/library/codegen/parser/mir/parser/function/real/lifetime.rs:36] parse_function_lifetime name=loopback_audio inputs_lifetimes=[] output_lifetimes=[] ans=ParseFunctionLifetimeOutput { needs_extend_lifetime_per_arg: [] }
[2024-07-17T19:37:04.982Z DEBUG /Users/zacharyhaslam/.cargo/registry/src/index.crates.io-6f17d22bba15001f/flutter_rust_bridge_codegen-2.1.0/src/library/codegen/parser/mir/parser/function/real/mod.rs:139] parse_function function name: "sender_side"
[2024-07-17T19:37:04.982Z DEBUG /Users/zacharyhaslam/.cargo/registry/src/index.crates.io-6f17d22bba15001f/flutter_rust_bridge_codegen-2.1.0/src/library/codegen/parser/mir/parser/function/real/lifetime.rs:36] parse_function_lifetime name=sender_side inputs_lifetimes=[[]] output_lifetimes=[] ans=ParseFunctionLifetimeOutput { needs_extend_lifetime_per_arg: [false] }
[2024-07-17T19:37:04.982Z DEBUG /Users/zacharyhaslam/.cargo/registry/src/index.crates.io-6f17d22bba15001f/flutter_rust_bridge_codegen-2.1.0/src/library/codegen/parser/mir/parser/ty/ty.rs:12] TypeParserWithContext.parse_type ty=str ans=Delegate(String)
[2024-07-17T19:37:04.985Z DEBUG /Users/zacharyhaslam/.cargo/registry/src/index.crates.io-6f17d22bba15001f/flutter_rust_bridge_codegen-2.1.0/src/library/codegen/parser/mir/parser/function/real/mod.rs:139] parse_function function name: "greet"
[2024-07-17T19:37:04.985Z DEBUG /Users/zacharyhaslam/.cargo/registry/src/index.crates.io-6f17d22bba15001f/flutter_rust_bridge_codegen-2.1.0/src/library/codegen/parser/mir/parser/function/real/lifetime.rs:36] parse_function_lifetime name=greet inputs_lifetimes=[[]] output_lifetimes=[] ans=ParseFunctionLifetimeOutput { needs_extend_lifetime_per_arg: [false] }
[2024-07-17T19:37:04.985Z DEBUG /Users/zacharyhaslam/.cargo/registry/src/index.crates.io-6f17d22bba15001f/flutter_rust_bridge_codegen-2.1.0/src/library/codegen/parser/mir/parser/ty/ty.rs:12] TypeParserWithContext.parse_type ty=String ans=Delegate(String)
[2024-07-17T19:37:04.985Z DEBUG /Users/zacharyhaslam/.cargo/registry/src/index.crates.io-6f17d22bba15001f/flutter_rust_bridge_codegen-2.1.0/src/library/codegen/parser/mir/parser/ty/ty.rs:12] TypeParserWithContext.parse_type ty=String ans=Delegate(String)
[2024-07-17T19:37:04.985Z DEBUG /Users/zacharyhaslam/.cargo/registry/src/index.crates.io-6f17d22bba15001f/flutter_rust_bridge_codegen-2.1.0/src/library/codegen/parser/mir/parser/function/real/mod.rs:139] parse_function function name: "hello"
[2024-07-17T19:37:04.985Z DEBUG /Users/zacharyhaslam/.cargo/registry/src/index.crates.io-6f17d22bba15001f/flutter_rust_bridge_codegen-2.1.0/src/library/codegen/parser/mir/parser/function/real/lifetime.rs:36] parse_function_lifetime name=hello inputs_lifetimes=[[]] output_lifetimes=[] ans=ParseFunctionLifetimeOutput { needs_extend_lifetime_per_arg: [false] }
[2024-07-17T19:37:04.985Z DEBUG /Users/zacharyhaslam/.cargo/registry/src/index.crates.io-6f17d22bba15001f/flutter_rust_bridge_codegen-2.1.0/src/library/codegen/parser/mir/parser/ty/ty.rs:12] TypeParserWithContext.parse_type ty=String ans=Delegate(String)
[2024-07-17T19:37:04.985Z DEBUG /Users/zacharyhaslam/.cargo/registry/src/index.crates.io-6f17d22bba15001f/flutter_rust_bridge_codegen-2.1.0/src/library/codegen/parser/mir/parser/ty/ty.rs:12] TypeParserWithContext.parse_type ty=String ans=Delegate(String)
[2024-07-17T19:37:04.985Z DEBUG /Users/zacharyhaslam/.cargo/registry/src/index.crates.io-6f17d22bba15001f/flutter_rust_bridge_codegen-2.1.0/src/library/codegen/parser/mir/parser/function/real/mod.rs:139] parse_function function name: "init_app"
[2024-07-17T19:37:04.985Z DEBUG /Users/zacharyhaslam/.cargo/registry/src/index.crates.io-6f17d22bba15001f/flutter_rust_bridge_codegen-2.1.0/src/library/codegen/parser/mir/parser/function/real/lifetime.rs:36] parse_function_lifetime name=init_app inputs_lifetimes=[] output_lifetimes=[] ans=ParseFunctionLifetimeOutput { needs_extend_lifetime_per_arg: [] }
[2024-07-17T19:37:04.985Z DEBUG /Users/zacharyhaslam/.cargo/registry/src/index.crates.io-6f17d22bba15001f/flutter_rust_bridge_codegen-2.1.0/src/library/codegen/parser/mir/parser/function/real/mod.rs:139] parse_function function name: "loopback_audio"
[2024-07-17T19:37:04.985Z DEBUG /Users/zacharyhaslam/.cargo/registry/src/index.crates.io-6f17d22bba15001f/flutter_rust_bridge_codegen-2.1.0/src/library/codegen/parser/mir/parser/function/real/lifetime.rs:36] parse_function_lifetime name=loopback_audio inputs_lifetimes=[] output_lifetimes=[] ans=ParseFunctionLifetimeOutput { needs_extend_lifetime_per_arg: [] }
[2024-07-17T19:37:04.985Z DEBUG /Users/zacharyhaslam/.cargo/registry/src/index.crates.io-6f17d22bba15001f/flutter_rust_bridge_codegen-2.1.0/src/library/codegen/parser/mir/parser/function/real/mod.rs:139] parse_function function name: "sender_side"
[2024-07-17T19:37:04.985Z DEBUG /Users/zacharyhaslam/.cargo/registry/src/index.crates.io-6f17d22bba15001f/flutter_rust_bridge_codegen-2.1.0/src/library/codegen/parser/mir/parser/function/real/lifetime.rs:36] parse_function_lifetime name=sender_side inputs_lifetimes=[[]] output_lifetimes=[] ans=ParseFunctionLifetimeOutput { needs_extend_lifetime_per_arg: [false] }
[2024-07-17T19:37:04.985Z DEBUG /Users/zacharyhaslam/.cargo/registry/src/index.crates.io-6f17d22bba15001f/flutter_rust_bridge_codegen-2.1.0/src/library/codegen/parser/mir/parser/ty/ty.rs:12] TypeParserWithContext.parse_type ty=str ans=Delegate(String)
[2024-07-17T19:37:04.988Z DEBUG /Users/zacharyhaslam/.cargo/registry/src/index.crates.io-6f17d22bba15001f/flutter_rust_bridge_codegen-2.1.0/src/library/commands/format_dart.rs:24] execute format_dart paths=["lib/src/rust/frb_generated.io.dart", "lib/src/rust/api/simple.dart", "lib/src/rust/frb_generated.dart", "lib/src/rust/frb_generated.web.dart"] line_length=80
[2024-07-17T19:37:04.988Z DEBUG /Users/zacharyhaslam/.cargo/registry/src/index.crates.io-6f17d22bba15001f/flutter_rust_bridge_codegen-2.1.0/src/library/commands/command_runner.rs:129] execute command: bin=sh args="-c \"dart\" \"format\" \"--line-length\" \"80\" \"lib/src/rust/frb_generated.io.dart\" \"lib/src/rust/api/simple.dart\" \"lib/src/rust/frb_generated.dart\" \"lib/src/rust/frb_generated.web.dart\"" current_dir=Some("/Users/zacharyhaslam/FlutterApplications/flutter_rust_test") cmd=cd "/Users/zacharyhaslam/FlutterApplications/flutter_rust_test" && "sh" "-c" "\"dart\" \"format\" \"--line-length\" \"80\" \"lib/src/rust/frb_generated.io.dart\" \"lib/src/rust/api/simple.dart\" \"lib/src/rust/frb_generated.dart\" \"lib/src/rust/frb_generated.web.dart\""
[2024-07-17T19:37:06.490Z DEBUG /Users/zacharyhaslam/.cargo/registry/src/index.crates.io-6f17d22bba15001f/flutter_rust_bridge_codegen-2.1.0/src/library/commands/command_runner.rs:140] command=cd "/Users/zacharyhaslam/FlutterApplications/flutter_rust_test" && "sh" "-c" "\"dart\" \"format\" \"--line-length\" \"80\" \"lib/src/rust/frb_generated.io.dart\" \"lib/src/rust/api/simple.dart\" \"lib/src/rust/frb_generated.dart\" \"lib/src/rust/frb_generated.web.dart\"" stdout=Formatted lib/src/rust/frb_generated.io.dart
Formatted lib/src/rust/api/simple.dart
Formatted lib/src/rust/frb_generated.dart
Formatted lib/src/rust/frb_generated.web.dart
Formatted 4 files (4 changed) in 0.27 seconds.
 stderr=
[2024-07-17T19:37:06.490Z DEBUG /Users/zacharyhaslam/.cargo/registry/src/index.crates.io-6f17d22bba15001f/flutter_rust_bridge_codegen-2.1.0/src/library/commands/format_rust.rs:9] execute format_rust paths=["src/frb_generated.rs"]
[2024-07-17T19:37:06.490Z DEBUG /Users/zacharyhaslam/.cargo/registry/src/index.crates.io-6f17d22bba15001f/flutter_rust_bridge_codegen-2.1.0/src/library/commands/command_runner.rs:129] execute command: bin=sh args="-c \"rustfmt\" \"--edition\" \"2018\" \"src/frb_generated.rs\"" current_dir=Some("/Users/zacharyhaslam/FlutterApplications/flutter_rust_test/rust") cmd=cd "/Users/zacharyhaslam/FlutterApplications/flutter_rust_test/rust" && "sh" "-c" "\"rustfmt\" \"--edition\" \"2018\" \"src/frb_generated.rs\""
[2024-07-17T19:37:06.545Z DEBUG /Users/zacharyhaslam/.cargo/registry/src/index.crates.io-6f17d22bba15001f/flutter_rust_bridge_codegen-2.1.0/src/library/commands/command_runner.rs:140] command=cd "/Users/zacharyhaslam/FlutterApplications/flutter_rust_test/rust" && "sh" "-c" "\"rustfmt\" \"--edition\" \"2018\" \"src/frb_generated.rs\"" stdout= stderr=
[2024-07-17T19:37:06.545Z DEBUG /Users/zacharyhaslam/.cargo/registry/src/index.crates.io-6f17d22bba15001f/flutter_rust_bridge_codegen-2.1.0/src/library/utils/dart_repository/dart_repo.rs:22] Guessing toolchain the runner is run into
[2024-07-17T19:37:06.546Z DEBUG /Users/zacharyhaslam/.cargo/registry/src/index.crates.io-6f17d22bba15001f/flutter_rust_bridge_codegen-2.1.0/src/library/utils/dart_repository/dart_repo.rs:71] Checking presence of flutter_rust_bridge in dependencies at /Users/zacharyhaslam/FlutterApplications/flutter_rust_test
[2024-07-17T19:37:06.546Z DEBUG /Users/zacharyhaslam/.cargo/registry/src/index.crates.io-6f17d22bba15001f/flutter_rust_bridge_codegen-2.1.0/src/library/utils/dart_repository/dart_repo.rs:103] Checking presence of flutter_rust_bridge in dependencies at /Users/zacharyhaslam/FlutterApplications/flutter_rust_test
[0.8s] Parse  
  └── [0.8s] Cargo expand & syn parse  
  └── [0.0s] Parse HIR  
  └── [0.0s] Parse MIR  
[0.0s] Generate  
[1.6s] Polish  
  └── [1.5s] Run Dart formatter  
  └── [0.1s] Run Rust formatter  
  └── [0.0s] Auto upgrade                                                                                                                                               Done!

Expected behavior

No response

Generated binding code

No response

OS

No response

Version of flutter_rust_bridge_codegen

No response

Flutter info

No response

Version of clang++

No response

Additional context

No response

fzyzcjy commented 1 month ago

I am not an expert of cpal, and from the errors you mentioned, it seems to be related to cpal instead of flutter-rust-bridge. My naive guess of "jniLibs folder missing" is to create an empty folder.

would this be something to take up with the cpal people instead?

I think so, maybe try to ask there since it looks like a general "how to compile cpal on android".

zhpixel517 commented 1 month ago

I was able to fix it. My original issue was that I couldn't actually find the libc++_shared.so on my system. The docs say that you can find it in $ANDROID_NDK/toolchains/llvm/prebuilt/ which is true, but in my case I had to search even deeper to find them in $ANDROID_NDK/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib. Then inside that directory are the different folders for x86_64-linux-android, aarch64-linux-android, etc.

I had to make the jniLibs folder inside android/app/src, then inside that folder create folders with these names and copy the libc++_shared.so from each one into the new folders separately.

Next I added this to my android/app/src/build.gradle inside android { ....

sourceSets {
        main {
            jni.srcDirs = []
            jniLibs.srcDirs = ['src/jniLibs']
        }
    }

Finally , based on this, my build.rs looks like this:

#[allow(dead_code)]
fn add_lib(name: impl AsRef<str>, _static: bool)
{
    #[cfg(not(feature = "test"))]
    println!(
        "cargo:rustc-link-lib={}{}",
        if _static { "static=" } else { "" },
        name.as_ref()
    );
}

fn main()
{
    let target = std::env::var("TARGET").expect("ERR: Could not check the target for the build.");

    if target.contains("android") {
        add_lib("c++_shared", false);
    }
}

unfortunately, copying the build.rs sample from the doc's troubleshooting page about this issue didn't work for me. in fact with this setup, it actually brought Could not resolve symbol __cxa_pure_virtual error back.

after these steps, the issue is solved. For extra reference, here is a template repo someone setup with cpal setup on Android.

fzyzcjy commented 1 month ago

Happy to see the cpal compilation problem is fixed!

github-actions[bot] commented 2 weeks ago

This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new issue.