pass rust args to flutter
Signed-off-by: 21pages <pages21@163.com>
This commit is contained in:
parent
089cf41a2f
commit
2ced73cdda
@ -7,7 +7,8 @@
|
||||
#include "utils.h"
|
||||
// #include <bitsdojo_window_windows/bitsdojo_window_plugin.h>
|
||||
|
||||
typedef bool (*FUNC_RUSTDESK_CORE_MAIN)(void);
|
||||
typedef char** (*FUNC_RUSTDESK_CORE_MAIN)(int*);
|
||||
typedef void (*FUNC_RUSTDESK_FREE_ARGS)( char**, int);
|
||||
|
||||
// auto bdw = bitsdojo_window_configure(BDW_CUSTOM_FRAME | BDW_HIDE_ON_STARTUP);
|
||||
int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
|
||||
@ -26,11 +27,23 @@ int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
|
||||
std::cout << "Failed to get rustdesk_core_main" << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (!rustdesk_core_main())
|
||||
FUNC_RUSTDESK_FREE_ARGS free_c_args =
|
||||
(FUNC_RUSTDESK_FREE_ARGS)GetProcAddress(hInstance, "free_c_args");
|
||||
if (!free_c_args)
|
||||
{
|
||||
std::cout << "Failed to get free_c_args" << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
int args_len = 0;
|
||||
char** c_args = rustdesk_core_main(&args_len);
|
||||
if (!c_args)
|
||||
{
|
||||
std::cout << "Rustdesk core returns false, exiting without launching Flutter app" << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
std::vector<std::string> rust_args(c_args, c_args + args_len);
|
||||
free_c_args(c_args, args_len);
|
||||
|
||||
// Attach to console when present (e.g., 'flutter run') or create a
|
||||
// new console when running with a debugger.
|
||||
@ -48,6 +61,7 @@ int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
|
||||
std::vector<std::string> command_line_arguments =
|
||||
GetCommandLineArguments();
|
||||
|
||||
command_line_arguments.insert(command_line_arguments.end(), rust_args.begin(), rust_args.end());
|
||||
project.set_dart_entrypoint_arguments(std::move(command_line_arguments));
|
||||
|
||||
FlutterWindow window(project);
|
||||
|
@ -1,5 +1,7 @@
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
ffi::CString,
|
||||
os::raw::{c_char, c_int},
|
||||
sync::{Arc, RwLock},
|
||||
};
|
||||
|
||||
@ -24,6 +26,78 @@ lazy_static::lazy_static! {
|
||||
pub static ref GLOBAL_EVENT_STREAM: RwLock<HashMap<String, StreamSink<String>>> = Default::default(); // rust to dart event channel
|
||||
}
|
||||
|
||||
/// FFI for rustdesk core's main entry.
|
||||
/// Return true if the app should continue running with UI(possibly Flutter), false if the app should exit.
|
||||
#[cfg(not(windows))]
|
||||
#[no_mangle]
|
||||
pub extern "C" fn rustdesk_core_main() -> bool {
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
return crate::core_main::core_main().is_some();
|
||||
#[cfg(any(target_os = "android", target_os = "ios"))]
|
||||
false
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
#[no_mangle]
|
||||
pub extern "C" fn rustdesk_core_main(args_len: *mut c_int) -> *mut *mut c_char {
|
||||
unsafe { std::ptr::write(args_len, 0) };
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
{
|
||||
if let Some(args) = crate::core_main::core_main() {
|
||||
return rust_args_to_c_args(args, args_len);
|
||||
}
|
||||
return std::ptr::null_mut() as _;
|
||||
}
|
||||
#[cfg(any(target_os = "android", target_os = "ios"))]
|
||||
return std::ptr::null_mut() as _;
|
||||
}
|
||||
|
||||
// https://gist.github.com/iskakaushik/1c5b8aa75c77479c33c4320913eebef6
|
||||
fn rust_args_to_c_args(args: Vec<String>, outlen: *mut c_int) -> *mut *mut c_char {
|
||||
let mut v = vec![];
|
||||
|
||||
// Let's fill a vector with null-terminated strings
|
||||
for s in args {
|
||||
v.push(CString::new(s).unwrap());
|
||||
}
|
||||
|
||||
// Turning each null-terminated string into a pointer.
|
||||
// `into_raw` takes ownershop, gives us the pointer and does NOT drop the data.
|
||||
let mut out = v.into_iter().map(|s| s.into_raw()).collect::<Vec<_>>();
|
||||
|
||||
// Make sure we're not wasting space.
|
||||
out.shrink_to_fit();
|
||||
assert!(out.len() == out.capacity());
|
||||
|
||||
// Get the pointer to our vector.
|
||||
let len = out.len();
|
||||
let ptr = out.as_mut_ptr();
|
||||
std::mem::forget(out);
|
||||
|
||||
// Let's write back the length the caller can expect
|
||||
unsafe { std::ptr::write(outlen, len as c_int) };
|
||||
|
||||
// Finally return the data
|
||||
ptr
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn free_c_args(ptr: *mut *mut c_char, len: c_int) {
|
||||
let len = len as usize;
|
||||
|
||||
// Get back our vector.
|
||||
// Previously we shrank to fit, so capacity == length.
|
||||
let v = Vec::from_raw_parts(ptr, len, len);
|
||||
|
||||
// Now drop one string at a time.
|
||||
for elem in v {
|
||||
let s = CString::from_raw(elem);
|
||||
std::mem::drop(s);
|
||||
}
|
||||
|
||||
// Afterwards the vector will be dropped and thus freed.
|
||||
}
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
pub struct FlutterHandler {
|
||||
pub event_stream: Arc<RwLock<Option<StreamSink<EventToUI>>>>,
|
||||
|
@ -43,16 +43,6 @@ fn initialize(app_dir: &str) {
|
||||
}
|
||||
}
|
||||
|
||||
/// FFI for rustdesk core's main entry.
|
||||
/// Return true if the app should continue running with UI(possibly Flutter), false if the app should exit.
|
||||
#[no_mangle]
|
||||
pub extern "C" fn rustdesk_core_main() -> bool {
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
return crate::core_main::core_main().is_some();
|
||||
#[cfg(any(target_os = "android", target_os = "ios"))]
|
||||
false
|
||||
}
|
||||
|
||||
pub enum EventToUI {
|
||||
Event(String),
|
||||
Rgba(ZeroCopyBuffer<Vec<u8>>),
|
||||
|
Loading…
Reference in New Issue
Block a user