From 5613696b897b8476b4782c501ababff7f7eed6e0 Mon Sep 17 00:00:00 2001 From: christoph_xd Date: Fri, 14 Nov 2025 22:18:15 +0100 Subject: [PATCH] rework lib --- Cargo.lock | 25 ++ open_wrapper/Cargo.toml | 5 +- open_wrapper/build.rs | 20 - open_wrapper/src/lib.rs | 971 +++++++++++++++++++++++++++++++++------- src/main.rs | 118 +---- 5 files changed, 852 insertions(+), 287 deletions(-) delete mode 100644 open_wrapper/build.rs diff --git a/Cargo.lock b/Cargo.lock index 14fc6c3..70b0134 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,12 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + [[package]] name = "connect_demo" version = "0.0.0" @@ -9,6 +15,25 @@ dependencies = [ "open_wrapper", ] +[[package]] +name = "libloading" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "754ca22de805bb5744484a5b151a9e1a8e837d5dc232c2d7d8c2e3492edc8b60" +dependencies = [ + "cfg-if", + "windows-link", +] + [[package]] name = "open_wrapper" version = "0.1.0" +dependencies = [ + "libloading", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" diff --git a/open_wrapper/Cargo.toml b/open_wrapper/Cargo.toml index 3af9bf5..97c3eb0 100644 --- a/open_wrapper/Cargo.toml +++ b/open_wrapper/Cargo.toml @@ -2,4 +2,7 @@ name = "open_wrapper" version = "0.1.0" edition.workspace = true -build = "build.rs" + + +[dependencies] +libloading = "0.9.0" \ No newline at end of file diff --git a/open_wrapper/build.rs b/open_wrapper/build.rs deleted file mode 100644 index e937b4c..0000000 --- a/open_wrapper/build.rs +++ /dev/null @@ -1,20 +0,0 @@ -use std::{env, path::PathBuf}; - -fn main() { - let manifest_dir = - PathBuf::from(env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR must be set")); - let lib_dir = manifest_dir.join("lib"); - - println!("cargo:rustc-link-search=native={}", lib_dir.display()); - println!("cargo:rerun-if-changed=build.rs"); - - let open_lib = lib_dir.join("open.lib"); - if open_lib.exists() { - println!("cargo:rerun-if-changed={}", open_lib.display()); - } else { - println!( - "cargo:warning=Expected to find open.lib in '{}'. Copy the vendor import library there.", - lib_dir.display() - ); - } -} diff --git a/open_wrapper/src/lib.rs b/open_wrapper/src/lib.rs index b7a0c44..41a0be9 100644 --- a/open_wrapper/src/lib.rs +++ b/open_wrapper/src/lib.rs @@ -1,4 +1,6 @@ #![allow(non_snake_case)] +use std::path::Path; +use libloading::{ Symbol, Library }; /// Pointer to a UTF-16 string (wide char) terminated with `0`. pub type PCWSTR = *const u16; @@ -246,300 +248,933 @@ pub enum OpenProjectStates { Error = 10, } -#[link(name = "open")] -extern "C" { - #[link_name = "startApplication"] - pub fn start_application(str_profile_file_name: PCWSTR) -> OpenReturnCodes; +// Helper type aliases for function signatures +type StartApplicationFn = unsafe extern "C" fn(PCWSTR) -> OpenReturnCodes; +type StopApplicationFn = unsafe extern "C" fn() -> OpenReturnCodes; +type ConnectFn = unsafe extern "C" fn() -> OpenReturnCodes; +type DisconnectFn = unsafe extern "C" fn() -> OpenReturnCodes; +type OpenProjectFn = unsafe extern "C" fn(PCWSTR) -> OpenReturnCodes; +type CreateProjectFn = unsafe extern "C" fn(PCWSTR, PCWSTR) -> OpenReturnCodes; +type CreateProjectWithScalingFn = unsafe extern "C" fn(PCWSTR, PCWSTR, PCWSTR) -> OpenReturnCodes; +type CreateProjectWithScalingNcuNumberFn = unsafe extern "C" fn( + PCWSTR, + PCWSTR, + PCWSTR, + u32 +) -> OpenReturnCodes; +type SaveProjectFn = unsafe extern "C" fn() -> OpenReturnCodes; +type CloseProjectFn = unsafe extern "C" fn() -> OpenReturnCodes; +type BootControllerFn = unsafe extern "C" fn() -> OpenReturnCodes; +type ShutdownControllerFn = unsafe extern "C" fn() -> OpenReturnCodes; +type ResetControllerFn = unsafe extern "C" fn() -> OpenReturnCodes; +type RegisterForEventsFn = unsafe extern "C" fn( + u32, + *const OpenEventMaskDefinition +) -> OpenReturnCodes; +type UnregisterEventsFn = unsafe extern "C" fn() -> OpenReturnCodes; +type WaitForEventsFn = unsafe extern "C" fn() -> OpenReturnCodes; +type ContinueSimulationFn = unsafe extern "C" fn() -> OpenReturnCodes; +type GetDictionaryIdFn = unsafe extern "C" fn(PCWSTR, *mut u32) -> OpenReturnCodes; +type RegisterWatchFn = unsafe extern "C" fn(u32, *const u32) -> OpenReturnCodes; +type UnregisterWatchFn = unsafe extern "C" fn() -> OpenReturnCodes; +type GetDictionaryElementTypeFn = unsafe extern "C" fn(u32, *mut u8) -> OpenReturnCodes; +type ReadUnsignedInteger64BitArrayFn = unsafe extern "C" fn(u32, u32, *mut u64) -> OpenReturnCodes; +type ReadSignedInteger32BitArrayFn = unsafe extern "C" fn(u32, u32, *mut i32) -> OpenReturnCodes; +type ReadUnsignedInteger32BitArrayFn = unsafe extern "C" fn(u32, u32, *mut u32) -> OpenReturnCodes; +type ReadUnsignedInteger16BitArrayFn = unsafe extern "C" fn(u32, u32, *mut u16) -> OpenReturnCodes; +type ReadUnsignedInteger8BitArrayFn = unsafe extern "C" fn(u32, u32, *mut u8) -> OpenReturnCodes; +type ReadBoolArrayFn = unsafe extern "C" fn(u32, u32, *mut bool) -> OpenReturnCodes; +type ReadDoubleArrayFn = unsafe extern "C" fn(u32, u32, *mut f64) -> OpenReturnCodes; +type ReadStringFn = unsafe extern "C" fn(u32, u32, PWSTR) -> OpenReturnCodes; +type ReadStringArrayFn = unsafe extern "C" fn(u32, u32, u32, PPWSTR) -> OpenReturnCodes; +type ReadUnsignedInteger16BitFn = unsafe extern "C" fn(u32, *mut u16) -> OpenReturnCodes; +type ReadSignedInteger16BitFn = unsafe extern "C" fn(u32, *mut i16) -> OpenReturnCodes; +type ReadUnsignedInteger32BitFn = unsafe extern "C" fn(u32, *mut u32) -> OpenReturnCodes; +type ReadSignedInteger32BitFn = unsafe extern "C" fn(u32, *mut i32) -> OpenReturnCodes; +type ReadUnsignedInteger64BitFn = unsafe extern "C" fn(u32, *mut u64) -> OpenReturnCodes; +type ReadSignedInteger64BitFn = unsafe extern "C" fn(u32, *mut i64) -> OpenReturnCodes; +type GetNumArrayElementsFn = unsafe extern "C" fn(u32, *mut u32) -> OpenReturnCodes; +type ReadBitFn = unsafe extern "C" fn(u32, *mut Bool32) -> OpenReturnCodes; +type ReadBoolFn = unsafe extern "C" fn(u32, *mut Bool32) -> OpenReturnCodes; +type ReadByteFn = unsafe extern "C" fn(u32, *mut u8) -> OpenReturnCodes; +type ReadDoubleFn = unsafe extern "C" fn(u32, *mut f64) -> OpenReturnCodes; +type ReadWordFn = unsafe extern "C" fn(u32, *mut u16) -> OpenReturnCodes; +type ReadDoubleWordFn = unsafe extern "C" fn(u32, *mut u32) -> OpenReturnCodes; +type ReadLongWordFn = unsafe extern "C" fn(u32, *mut u64) -> OpenReturnCodes; +type ReadNextEventFn = unsafe extern "C" fn(*mut u64) -> OpenReturnCodes; +type ReadNextEventWithNcuIndexFn = unsafe extern "C" fn(*mut u64, *mut i32) -> OpenReturnCodes; +type WriteBitFn = unsafe extern "C" fn(u32, Bool32) -> OpenReturnCodes; +type WriteBoolFn = unsafe extern "C" fn(u32, Bool32) -> OpenReturnCodes; +type WriteByteFn = unsafe extern "C" fn(u32, u8) -> OpenReturnCodes; +type WriteDoubleFn = unsafe extern "C" fn(u32, f64) -> OpenReturnCodes; +type WriteWordFn = unsafe extern "C" fn(u32, u16) -> OpenReturnCodes; +type WriteDoubleWordFn = unsafe extern "C" fn(u32, u32) -> OpenReturnCodes; +type WriteLongWordFn = unsafe extern "C" fn(u32, u64) -> OpenReturnCodes; +type WriteBoolArrayFn = unsafe extern "C" fn(u32, u32, *const bool) -> OpenReturnCodes; +type GetSimulationSpeedFn = unsafe extern "C" fn(*mut u32) -> OpenReturnCodes; +type SetSimulationSpeedFn = unsafe extern "C" fn(u32) -> OpenReturnCodes; +type GetCardPathFn = unsafe extern "C" fn(u32, PWSTR) -> OpenReturnCodes; +type GetCardPathsFn = unsafe extern "C" fn(u32, u32, PPWSTR) -> OpenReturnCodes; +type GetFileFn = unsafe extern "C" fn(PCWSTR, PCWSTR) -> OpenReturnCodes; +type PutFileFn = unsafe extern "C" fn(PCWSTR, PCWSTR) -> OpenReturnCodes; +type SelectFileFn = unsafe extern "C" fn(PCWSTR, PCWSTR) -> OpenReturnCodes; +type DeleteFileFn = unsafe extern "C" fn(PCWSTR) -> OpenReturnCodes; +type DeleteDirectoryFn = unsafe extern "C" fn(PCWSTR) -> OpenReturnCodes; +type CreateDirectoryFn = unsafe extern "C" fn(PCWSTR) -> OpenReturnCodes; +type ListDirectoryFn = unsafe extern "C" fn(PCWSTR, PCWSTR) -> OpenReturnCodes; +type GetVersionInformationFn = unsafe extern "C" fn(PCWSTR) -> OpenReturnCodes; +type GetProjectInformationFn = unsafe extern "C" fn(PCWSTR, PCWSTR) -> OpenReturnCodes; +type GetCurrentProjectInformationFn = unsafe extern "C" fn(PCWSTR) -> OpenReturnCodes; +type GetCurrentProjectStateFn = unsafe extern "C" fn(*mut OpenProjectStates) -> OpenReturnCodes; +type ImportProjectSettingsFn = unsafe extern "C" fn(PCWSTR, PCWSTR) -> OpenReturnCodes; +type ExportProjectSettingsFn = unsafe extern "C" fn(PCWSTR) -> OpenReturnCodes; +type WriteUnsignedInteger8BitArrayFn = unsafe extern "C" fn(u32, u32, *const u8) -> OpenReturnCodes; +type GetNumberOfNcusFn = unsafe extern "C" fn(*mut u32) -> OpenReturnCodes; - #[link_name = "stopApplication"] - pub fn stop_application() -> OpenReturnCodes; +fn load_symbol(lib: &'static Library, name: &[u8]) -> Result { + unsafe { + let symbol: Symbol = lib.get(name)?; + Ok(*symbol) + } +} - #[link_name = "connect"] - pub fn connect() -> OpenReturnCodes; +pub struct OpenApi { + _lib: &'static Library, // keep leaked library alive so function pointers remain valid + start_application: StartApplicationFn, + stop_application: StopApplicationFn, + connect: ConnectFn, + disconnect: DisconnectFn, + open_project: OpenProjectFn, + create_project: CreateProjectFn, + create_project_with_scaling: CreateProjectWithScalingFn, + create_project_with_scaling_ncu_number: CreateProjectWithScalingNcuNumberFn, + save_project: SaveProjectFn, + close_project: CloseProjectFn, + boot_controller: BootControllerFn, + shutdown_controller: ShutdownControllerFn, + reset_controller: ResetControllerFn, + register_for_events: RegisterForEventsFn, + unregister_events: UnregisterEventsFn, + wait_for_events: WaitForEventsFn, + continue_simulation: ContinueSimulationFn, + get_dictionary_id: GetDictionaryIdFn, + register_watch: RegisterWatchFn, + unregister_watch: UnregisterWatchFn, + get_dictionary_element_type: GetDictionaryElementTypeFn, + read_unsigned_integer_64_bit_array: ReadUnsignedInteger64BitArrayFn, + read_signed_integer_32_bit_array: ReadSignedInteger32BitArrayFn, + read_unsigned_integer_32_bit_array: ReadUnsignedInteger32BitArrayFn, + read_unsigned_integer_16_bit_array: ReadUnsignedInteger16BitArrayFn, + read_unsigned_integer_8_bit_array: ReadUnsignedInteger8BitArrayFn, + read_bool_array: ReadBoolArrayFn, + read_double_array: ReadDoubleArrayFn, + read_string: ReadStringFn, + read_string_array: ReadStringArrayFn, + read_unsigned_integer_16_bit: ReadUnsignedInteger16BitFn, + read_signed_integer_16_bit: ReadSignedInteger16BitFn, + read_unsigned_integer_32_bit: ReadUnsignedInteger32BitFn, + read_signed_integer_32_bit: ReadSignedInteger32BitFn, + read_unsigned_integer_64_bit: ReadUnsignedInteger64BitFn, + read_signed_integer_64_bit: ReadSignedInteger64BitFn, + get_num_array_elements: GetNumArrayElementsFn, + read_bit: ReadBitFn, + read_bool: ReadBoolFn, + read_byte: ReadByteFn, + read_double: ReadDoubleFn, + read_word: ReadWordFn, + read_double_word: ReadDoubleWordFn, + read_long_word: ReadLongWordFn, + read_next_event: ReadNextEventFn, + read_next_event_with_ncu_index: ReadNextEventWithNcuIndexFn, + write_bit: WriteBitFn, + write_bool: WriteBoolFn, + write_byte: WriteByteFn, + write_double: WriteDoubleFn, + write_word: WriteWordFn, + write_double_word: WriteDoubleWordFn, + write_long_word: WriteLongWordFn, + write_bool_array: WriteBoolArrayFn, + get_simulation_speed: GetSimulationSpeedFn, + set_simulation_speed: SetSimulationSpeedFn, + get_card_path: GetCardPathFn, + get_card_paths: GetCardPathsFn, + get_file: GetFileFn, + put_file: PutFileFn, + select_file: SelectFileFn, + delete_file: DeleteFileFn, + delete_directory: DeleteDirectoryFn, + create_directory: CreateDirectoryFn, + list_directory: ListDirectoryFn, + get_version_information: GetVersionInformationFn, + get_project_information: GetProjectInformationFn, + get_current_project_information: GetCurrentProjectInformationFn, + get_current_project_state: GetCurrentProjectStateFn, + import_project_settings: ImportProjectSettingsFn, + export_project_settings: ExportProjectSettingsFn, + write_unsigned_integer_8_bit_array: WriteUnsignedInteger8BitArrayFn, + get_number_of_ncus: GetNumberOfNcusFn, +} - #[link_name = "disconnect"] - pub fn disconnect() -> OpenReturnCodes; +impl OpenApi { + /// Load DLL from a path, binding required symbols. + pub unsafe fn load>(path: P) -> Result { + // Load the DLL + let lib = Library::new(path.as_ref())?; + // Extend the library's lifetime to 'static by leaking it. + // (Alternatively: design OpenApi with lifetimes and avoid leaking.) + let lib: &'static Library = Box::leak(Box::new(lib)); - #[link_name = "openProject"] - pub fn open_project(str_file_name: PCWSTR) -> OpenReturnCodes; + let start_application = load_symbol::(lib, b"startApplication")?; + let stop_application = load_symbol::(lib, b"stopApplication")?; + let connect = load_symbol::(lib, b"connect")?; + let disconnect = load_symbol::(lib, b"disconnect")?; + let open_project = load_symbol::(lib, b"openProject")?; + let create_project = load_symbol::(lib, b"createProject")?; + let create_project_with_scaling = load_symbol::( + lib, + b"createProjectWithScaling" + )?; + let create_project_with_scaling_ncu_number = + load_symbol::( + lib, + b"createProjectWithScalingNCUNumber" + )?; + let save_project = load_symbol::(lib, b"saveProject")?; + let close_project = load_symbol::(lib, b"closeProject")?; + let boot_controller = load_symbol::(lib, b"bootController")?; + let shutdown_controller = load_symbol::(lib, b"shutdownController")?; + let reset_controller = load_symbol::(lib, b"resetController")?; + let register_for_events = load_symbol::(lib, b"registerForEvents")?; + let unregister_events = load_symbol::(lib, b"unregisterEvents")?; + let wait_for_events = load_symbol::(lib, b"waitForEvents")?; + let continue_simulation = load_symbol::(lib, b"continueSimulation")?; + let get_dictionary_id = load_symbol::(lib, b"getDictionaryId")?; + let register_watch = load_symbol::(lib, b"registerWatch")?; + let unregister_watch = load_symbol::(lib, b"unregisterWatch")?; + let get_dictionary_element_type = load_symbol::( + lib, + b"getDictionaryElementType" + )?; + let read_unsigned_integer_64_bit_array = load_symbol::( + lib, + b"readUnsignedInteger64BitArray" + )?; + let read_signed_integer_32_bit_array = load_symbol::( + lib, + b"readSignedInteger32BitArray" + )?; + let read_unsigned_integer_32_bit_array = load_symbol::( + lib, + b"readUnsignedInteger32BitArray" + )?; + let read_unsigned_integer_16_bit_array = load_symbol::( + lib, + b"readUnsignedInteger16BitArray" + )?; + let read_unsigned_integer_8_bit_array = load_symbol::( + lib, + b"readUnsignedInteger8BitArray" + )?; + let read_bool_array = load_symbol::(lib, b"readBoolArray")?; + let read_double_array = load_symbol::(lib, b"readDoubleArray")?; + let read_string = load_symbol::(lib, b"readString")?; + let read_string_array = load_symbol::(lib, b"readStringArray")?; + let read_unsigned_integer_16_bit = load_symbol::( + lib, + b"readUnsignedInteger16Bit" + )?; + let read_signed_integer_16_bit = load_symbol::( + lib, + b"readSignedInteger16Bit" + )?; + let read_unsigned_integer_32_bit = load_symbol::( + lib, + b"readUnsignedInteger32Bit" + )?; + let read_signed_integer_32_bit = load_symbol::( + lib, + b"readSignedInteger32Bit" + )?; + let read_unsigned_integer_64_bit = load_symbol::( + lib, + b"readUnsignedInteger64Bit" + )?; + let read_signed_integer_64_bit = load_symbol::( + lib, + b"readSignedInteger64Bit" + )?; + let get_num_array_elements = load_symbol::( + lib, + b"getNumArrayElements" + )?; + let read_bit = load_symbol::(lib, b"readBit")?; + let read_bool = load_symbol::(lib, b"readBool")?; + let read_byte = load_symbol::(lib, b"readByte")?; + let read_double = load_symbol::(lib, b"readDouble")?; + let read_word = load_symbol::(lib, b"readWord")?; + let read_double_word = load_symbol::(lib, b"readDoubleWord")?; + let read_long_word = load_symbol::(lib, b"readLongWord")?; + let read_next_event = load_symbol::(lib, b"readNextEvent")?; + let read_next_event_with_ncu_index = load_symbol::( + lib, + b"readNextEventWithNcuIndex" + )?; + let write_bit = load_symbol::(lib, b"writeBit")?; + let write_bool = load_symbol::(lib, b"writeBool")?; + let write_byte = load_symbol::(lib, b"writeByte")?; + let write_double = load_symbol::(lib, b"writeDouble")?; + let write_word = load_symbol::(lib, b"writeWord")?; + let write_double_word = load_symbol::(lib, b"writeDoubleWord")?; + let write_long_word = load_symbol::(lib, b"writeLongWord")?; + let write_bool_array = load_symbol::(lib, b"writeBoolArray")?; + let get_simulation_speed = load_symbol::(lib, b"getSimulationSpeed")?; + let set_simulation_speed = load_symbol::(lib, b"setSimulationSpeed")?; + let get_card_path = load_symbol::(lib, b"getCardPath")?; + let get_card_paths = load_symbol::(lib, b"getCardPaths")?; + let get_file = load_symbol::(lib, b"getFile")?; + let put_file = load_symbol::(lib, b"putFile")?; + let select_file = load_symbol::(lib, b"selectFile")?; + let delete_file = load_symbol::(lib, b"deleteFile")?; + let delete_directory = load_symbol::(lib, b"deleteDirectory")?; + let create_directory = load_symbol::(lib, b"createDirectory")?; + let list_directory = load_symbol::(lib, b"listDirectory")?; + let get_version_information = load_symbol::( + lib, + b"getVersionInformation" + )?; + let get_project_information = load_symbol::( + lib, + b"getProjectInformation" + )?; + let get_current_project_information = load_symbol::( + lib, + b"getCurrentProjectInformation" + )?; + let get_current_project_state = load_symbol::( + lib, + b"getCurrentProjectState" + )?; + let import_project_settings = load_symbol::( + lib, + b"importProjectSettings" + )?; + let export_project_settings = load_symbol::( + lib, + b"exportProjectSettings" + )?; + let write_unsigned_integer_8_bit_array = load_symbol::( + lib, + b"writeUnsignedInteger8BitArray" + )?; + let get_number_of_ncus = load_symbol::(lib, b"getNumberOfNCUs")?; - #[link_name = "createProject"] - pub fn create_project(str_file_name: PCWSTR, str_version: PCWSTR) -> OpenReturnCodes; + Ok(Self { + _lib: lib, + start_application, + stop_application, + connect, + disconnect, + open_project, + create_project, + create_project_with_scaling, + create_project_with_scaling_ncu_number, + save_project, + close_project, + boot_controller, + shutdown_controller, + reset_controller, + register_for_events, + unregister_events, + wait_for_events, + continue_simulation, + get_dictionary_id, + register_watch, + unregister_watch, + get_dictionary_element_type, + read_unsigned_integer_64_bit_array, + read_signed_integer_32_bit_array, + read_unsigned_integer_32_bit_array, + read_unsigned_integer_16_bit_array, + read_unsigned_integer_8_bit_array, + read_bool_array, + read_double_array, + read_string, + read_string_array, + read_unsigned_integer_16_bit, + read_signed_integer_16_bit, + read_unsigned_integer_32_bit, + read_signed_integer_32_bit, + read_unsigned_integer_64_bit, + read_signed_integer_64_bit, + get_num_array_elements, + read_bit, + read_bool, + read_byte, + read_double, + read_word, + read_double_word, + read_long_word, + read_next_event, + read_next_event_with_ncu_index, + write_bit, + write_bool, + write_byte, + write_double, + write_word, + write_double_word, + write_long_word, + write_bool_array, + get_simulation_speed, + set_simulation_speed, + get_card_path, + get_card_paths, + get_file, + put_file, + select_file, + delete_file, + delete_directory, + create_directory, + list_directory, + get_version_information, + get_project_information, + get_current_project_information, + get_current_project_state, + import_project_settings, + export_project_settings, + write_unsigned_integer_8_bit_array, + get_number_of_ncus, + }) + } + #[inline] + pub unsafe fn start_application(&self, str_profile_file_name: PCWSTR) -> OpenReturnCodes { + (self.start_application)(str_profile_file_name) + } - #[link_name = "createProjectWithScaling"] - pub fn create_project_with_scaling( + #[inline] + pub unsafe fn stop_application(&self) -> OpenReturnCodes { + (self.stop_application)() + } + + #[inline] + pub unsafe fn connect(&self) -> OpenReturnCodes { + (self.connect)() + } + + #[inline] + pub unsafe fn disconnect(&self) -> OpenReturnCodes { + (self.disconnect)() + } + + #[inline] + pub unsafe fn open_project(&self, str_file_name: PCWSTR) -> OpenReturnCodes { + (self.open_project)(str_file_name) + } + + #[inline] + pub unsafe fn create_project( + &self, + str_file_name: PCWSTR, + str_version: PCWSTR + ) -> OpenReturnCodes { + (self.create_project)(str_file_name, str_version) + } + + #[inline] + pub unsafe fn create_project_with_scaling( + &self, str_file_name: PCWSTR, str_version: PCWSTR, str_nck_scaling: PCWSTR - ) -> OpenReturnCodes; + ) -> OpenReturnCodes { + (self.create_project_with_scaling)(str_file_name, str_version, str_nck_scaling) + } - #[link_name = "createProjectWithScalingNCUNumber"] - pub fn create_project_with_scaling_ncu_number( + #[inline] + pub unsafe fn create_project_with_scaling_ncu_number( + &self, str_file_name: PCWSTR, str_version: PCWSTR, str_nck_scaling: PCWSTR, ncu_number: u32 - ) -> OpenReturnCodes; + ) -> OpenReturnCodes { + (self.create_project_with_scaling_ncu_number)( + str_file_name, + str_version, + str_nck_scaling, + ncu_number + ) + } - #[link_name = "saveProject"] - pub fn save_project() -> OpenReturnCodes; + #[inline] + pub unsafe fn save_project(&self) -> OpenReturnCodes { + (self.save_project)() + } - #[link_name = "closeProject"] - pub fn close_project() -> OpenReturnCodes; + #[inline] + pub unsafe fn close_project(&self) -> OpenReturnCodes { + (self.close_project)() + } - #[link_name = "bootController"] - pub fn boot_controller() -> OpenReturnCodes; + #[inline] + pub unsafe fn boot_controller(&self) -> OpenReturnCodes { + (self.boot_controller)() + } - #[link_name = "shutdownController"] - pub fn shutdown_controller() -> OpenReturnCodes; + #[inline] + pub unsafe fn shutdown_controller(&self) -> OpenReturnCodes { + (self.shutdown_controller)() + } - #[link_name = "resetController"] - pub fn reset_controller() -> OpenReturnCodes; + #[inline] + pub unsafe fn reset_controller(&self) -> OpenReturnCodes { + (self.reset_controller)() + } - #[link_name = "registerForEvents"] - pub fn register_for_events( + #[inline] + pub unsafe fn register_for_events( + &self, event_list_length: u32, event_list: *const OpenEventMaskDefinition - ) -> OpenReturnCodes; + ) -> OpenReturnCodes { + (self.register_for_events)(event_list_length, event_list) + } - #[link_name = "unregisterEvents"] - pub fn unregister_events() -> OpenReturnCodes; + #[inline] + pub unsafe fn unregister_events(&self) -> OpenReturnCodes { + (self.unregister_events)() + } - #[link_name = "waitForEvents"] - pub fn wait_for_events() -> OpenReturnCodes; + #[inline] + pub unsafe fn wait_for_events(&self) -> OpenReturnCodes { + (self.wait_for_events)() + } - #[link_name = "continueSimulation"] - pub fn continue_simulation() -> OpenReturnCodes; + #[inline] + pub unsafe fn continue_simulation(&self) -> OpenReturnCodes { + (self.continue_simulation)() + } - #[link_name = "getDictionaryId"] - pub fn get_dictionary_id( + #[inline] + pub unsafe fn get_dictionary_id( + &self, dictionary_element: PCWSTR, dictionary_id: *mut u32 - ) -> OpenReturnCodes; + ) -> OpenReturnCodes { + (self.get_dictionary_id)(dictionary_element, dictionary_id) + } - #[link_name = "registerWatch"] - pub fn register_watch( + #[inline] + pub unsafe fn register_watch( + &self, watch_list_length: u32, dictionary_id_list: *const u32 - ) -> OpenReturnCodes; + ) -> OpenReturnCodes { + (self.register_watch)(watch_list_length, dictionary_id_list) + } - #[link_name = "unregisterWatch"] - pub fn unregister_watch() -> OpenReturnCodes; + #[inline] + pub unsafe fn unregister_watch(&self) -> OpenReturnCodes { + (self.unregister_watch)() + } - #[link_name = "getDictionaryElementType"] - pub fn get_dictionary_element_type(dictionary_id: u32, value: *mut u8) -> OpenReturnCodes; + #[inline] + pub unsafe fn get_dictionary_element_type( + &self, + dictionary_id: u32, + value: *mut u8 + ) -> OpenReturnCodes { + (self.get_dictionary_element_type)(dictionary_id, value) + } - #[link_name = "readUnsignedInteger64BitArray"] - pub fn read_unsigned_integer_64_bit_array( + #[inline] + pub unsafe fn read_unsigned_integer_64_bit_array( + &self, dictionary_id: u32, value_list_max_length: u32, value_list: *mut u64 - ) -> OpenReturnCodes; + ) -> OpenReturnCodes { + (self.read_unsigned_integer_64_bit_array)(dictionary_id, value_list_max_length, value_list) + } - #[link_name = "readSignedInteger32BitArray"] - pub fn read_signed_integer_32_bit_array( + #[inline] + pub unsafe fn read_signed_integer_32_bit_array( + &self, dictionary_id: u32, value_list_max_length: u32, value_list: *mut i32 - ) -> OpenReturnCodes; + ) -> OpenReturnCodes { + (self.read_signed_integer_32_bit_array)(dictionary_id, value_list_max_length, value_list) + } - #[link_name = "readUnsignedInteger32BitArray"] - pub fn read_unsigned_integer_32_bit_array( + #[inline] + pub unsafe fn read_unsigned_integer_32_bit_array( + &self, dictionary_id: u32, value_list_max_length: u32, value_list: *mut u32 - ) -> OpenReturnCodes; + ) -> OpenReturnCodes { + (self.read_unsigned_integer_32_bit_array)(dictionary_id, value_list_max_length, value_list) + } - #[link_name = "readUnsignedInteger16BitArray"] - pub fn read_unsigned_integer_16_bit_array( + #[inline] + pub unsafe fn read_unsigned_integer_16_bit_array( + &self, dictionary_id: u32, value_list_max_length: u32, value_list: *mut u16 - ) -> OpenReturnCodes; + ) -> OpenReturnCodes { + (self.read_unsigned_integer_16_bit_array)(dictionary_id, value_list_max_length, value_list) + } - #[link_name = "readUnsignedInteger8BitArray"] - pub fn read_unsigned_integer_8_bit_array( + #[inline] + pub unsafe fn read_unsigned_integer_8_bit_array( + &self, dictionary_id: u32, value_list_max_length: u32, value_list: *mut u8 - ) -> OpenReturnCodes; + ) -> OpenReturnCodes { + (self.read_unsigned_integer_8_bit_array)(dictionary_id, value_list_max_length, value_list) + } - #[link_name = "readBoolArray"] - pub fn read_bool_array( + #[inline] + pub unsafe fn read_bool_array( + &self, dictionary_id: u32, value_list_max_length: u32, value_list: *mut bool - ) -> OpenReturnCodes; + ) -> OpenReturnCodes { + (self.read_bool_array)(dictionary_id, value_list_max_length, value_list) + } - #[link_name = "readDoubleArray"] - pub fn read_double_array( + #[inline] + pub unsafe fn read_double_array( + &self, dictionary_id: u32, value_list_max_length: u32, value_list: *mut f64 - ) -> OpenReturnCodes; + ) -> OpenReturnCodes { + (self.read_double_array)(dictionary_id, value_list_max_length, value_list) + } - #[link_name = "readString"] - pub fn read_string( + #[inline] + pub unsafe fn read_string( + &self, dictionary_id: u32, string_max_length: u32, string_buffer: PWSTR - ) -> OpenReturnCodes; + ) -> OpenReturnCodes { + (self.read_string)(dictionary_id, string_max_length, string_buffer) + } - #[link_name = "readStringArray"] - pub fn read_string_array( + #[inline] + pub unsafe fn read_string_array( + &self, dictionary_id: u32, string_array_max_length: u32, string_max_length: u32, string_array: PPWSTR - ) -> OpenReturnCodes; + ) -> OpenReturnCodes { + (self.read_string_array)( + dictionary_id, + string_array_max_length, + string_max_length, + string_array + ) + } - #[link_name = "readUnsignedInteger16Bit"] - pub fn read_unsigned_integer_16_bit(dictionary_id: u32, value: *mut u16) -> OpenReturnCodes; + #[inline] + pub unsafe fn read_unsigned_integer_16_bit( + &self, + dictionary_id: u32, + value: *mut u16 + ) -> OpenReturnCodes { + (self.read_unsigned_integer_16_bit)(dictionary_id, value) + } - #[link_name = "readSignedInteger16Bit"] - pub fn read_signed_integer_16_bit(dictionary_id: u32, value: *mut i16) -> OpenReturnCodes; + #[inline] + pub unsafe fn read_signed_integer_16_bit( + &self, + dictionary_id: u32, + value: *mut i16 + ) -> OpenReturnCodes { + (self.read_signed_integer_16_bit)(dictionary_id, value) + } - #[link_name = "readUnsignedInteger32Bit"] - pub fn read_unsigned_integer_32_bit(dictionary_id: u32, value: *mut u32) -> OpenReturnCodes; + #[inline] + pub unsafe fn read_unsigned_integer_32_bit( + &self, + dictionary_id: u32, + value: *mut u32 + ) -> OpenReturnCodes { + (self.read_unsigned_integer_32_bit)(dictionary_id, value) + } - #[link_name = "readSignedInteger32Bit"] - pub fn read_signed_integer_32_bit(dictionary_id: u32, value: *mut i32) -> OpenReturnCodes; + #[inline] + pub unsafe fn read_signed_integer_32_bit( + &self, + dictionary_id: u32, + value: *mut i32 + ) -> OpenReturnCodes { + (self.read_signed_integer_32_bit)(dictionary_id, value) + } - #[link_name = "readUnsignedInteger64Bit"] - pub fn read_unsigned_integer_64_bit(dictionary_id: u32, value: *mut u64) -> OpenReturnCodes; + #[inline] + pub unsafe fn read_unsigned_integer_64_bit( + &self, + dictionary_id: u32, + value: *mut u64 + ) -> OpenReturnCodes { + (self.read_unsigned_integer_64_bit)(dictionary_id, value) + } - #[link_name = "readSignedInteger64Bit"] - pub fn read_signed_integer_64_bit(dictionary_id: u32, value: *mut i64) -> OpenReturnCodes; + #[inline] + pub unsafe fn read_signed_integer_64_bit( + &self, + dictionary_id: u32, + value: *mut i64 + ) -> OpenReturnCodes { + (self.read_signed_integer_64_bit)(dictionary_id, value) + } - #[link_name = "getNumArrayElements"] - pub fn get_num_array_elements( + #[inline] + pub unsafe fn get_num_array_elements( + &self, dictionary_id: u32, num_array_elements: *mut u32 - ) -> OpenReturnCodes; + ) -> OpenReturnCodes { + (self.get_num_array_elements)(dictionary_id, num_array_elements) + } - #[link_name = "readBit"] - pub fn read_bit(dictionary_id: u32, value: *mut Bool32) -> OpenReturnCodes; + #[inline] + pub unsafe fn read_bit(&self, dictionary_id: u32, value: *mut Bool32) -> OpenReturnCodes { + (self.read_bit)(dictionary_id, value) + } - #[link_name = "readBool"] - pub fn read_bool(dictionary_id: u32, value: *mut Bool32) -> OpenReturnCodes; + #[inline] + pub unsafe fn read_bool(&self, dictionary_id: u32, value: *mut Bool32) -> OpenReturnCodes { + (self.read_bool)(dictionary_id, value) + } - #[link_name = "readByte"] - pub fn read_byte(dictionary_id: u32, value: *mut u8) -> OpenReturnCodes; + #[inline] + pub unsafe fn read_byte(&self, dictionary_id: u32, value: *mut u8) -> OpenReturnCodes { + (self.read_byte)(dictionary_id, value) + } - #[link_name = "readDouble"] - pub fn read_double(dictionary_id: u32, value: *mut f64) -> OpenReturnCodes; + #[inline] + pub unsafe fn read_double(&self, dictionary_id: u32, value: *mut f64) -> OpenReturnCodes { + (self.read_double)(dictionary_id, value) + } - #[link_name = "readWord"] - pub fn read_word(dictionary_id: u32, value: *mut u16) -> OpenReturnCodes; + #[inline] + pub unsafe fn read_word(&self, dictionary_id: u32, value: *mut u16) -> OpenReturnCodes { + (self.read_word)(dictionary_id, value) + } - #[link_name = "readDoubleWord"] - pub fn read_double_word(dictionary_id: u32, value: *mut u32) -> OpenReturnCodes; + #[inline] + pub unsafe fn read_double_word(&self, dictionary_id: u32, value: *mut u32) -> OpenReturnCodes { + (self.read_double_word)(dictionary_id, value) + } - #[link_name = "readLongWord"] - pub fn read_long_word(dictionary_id: u32, value: *mut u64) -> OpenReturnCodes; + #[inline] + pub unsafe fn read_long_word(&self, dictionary_id: u32, value: *mut u64) -> OpenReturnCodes { + (self.read_long_word)(dictionary_id, value) + } - #[link_name = "readNextEvent"] - pub fn read_next_event(event: *mut u64) -> OpenReturnCodes; + #[inline] + pub unsafe fn read_next_event(&self, event: *mut u64) -> OpenReturnCodes { + (self.read_next_event)(event) + } - #[link_name = "readNextEventWithNcuIndex"] - pub fn read_next_event_with_ncu_index(event: *mut u64, ncu_index: *mut i32) -> OpenReturnCodes; + #[inline] + pub unsafe fn read_next_event_with_ncu_index( + &self, + event: *mut u64, + ncu_index: *mut i32 + ) -> OpenReturnCodes { + (self.read_next_event_with_ncu_index)(event, ncu_index) + } - #[link_name = "writeBit"] - pub fn write_bit(dictionary_id: u32, value: Bool32) -> OpenReturnCodes; + #[inline] + pub unsafe fn write_bit(&self, dictionary_id: u32, value: Bool32) -> OpenReturnCodes { + (self.write_bit)(dictionary_id, value) + } - #[link_name = "writeBool"] - pub fn write_bool(dictionary_id: u32, value: Bool32) -> OpenReturnCodes; + #[inline] + pub unsafe fn write_bool(&self, dictionary_id: u32, value: Bool32) -> OpenReturnCodes { + (self.write_bool)(dictionary_id, value) + } - #[link_name = "writeByte"] - pub fn write_byte(dictionary_id: u32, value: u8) -> OpenReturnCodes; + #[inline] + pub unsafe fn write_byte(&self, dictionary_id: u32, value: u8) -> OpenReturnCodes { + (self.write_byte)(dictionary_id, value) + } - #[link_name = "writeDouble"] - pub fn write_double(dictionary_id: u32, value: f64) -> OpenReturnCodes; + #[inline] + pub unsafe fn write_double(&self, dictionary_id: u32, value: f64) -> OpenReturnCodes { + (self.write_double)(dictionary_id, value) + } - #[link_name = "writeWord"] - pub fn write_word(dictionary_id: u32, value: u16) -> OpenReturnCodes; + #[inline] + pub unsafe fn write_word(&self, dictionary_id: u32, value: u16) -> OpenReturnCodes { + (self.write_word)(dictionary_id, value) + } - #[link_name = "writeDoubleWord"] - pub fn write_double_word(dictionary_id: u32, value: u32) -> OpenReturnCodes; + #[inline] + pub unsafe fn write_double_word(&self, dictionary_id: u32, value: u32) -> OpenReturnCodes { + (self.write_double_word)(dictionary_id, value) + } - #[link_name = "writeLongWord"] - pub fn write_long_word(dictionary_id: u32, value: u64) -> OpenReturnCodes; + #[inline] + pub unsafe fn write_long_word(&self, dictionary_id: u32, value: u64) -> OpenReturnCodes { + (self.write_long_word)(dictionary_id, value) + } - #[link_name = "writeBoolArray"] - pub fn write_bool_array( + #[inline] + pub unsafe fn write_bool_array( + &self, dictionary_id: u32, value_list_length: u32, value_list: *const bool - ) -> OpenReturnCodes; + ) -> OpenReturnCodes { + (self.write_bool_array)(dictionary_id, value_list_length, value_list) + } - #[link_name = "getSimulationSpeed"] - pub fn get_simulation_speed(percent: *mut u32) -> OpenReturnCodes; + #[inline] + pub unsafe fn get_simulation_speed(&self, percent: *mut u32) -> OpenReturnCodes { + (self.get_simulation_speed)(percent) + } - #[link_name = "setSimulationSpeed"] - pub fn set_simulation_speed(percent: u32) -> OpenReturnCodes; + #[inline] + pub unsafe fn set_simulation_speed(&self, percent: u32) -> OpenReturnCodes { + (self.set_simulation_speed)(percent) + } - #[link_name = "getCardPath"] - pub fn get_card_path(card_path_max_length: u32, card_path: PWSTR) -> OpenReturnCodes; + #[inline] + pub unsafe fn get_card_path( + &self, + card_path_max_length: u32, + card_path: PWSTR + ) -> OpenReturnCodes { + (self.get_card_path)(card_path_max_length, card_path) + } - #[link_name = "getCardPaths"] - pub fn get_card_paths( + #[inline] + pub unsafe fn get_card_paths( + &self, card_paths_array_max_length: u32, card_path_max_length: u32, card_paths: PPWSTR - ) -> OpenReturnCodes; + ) -> OpenReturnCodes { + (self.get_card_paths)(card_paths_array_max_length, card_path_max_length, card_paths) + } - #[link_name = "getFile"] - pub fn get_file(source_file_path: PCWSTR, destination_file_path: PCWSTR) -> OpenReturnCodes; + #[inline] + pub unsafe fn get_file( + &self, + source_file_path: PCWSTR, + destination_file_path: PCWSTR + ) -> OpenReturnCodes { + (self.get_file)(source_file_path, destination_file_path) + } - #[link_name = "putFile"] - pub fn put_file(source_file_path: PCWSTR, destination_file_path: PCWSTR) -> OpenReturnCodes; + #[inline] + pub unsafe fn put_file( + &self, + source_file_path: PCWSTR, + destination_file_path: PCWSTR + ) -> OpenReturnCodes { + (self.put_file)(source_file_path, destination_file_path) + } - #[link_name = "selectFile"] - pub fn select_file(source_file_path: PCWSTR, channel_name: PCWSTR) -> OpenReturnCodes; + #[inline] + pub unsafe fn select_file( + &self, + source_file_path: PCWSTR, + channel_name: PCWSTR + ) -> OpenReturnCodes { + (self.select_file)(source_file_path, channel_name) + } - #[link_name = "deleteFile"] - pub fn delete_file(file_path: PCWSTR) -> OpenReturnCodes; + #[inline] + pub unsafe fn delete_file(&self, file_path: PCWSTR) -> OpenReturnCodes { + (self.delete_file)(file_path) + } - #[link_name = "deleteDirectory"] - pub fn delete_directory(directory_path: PCWSTR) -> OpenReturnCodes; + #[inline] + pub unsafe fn delete_directory(&self, directory_path: PCWSTR) -> OpenReturnCodes { + (self.delete_directory)(directory_path) + } - #[link_name = "createDirectory"] - pub fn create_directory(directory_path: PCWSTR) -> OpenReturnCodes; + #[inline] + pub unsafe fn create_directory(&self, directory_path: PCWSTR) -> OpenReturnCodes { + (self.create_directory)(directory_path) + } - #[link_name = "listDirectory"] - pub fn list_directory(directory_path: PCWSTR, result_file_path: PCWSTR) -> OpenReturnCodes; + #[inline] + pub unsafe fn list_directory( + &self, + directory_path: PCWSTR, + result_file_path: PCWSTR + ) -> OpenReturnCodes { + (self.list_directory)(directory_path, result_file_path) + } - #[link_name = "getVersionInformation"] - pub fn get_version_information(destination_file_path: PCWSTR) -> OpenReturnCodes; + #[inline] + pub unsafe fn get_version_information(&self, destination_file_path: PCWSTR) -> OpenReturnCodes { + (self.get_version_information)(destination_file_path) + } - #[link_name = "getProjectInformation"] - pub fn get_project_information( + #[inline] + pub unsafe fn get_project_information( + &self, vcp_file_path: PCWSTR, destination_file_path: PCWSTR - ) -> OpenReturnCodes; + ) -> OpenReturnCodes { + (self.get_project_information)(vcp_file_path, destination_file_path) + } - #[link_name = "getCurrentProjectInformation"] - pub fn get_current_project_information(destination_file_path: PCWSTR) -> OpenReturnCodes; + #[inline] + pub unsafe fn get_current_project_information( + &self, + destination_file_path: PCWSTR + ) -> OpenReturnCodes { + (self.get_current_project_information)(destination_file_path) + } - #[link_name = "getCurrentProjectState"] - pub fn get_current_project_state(project_state: *mut OpenProjectStates) -> OpenReturnCodes; + #[inline] + pub unsafe fn get_current_project_state( + &self, + project_state: *mut OpenProjectStates + ) -> OpenReturnCodes { + (self.get_current_project_state)(project_state) + } - #[link_name = "importProjectSettings"] - pub fn import_project_settings( + #[inline] + pub unsafe fn import_project_settings( + &self, file_name: PCWSTR, import_content_file_name: PCWSTR - ) -> OpenReturnCodes; + ) -> OpenReturnCodes { + (self.import_project_settings)(file_name, import_content_file_name) + } - #[link_name = "exportProjectSettings"] - pub fn export_project_settings(file_name: PCWSTR) -> OpenReturnCodes; + #[inline] + pub unsafe fn export_project_settings(&self, file_name: PCWSTR) -> OpenReturnCodes { + (self.export_project_settings)(file_name) + } - #[link_name = "writeUnsignedInteger8BitArray"] - pub fn write_unsigned_integer_8_bit_array( + #[inline] + pub unsafe fn write_unsigned_integer_8_bit_array( + &self, dictionary_id: u32, value_list_max_length: u32, value_list: *const u8 - ) -> OpenReturnCodes; + ) -> OpenReturnCodes { + (self.write_unsigned_integer_8_bit_array)(dictionary_id, value_list_max_length, value_list) + } - #[link_name = "getNumberOfNCUs"] - pub fn get_number_of_ncus(number_of_ncus: *mut u32) -> OpenReturnCodes; + #[inline] + pub unsafe fn get_number_of_ncus(&self, number_of_ncus: *mut u32) -> OpenReturnCodes { + (self.get_number_of_ncus)(number_of_ncus) + } } diff --git a/src/main.rs b/src/main.rs index e8ee068..9ff11ea 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,108 +1,30 @@ -use std::io::{ self, Write }; +use std::{ env, path::PathBuf, process }; -use open_wrapper::{ self, OpenReturnCodes }; +use open_wrapper::OpenApi; fn main() { - println!("Rust connect demo for open.dll"); - println!("(make sure open.dll is discoverable and open.lib is linked)\n"); - print_menu(); + let dll_path = env + ::args_os() + .nth(1) + .map(PathBuf::from) + .unwrap_or_else(|| PathBuf::from("open_wrapper/lib/open.dll")); - let stdin = io::stdin(); - let mut state = ConnectionState::default(); - - loop { - print!("> "); - if io::stdout().flush().is_err() { - eprintln!("Failed to flush stdout."); - break; + println!("Loading Open API from '{}'", dll_path.display()); + let api = match (unsafe { OpenApi::load(&dll_path) }) { + Ok(api) => api, + Err(err) => { + eprintln!("Failed to load '{}': {err}", dll_path.display()); + process::exit(1); } + }; - let mut line = String::new(); - if stdin.read_line(&mut line).is_err() { - eprintln!("Failed to read input, exiting."); - break; - } + println!("Calling connect() ..."); + let rc = unsafe { api.connect() }; - let cmd = line.trim().to_lowercase(); - if cmd.is_empty() { - continue; - } - - match cmd.as_str() { - "1" | "c" | "connect" => handle_connect(&mut state), - "2" | "d" | "disconnect" => handle_disconnect(&mut state), - // "3" | "g" | "get-speed" => handle_get_speed(), - // "4" | "r" | "realtime" => handle_set_speed(100, "SetSimulationSpeed (100%)"), - // "5" | "m" | "max" => handle_set_speed(u32::MAX, "SetSimulationSpeed (u32::MAX)"), - "h" | "help" | "?" => print_menu(), - "q" | "quit" | "exit" => { - println!("Bye!"); - break; - } - _ => println!("Unknown command. Type `help` to see the list of commands."), - } - } -} - -#[derive(Default)] -struct ConnectionState { - connected: bool, -} - -fn handle_connect(state: &mut ConnectionState) { - if state.connected { - println!("Already connected. Run `disconnect` first if you need a fresh session."); - return; - } - - let rc = call_and_report("Connect", || unsafe { open_wrapper::connect() }); if rc.is_ok() { - state.connected = true; + println!("connect() succeeded with status {rc:?}"); + } else { + eprintln!("connect() failed with status {rc:?}"); + process::exit(2); } } - -fn handle_disconnect(state: &mut ConnectionState) { - if !state.connected { - println!("Not connected yet. Use `connect` first."); - return; - } - - let rc = call_and_report("Disconnect", || unsafe { open_wrapper::disconnect() }); - if rc.is_ok() { - state.connected = false; - } -} - -// fn handle_get_speed() { -// println!("GetSimulationSpeed called ..."); -// let mut sim_speed = 0u32; -// let rc = unsafe { open_wrapper::get_simulation_speed(&mut sim_speed) }; -// if rc.is_ok() { -// println!("Current simulation speed: {sim_speed}%"); -// } -// println!("GetSimulationSpeed returned: {rc:?}"); -// } - -// fn handle_set_speed(value: u32, label: &str) { -// println!("{label} called ..."); -// let rc = unsafe { open_wrapper::set_simulation_speed(value) }; -// println!("{label} returned: {rc:?}"); -// } - -fn call_and_report(action: &str, mut op: impl FnMut() -> OpenReturnCodes) -> OpenReturnCodes { - println!("{action} called ..."); - let rc = op(); - println!("{action} returned: {rc:?}"); - rc -} - -fn print_menu() { - println!("Commands:"); - println!(" (1) connect - connect to the running controller"); - println!(" (2) disconnect - disconnect the session"); - println!(" (3) get-speed - read the current simulation speed"); - println!(" (4) realtime - set speed to 100%"); - println!(" (5) max - set speed to u32::MAX"); - println!(" (h) help - show this list"); - println!(" (q) quit - exit the demo"); -}