From e3a7b4614a7a28cec2174fdbf469a525a603e8d8 Mon Sep 17 00:00:00 2001 From: Caelan Sayler Date: Wed, 16 Oct 2024 21:24:28 +0100 Subject: [PATCH] Add bridge code for app builder --- src/lib-cpp/Cargo.toml | 2 +- src/lib-cpp/include/Velopack.h | 27 ++++++++++++- src/lib-cpp/src/bridge.cc | 70 +++++++++++++++++++++++++++++++--- src/lib-cpp/src/bridge.hpp | 7 ++++ src/lib-cpp/src/lib.rs | 52 +++++++++++++------------ 5 files changed, 125 insertions(+), 33 deletions(-) diff --git a/src/lib-cpp/Cargo.toml b/src/lib-cpp/Cargo.toml index 03bb1049..fe9598e3 100644 --- a/src/lib-cpp/Cargo.toml +++ b/src/lib-cpp/Cargo.toml @@ -15,7 +15,7 @@ rust-version.workspace = true [lib] path = "src/lib.rs" -crate-type = ["cdylib", "staticlib"] +crate-type = ["cdylib"] [dependencies] cxx.workspace = true diff --git a/src/lib-cpp/include/Velopack.h b/src/lib-cpp/include/Velopack.h index af59c3cd..bef77691 100644 --- a/src/lib-cpp/include/Velopack.h +++ b/src/lib-cpp/include/Velopack.h @@ -15,6 +15,27 @@ #if defined(VELOPACK_LIBC_EXPORTS) && defined(_WIN32) #define VPKC_EXPORT __declspec(dllexport) #pragma comment(linker, "/EXPORT:vpkc_new_update_manager") +#pragma comment(linker, "/EXPORT:vpkc_get_current_version") +#pragma comment(linker, "/EXPORT:vpkc_get_app_id") +#pragma comment(linker, "/EXPORT:vpkc_is_portable") +#pragma comment(linker, "/EXPORT:vpkc_update_pending_restart") +#pragma comment(linker, "/EXPORT:vpkc_download_updates") +#pragma comment(linker, "/EXPORT:vpkc_wait_exit_then_apply_update") +#pragma comment(linker, "/EXPORT:vpkc_app_set_auto_apply_on_startup") +#pragma comment(linker, "/EXPORT:vpkc_app_set_args") +#pragma comment(linker, "/EXPORT:vpkc_app_set_locator") +#pragma comment(linker, "/EXPORT:vpkc_app_set_hook_after_install") +#pragma comment(linker, "/EXPORT:vpkc_app_set_hook_before_uninstall") +#pragma comment(linker, "/EXPORT:vpkc_app_set_hook_before_update") +#pragma comment(linker, "/EXPORT:vpkc_app_set_hook_after_update") +#pragma comment(linker, "/EXPORT:vpkc_app_set_hook_first_run") +#pragma comment(linker, "/EXPORT:vpkc_app_set_hook_restarted") +#pragma comment(linker, "/EXPORT:vpkc_app_run") +#pragma comment(linker, "/EXPORT:vpkc_get_last_error") +#pragma comment(linker, "/EXPORT:vpkc_set_log") +#pragma comment(linker, "/EXPORT:vpkc_free_update_manager") +#pragma comment(linker, "/EXPORT:vpkc_free_update_info") +#pragma comment(linker, "/EXPORT:vpkc_free_asset") #elif defined(VELOPACK_LIBC_EXPORTS) && !defined(_WIN32) #define VPKC_EXPORT __attribute__((visibility("default"))) __attribute__((used)) #else @@ -69,6 +90,7 @@ typedef struct { bool IsDowngrade; } vpkc_update_info_t; +// Update Manager VPKC_EXPORT bool VPKC_CALL vpkc_new_update_manager(const char* pszUrlOrString, const vpkc_options_t* pOptions, const vpkc_locator_t* locator, vpkc_update_manager_t* pManager); VPKC_EXPORT size_t VPKC_CALL vpkc_get_current_version(vpkc_update_manager_t* pManager, char* pszVersion, size_t cVersion); VPKC_EXPORT size_t VPKC_CALL vpkc_get_app_id(vpkc_update_manager_t* pManager, char* pszId, size_t cId); @@ -78,6 +100,7 @@ VPKC_EXPORT vpkc_update_check_t VPKC_CALL vpkc_check_for_updates(vpkc_update_man VPKC_EXPORT bool VPKC_CALL vpkc_download_updates(vpkc_update_manager_t* pManager, const vpkc_update_info_t* pUpdate, vpkc_progress_callback_t cbProgress); VPKC_EXPORT bool VPKC_CALL vpkc_wait_exit_then_apply_update(vpkc_update_manager_t* pManager, vpkc_asset_t* pAsset, bool bSilent, bool bRestart, char** pRestartArgs, size_t cRestartArgs); +// VelopackApp VPKC_EXPORT void VPKC_CALL vpkc_app_set_auto_apply_on_startup(bool bAutoApply); VPKC_EXPORT void VPKC_CALL vpkc_app_set_args(char** pArgs, size_t cArgs); VPKC_EXPORT void VPKC_CALL vpkc_app_set_locator(vpkc_locator_t* pLocator); @@ -89,6 +112,7 @@ VPKC_EXPORT void VPKC_CALL vpkc_app_set_hook_first_run(vpkc_hook_callback_t cbFi VPKC_EXPORT void VPKC_CALL vpkc_app_set_hook_restarted(vpkc_hook_callback_t cbRestarted); VPKC_EXPORT void VPKC_CALL vpkc_app_run(); +// Misc functions VPKC_EXPORT size_t VPKC_CALL vpkc_get_last_error(char* pszError, size_t cError); VPKC_EXPORT void VPKC_CALL vpkc_set_log(vpkc_log_callback_t cbLog); VPKC_EXPORT void VPKC_CALL vpkc_free_update_manager(vpkc_update_manager_t* pManager); @@ -336,7 +360,8 @@ namespace Velopack { strcpy_s(pRestartArgs[i], restartArgs[i].size() + 1, restartArgs[i].c_str()); } - bool result = vpkc_wait_exit_then_apply_update(&m_pManager, &to_vpkc(asset), silent, restart, pRestartArgs, restartArgs.size()); + vpkc_asset_t vpkc_asset = to_vpkc(asset); + bool result = vpkc_wait_exit_then_apply_update(&m_pManager, &vpkc_asset, silent, restart, pRestartArgs, restartArgs.size()); // Free all the memory for (size_t i = 0; i < restartArgs.size(); i++) { diff --git a/src/lib-cpp/src/bridge.cc b/src/lib-cpp/src/bridge.cc index 3c3cf4b3..4708beed 100644 --- a/src/lib-cpp/src/bridge.cc +++ b/src/lib-cpp/src/bridge.cc @@ -1,7 +1,65 @@ -#include "velopack_libc/include/Velopack.h" -#include "velopack_libc/src/bridge.hpp" +#include "velopack_libc/src/lib.rs.h" -VPKC_EXPORT bool VPKC_CALL vpkc_new_update_manager(const char* pszUrlOrString, const vpkc_options_t* pOptions, const vpkc_locator_t* locator, vpkc_update_manager_t* pManager) -{ - return 0; -} \ No newline at end of file +// Update Manager +VPKC_EXPORT bool VPKC_CALL vpkc_new_update_manager(const char* pszUrlOrString, const vpkc_options_t* pOptions, const vpkc_locator_t* locator, vpkc_update_manager_t* pManager); +VPKC_EXPORT size_t VPKC_CALL vpkc_get_current_version(vpkc_update_manager_t* pManager, char* pszVersion, size_t cVersion); +VPKC_EXPORT size_t VPKC_CALL vpkc_get_app_id(vpkc_update_manager_t* pManager, char* pszId, size_t cId); +VPKC_EXPORT bool VPKC_CALL vpkc_is_portable(vpkc_update_manager_t* pManager); +VPKC_EXPORT bool VPKC_CALL vpkc_update_pending_restart(vpkc_update_manager_t* pManager, vpkc_asset_t* pAsset); +VPKC_EXPORT vpkc_update_check_t VPKC_CALL vpkc_check_for_updates(vpkc_update_manager_t* pManager, vpkc_update_info_t* pUpdate); +VPKC_EXPORT bool VPKC_CALL vpkc_download_updates(vpkc_update_manager_t* pManager, const vpkc_update_info_t* pUpdate, vpkc_progress_callback_t cbProgress); +VPKC_EXPORT bool VPKC_CALL vpkc_wait_exit_then_apply_update(vpkc_update_manager_t* pManager, vpkc_asset_t* pAsset, bool bSilent, bool bRestart, char** pRestartArgs, size_t cRestartArgs); + +// VelopackApp +bool autoApply = true; +StringArrayOption args{}; +LocatorConfigOption locator{}; +HookCallbackManager hooks{}; + +VPKC_EXPORT void VPKC_CALL vpkc_app_set_auto_apply_on_startup(bool bAutoApply) { + autoApply = bAutoApply; +} +VPKC_EXPORT void VPKC_CALL vpkc_app_set_args(char** pArgs, size_t cArgs) { + args.has_data = true; + args.data.clear(); + for (size_t i = 0; i < cArgs; i++) { + args.data.push_back(pArgs[i]); + } +} +VPKC_EXPORT void VPKC_CALL vpkc_app_set_locator(vpkc_locator_t* pLocator) { + locator.has_data = true; + locator.data.RootAppDir = pLocator->RootAppDir; + locator.data.UpdateExePath = pLocator->UpdateExePath; + locator.data.PackagesDir = pLocator->PackagesDir; + locator.data.ManifestPath = pLocator->ManifestPath; + locator.data.CurrentBinaryDir = pLocator->CurrentBinaryDir; + locator.data.IsPortable = pLocator->IsPortable; +} +VPKC_EXPORT void VPKC_CALL vpkc_app_set_hook_after_install(vpkc_hook_callback_t cbAfterInstall) { + hooks.after_install = cbAfterInstall; +} +VPKC_EXPORT void VPKC_CALL vpkc_app_set_hook_before_uninstall(vpkc_hook_callback_t cbBeforeUninstall) { + hooks.before_uninstall = cbBeforeUninstall; +} +VPKC_EXPORT void VPKC_CALL vpkc_app_set_hook_before_update(vpkc_hook_callback_t cbBeforeUpdate) { + hooks.before_update = cbBeforeUpdate; +} +VPKC_EXPORT void VPKC_CALL vpkc_app_set_hook_after_update(vpkc_hook_callback_t cbAfterUpdate) { + hooks.after_update = cbAfterUpdate; +} +VPKC_EXPORT void VPKC_CALL vpkc_app_set_hook_first_run(vpkc_hook_callback_t cbFirstRun) { + hooks.first_run = cbFirstRun; +} +VPKC_EXPORT void VPKC_CALL vpkc_app_set_hook_restarted(vpkc_hook_callback_t cbRestarted) { + hooks.restarted = cbRestarted; +} +VPKC_EXPORT void VPKC_CALL vpkc_app_run() { + bridge_appbuilder_run(hooks, args, locator, autoApply); +} + +// Misc functions +VPKC_EXPORT size_t VPKC_CALL vpkc_get_last_error(char* pszError, size_t cError); +VPKC_EXPORT void VPKC_CALL vpkc_set_log(vpkc_log_callback_t cbLog); +VPKC_EXPORT void VPKC_CALL vpkc_free_update_manager(vpkc_update_manager_t* pManager); +VPKC_EXPORT void VPKC_CALL vpkc_free_update_info(vpkc_update_info_t* pManager); +VPKC_EXPORT void VPKC_CALL vpkc_free_asset(vpkc_asset_t* pManager); \ No newline at end of file diff --git a/src/lib-cpp/src/bridge.hpp b/src/lib-cpp/src/bridge.hpp index a54ceaa0..2e1fcf78 100644 --- a/src/lib-cpp/src/bridge.hpp +++ b/src/lib-cpp/src/bridge.hpp @@ -3,6 +3,13 @@ #include "velopack_libc/include/Velopack.h" struct HookCallbackManager { + vpkc_hook_callback_t after_install = nullptr; + vpkc_hook_callback_t before_uninstall = nullptr; + vpkc_hook_callback_t before_update = nullptr; + vpkc_hook_callback_t after_update = nullptr; + vpkc_hook_callback_t first_run = nullptr; + vpkc_hook_callback_t restarted = nullptr; + void install_hook(::rust::String app_version) const {}; void update_hook(::rust::String app_version) const {}; void obsolete_hook(::rust::String app_version) const {}; diff --git a/src/lib-cpp/src/lib.rs b/src/lib-cpp/src/lib.rs index 2e6a45d7..9259969b 100644 --- a/src/lib-cpp/src/lib.rs +++ b/src/lib-cpp/src/lib.rs @@ -48,30 +48,30 @@ mod ffi { pub has_data: bool, } - pub struct LocatorConfigDto<'a> { - pub RootAppDir: &'a CxxString, - pub UpdateExePath: &'a CxxString, - pub PackagesDir: &'a CxxString, - pub ManifestPath: &'a CxxString, - pub CurrentBinaryDir: &'a CxxString, + pub struct LocatorConfigDto { + pub RootAppDir: String, + pub UpdateExePath: String, + pub PackagesDir: String, + pub ManifestPath: String, + pub CurrentBinaryDir: String, pub IsPortable: bool, } - pub struct LocatorConfigOption<'a> { - pub data: LocatorConfigDto<'a>, + pub struct LocatorConfigOption { + pub data: LocatorConfigDto, pub has_data: bool, } - pub struct UpdateOptionsDto<'a> { + pub struct UpdateOptionsDto { pub AllowVersionDowngrade: bool, - pub ExplicitChannel: &'a CxxString, + pub ExplicitChannel: String, } pub struct StringArrayOption { pub data: Vec, pub has_data: bool, } - + // C++ types and signatures exposed to Rust. unsafe extern "C++" { include!("velopack_libc/include/Velopack.h"); @@ -100,7 +100,7 @@ mod ffi { fn bridge_check_for_updates(manager: &UpdateManagerOpaque) -> Result; fn bridge_download_update(manager: &UpdateManagerOpaque, to_download: UpdateInfoDto, progress: UniquePtr) -> Result<()>; fn bridge_wait_exit_then_apply_update(manager: &UpdateManagerOpaque, to_download: AssetDto, silent: bool, restart: bool, restart_args: Vec) -> Result<()>; - fn bridge_appbuilder_run(cb: UniquePtr, custom_args: StringArrayOption, locator: LocatorConfigOption, auto_apply: bool); + unsafe fn bridge_appbuilder_run(cb: &HookCallbackManager, custom_args: &StringArrayOption, locator: &LocatorConfigOption, auto_apply: bool); fn bridge_set_logger_callback(cb: UniquePtr); } } @@ -112,17 +112,17 @@ struct UpdateManagerOpaque { fn to_locator_config(locator: &ffi::LocatorConfigDto) -> VelopackLocatorConfig { VelopackLocatorConfig { - RootAppDir: PathBuf::from(locator.RootAppDir.to_string_lossy().to_string()), - UpdateExePath: PathBuf::from(locator.UpdateExePath.to_string_lossy().to_string()), - PackagesDir: PathBuf::from(locator.PackagesDir.to_string_lossy().to_string()), - ManifestPath: PathBuf::from(locator.ManifestPath.to_string_lossy().to_string()), - CurrentBinaryDir: PathBuf::from(locator.CurrentBinaryDir.to_string_lossy().to_string()), + RootAppDir: PathBuf::from(locator.RootAppDir.clone()), + UpdateExePath: PathBuf::from(locator.UpdateExePath.clone()), + PackagesDir: PathBuf::from(locator.PackagesDir.clone()), + ManifestPath: PathBuf::from(locator.ManifestPath.clone()), + CurrentBinaryDir: PathBuf::from(locator.CurrentBinaryDir.clone()), IsPortable: locator.IsPortable, } } fn to_update_options(options: &ffi::UpdateOptionsDto) -> VelopackUpdateOptions { - let channel = options.ExplicitChannel.to_string_lossy().to_string(); + let channel = options.ExplicitChannel.clone(); VelopackUpdateOptions { AllowVersionDowngrade: options.AllowVersionDowngrade, ExplicitChannel: if channel.is_empty() { None } else { Some(channel) }, @@ -267,15 +267,16 @@ fn bridge_wait_exit_then_apply_update(manager: &UpdateManagerOpaque, to_download Ok(()) } -fn bridge_appbuilder_run(cb: cxx::UniquePtr, custom_args: ffi::StringArrayOption, locator: ffi::LocatorConfigOption, auto_apply: bool) { +fn bridge_appbuilder_run(cb: &ffi::HookCallbackManager, custom_args: &ffi::StringArrayOption, locator: &ffi::LocatorConfigOption, auto_apply: bool) { let mut app = VelopackApp::build() + .set_auto_apply_on_startup(auto_apply) .on_first_run(|v| cb.firstrun_hook(v.to_string())) - .on_restarted(|v| cb.restarted_hook(v.to_string())) - .set_auto_apply_on_startup(auto_apply); + .on_restarted(|v| cb.restarted_hook(v.to_string())); #[cfg(windows)] { - app = app.on_after_install_fast_callback(|v| cb.install_hook(v.to_string())) + app = app + .on_after_install_fast_callback(|v| cb.install_hook(v.to_string())) .on_after_update_fast_callback(|v| cb.update_hook(v.to_string())) .on_before_update_fast_callback(|v| cb.obsolete_hook(v.to_string())) .on_before_uninstall_fast_callback(|v| cb.uninstall_hook(v.to_string())); @@ -286,13 +287,14 @@ fn bridge_appbuilder_run(cb: cxx::UniquePtr, custom_ar } if custom_args.has_data { - app = app.set_args(custom_args.data); + app = app.set_args(custom_args.data.clone()); } app.run(); } struct LoggerImpl {} + static LOGGER: LoggerImpl = LoggerImpl {}; impl Log for LoggerImpl { @@ -314,7 +316,7 @@ impl Log for LoggerImpl { Level::Debug => "debug", Level::Trace => "trace", }.to_string(); - + if let Some(cb) = get_logger() { if let Some(cb) = unsafe { cb.as_mut() } { cb.log(level, text); @@ -345,7 +347,7 @@ fn get_logger() -> Option<*mut ffi::LoggerCallbackManager> { fn bridge_set_logger_callback(cb: cxx::UniquePtr) { let _ = log::set_logger(&LOGGER); log::set_max_level(log::LevelFilter::Trace); - + let cb = cb.into_raw(); store_logger(cb); } \ No newline at end of file