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 "utils.h"
|
||||||
// #include <bitsdojo_window_windows/bitsdojo_window_plugin.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);
|
// auto bdw = bitsdojo_window_configure(BDW_CUSTOM_FRAME | BDW_HIDE_ON_STARTUP);
|
||||||
int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
|
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;
|
std::cout << "Failed to get rustdesk_core_main" << std::endl;
|
||||||
return EXIT_FAILURE;
|
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;
|
std::cout << "Rustdesk core returns false, exiting without launching Flutter app" << std::endl;
|
||||||
return EXIT_SUCCESS;
|
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
|
// Attach to console when present (e.g., 'flutter run') or create a
|
||||||
// new console when running with a debugger.
|
// 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 =
|
std::vector<std::string> command_line_arguments =
|
||||||
GetCommandLineArguments();
|
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));
|
project.set_dart_entrypoint_arguments(std::move(command_line_arguments));
|
||||||
|
|
||||||
FlutterWindow window(project);
|
FlutterWindow window(project);
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
|
ffi::CString,
|
||||||
|
os::raw::{c_char, c_int},
|
||||||
sync::{Arc, RwLock},
|
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
|
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)]
|
#[derive(Default, Clone)]
|
||||||
pub struct FlutterHandler {
|
pub struct FlutterHandler {
|
||||||
pub event_stream: Arc<RwLock<Option<StreamSink<EventToUI>>>>,
|
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 {
|
pub enum EventToUI {
|
||||||
Event(String),
|
Event(String),
|
||||||
Rgba(ZeroCopyBuffer<Vec<u8>>),
|
Rgba(ZeroCopyBuffer<Vec<u8>>),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user