diff --git a/examples/feature-persistence.rs b/examples/feature-persistence.rs new file mode 100644 index 0000000..aeb869c --- /dev/null +++ b/examples/feature-persistence.rs @@ -0,0 +1,20 @@ +fn main() -> anyhow::Result<()> { + // Before using any pylon methods, the pylon runtime must be initialized. + let pylon = pylon_cxx::Pylon::new(); + + // Create an instant camera object with the camera device found first. + let camera = pylon_cxx::TlFactory::instance(&pylon).create_first_device()?; + + camera.open()?; + + let filename = "NodeMap.pfs"; + + println!("Saving camera's node map to file."); + pylon_cxx::NodeMap::save(&camera, filename)?; + + println!("Reading file back to camera's node map."); + pylon_cxx::NodeMap::load(&camera, filename, true)?; + + println!("Ok."); + Ok(()) +} diff --git a/include/pylon-cxx-rs.h b/include/pylon-cxx-rs.h index 562f43f..58a1e49 100644 --- a/include/pylon-cxx-rs.h +++ b/include/pylon-cxx-rs.h @@ -18,6 +18,12 @@ namespace Pylon void instant_camera_open(const std::unique_ptr &); bool instant_camera_is_open(const std::unique_ptr &); void instant_camera_close(const std::unique_ptr &); + void node_map_load(const std::unique_ptr &, rust::String, bool); + void node_map_save(const std::unique_ptr &, rust::String); + + void node_map_load_from_string(const std::unique_ptr &, rust::String, bool); + rust::String node_map_save_to_string(const std::unique_ptr &); + void instant_camera_start_grabbing(const std::unique_ptr &); void instant_camera_start_grabbing_with_count(const std::unique_ptr &, uint32_t); void instant_camera_stop_grabbing(const std::unique_ptr &); diff --git a/src/lib.rs b/src/lib.rs index 1af1246..f486951 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -104,6 +104,19 @@ mod ffi { timeout_handling: TimeoutHandling, ) -> Result; + fn node_map_load( + camera: &UniquePtr, + filename: String, + validate: bool, + ) -> Result<()>; + fn node_map_save(camera: &UniquePtr, filename: String) -> Result<()>; + fn node_map_load_from_string( + camera: &UniquePtr, + features: String, + validate: bool, + ) -> Result<()>; + fn node_map_save_to_string(camera: &UniquePtr) -> Result; + fn node_map_get_boolean_parameter( camera: &UniquePtr, name: &str, @@ -390,6 +403,11 @@ impl CommandNode { } pub trait NodeMap { + fn load>(&self, path: P, validate: bool) -> PylonResult<()>; + fn save>(&self, path: P) -> PylonResult<()>; + fn load_from_string(&self, features: String, validate: bool) -> PylonResult<()>; + fn save_to_string(&self) -> PylonResult; + fn boolean_node(&self, name: &str) -> PylonResult; fn integer_node(&self, name: &str) -> PylonResult; fn float_node(&self, name: &str) -> PylonResult; @@ -400,6 +418,21 @@ pub trait NodeMap { unsafe impl<'a> Send for InstantCamera<'a> {} impl<'a> NodeMap for InstantCamera<'a> { + fn load>(&self, path: P, validate: bool) -> PylonResult<()> { + let filename = path_to_string(path)?; + ffi::node_map_load(&self.inner, filename, validate).into_rust() + } + fn save>(&self, path: P) -> PylonResult<()> { + let filename = path_to_string(path)?; + ffi::node_map_save(&self.inner, filename).into_rust() + } + fn load_from_string(&self, features: String, validate: bool) -> PylonResult<()> { + ffi::node_map_load_from_string(&self.inner, features, validate).into_rust() + } + fn save_to_string(&self) -> PylonResult { + ffi::node_map_save_to_string(&self.inner).into_rust() + } + fn boolean_node(&self, name: &str) -> PylonResult { let inner = ffi::node_map_get_boolean_parameter(&self.inner, name)?; Ok(BooleanNode { inner }) @@ -615,3 +648,14 @@ impl Clone for DeviceInfo { } unsafe impl Send for DeviceInfo {} + +fn path_to_string>(path: P) -> PylonResult { + match path.as_ref().to_str() { + Some(filename) => Ok(filename.into()), + None => Err(PylonError { + msg: "Cannot convert path to UTF-8".to_string(), + #[cfg(feature = "backtrace")] + backtrace: Backtrace::capture(), + }), + } +} diff --git a/src/pylon-cxx-rs.cc b/src/pylon-cxx-rs.cc index c0b35a1..e1a3506 100644 --- a/src/pylon-cxx-rs.cc +++ b/src/pylon-cxx-rs.cc @@ -64,6 +64,31 @@ namespace Pylon camera->Close(); } + void node_map_load(const std::unique_ptr &camera, rust::String filename, bool validate) + { + const char *filename_c = filename.c_str(); + CFeaturePersistence::Load(filename_c, &camera->GetNodeMap(), validate); + } + + void node_map_save(const std::unique_ptr &camera, rust::String filename) + { + const char *filename_c = filename.c_str(); + CFeaturePersistence::Save(filename_c, &camera->GetNodeMap()); + } + + void node_map_load_from_string(const std::unique_ptr &camera, rust::String features, bool validate) + { + const char *features_c = features.c_str(); + CFeaturePersistence::LoadFromString(features_c, &camera->GetNodeMap(), validate); + } + + rust::String node_map_save_to_string(const std::unique_ptr &camera) + { + Pylon::String_t result; + CFeaturePersistence::SaveToString(result, &camera->GetNodeMap()); + return rust::String(result.c_str(), result.length()); + } + void instant_camera_start_grabbing(const std::unique_ptr &camera) { camera->StartGrabbing();