pub struct OwnedUHandle<T: ?Sized + 'static>(/* private fields */);
Expand description
A value allocated in the LabVIEW memory managed by Rust.
This will manage the lifetime and free the handle on drop.
This is a semantic difference from handle and is transparent with the handle data.
This means it can be used in structs in place of a handle.
§Example In Struct (LStrOwned is equivalent of OwnedUHandle<LStr>
).
labview_layout!(
pub struct UserEventCluster {
eventno: i32,
id: LStrOwned,
}
);
§From a Handle
You can convert a handle to an owned value using the UHandle::try_to_owned
method.
The type must be LVCopy
to ensure it is safe to copy the internal data.
§Example
use labview_interop::types::{LStrHandle, LStrOwned};
fn handle_to_owned(handle: LStrHandle) -> LStrOwned {
handle.try_to_owned().unwrap()
}
§Clone
Clone is implemented but can panic if there is not enough memory to create the new handle.
There is also a OwnedUHandle::try_clone
method which will return a Result.
The type must be LVCopy
to ensure it is safe to clone.
Implementations§
Source§impl<T: Copy + 'static> OwnedUHandle<T>
impl<T: Copy + 'static> OwnedUHandle<T>
Source§impl<T: ?Sized> OwnedUHandle<T>
impl<T: ?Sized> OwnedUHandle<T>
Sourcepub fn handle_to_inner(&mut self) -> UHandle<'_, T>
pub fn handle_to_inner(&mut self) -> UHandle<'_, T>
Return a new handle to the inner value.
This takes a mutable borrow on the owned value as you can use the handle to modify the inner value.
Note: This is only if you need a true handle to put into a structure that is expecting this. Better options are :
- If you can define the type, just define it with the owned value. An owned value can take the place of a handle.
- If you just need access to the data then use the Deref methods to access the handle.
§Safety
- This needs to take a mutable reference to self and lifetime annotation on UHandle, to avoid creating multiple UHandles.
§Examples
§Use Handle in Struct
use labview_interop::types::{LStrHandle, LStrOwned};
use labview_interop::labview_layout;
// This must have a handle due to other uses.
labview_layout! {
struct ClusterWithString<'a> {
string_handle: LStrHandle<'a>
}
}
// Mutable is required since once you have a handle you can mutate the data.
let mut owned_string = LStrOwned::from_data(b"Hello World!").unwrap();
let handle = owned_string.handle_to_inner();
let cluster = ClusterWithString {
string_handle: handle
};
// Do something with the cluster.
§Lifetime Guarantees - Single Handle
use labview_interop::memory::LvOwned;
let mut owned = LvOwned::<f64>::new().unwrap();
let mut handle = owned.handle_to_inner();
// Cannot get a second handle due to lifetime.
// This fails to compile.
let handle2 = owned.handle_to_inner();
*handle = 1.0;
§Lifetime Guarantees - Owned Outlives Handle
use labview_interop::memory::LvOwned;
let mut owned = LvOwned::<f64>::new().unwrap();
let mut handle = owned.handle_to_inner();
// Cannot drop owned because we have a handle.
// This fails to compile.
drop(owned);
*handle = 1.0;
Source§impl<T: ?Sized + LVCopy + 'static> OwnedUHandle<T>
impl<T: ?Sized + LVCopy + 'static> OwnedUHandle<T>
Source§impl<const D: usize, T: NumericArrayResizable + Sized + Copy> OwnedUHandle<LVArray<D, T>>
impl<const D: usize, T: NumericArrayResizable + Sized + Copy> OwnedUHandle<LVArray<D, T>>
Sourcepub fn new_empty() -> Result<Self>
pub fn new_empty() -> Result<Self>
Create a new empty owned array. Once created you can use the existing handle methods to manipulate the data.
§Example
use labview_interop::types::LVArrayOwned;
let mut array = LVArrayOwned::<1, f64>::new_empty().unwrap();
array.resize_array([10].into()).unwrap();
Source§impl OwnedUHandle<LStr>
impl OwnedUHandle<LStr>
Sourcepub fn empty_string() -> Result<Self>
pub fn empty_string() -> Result<Self>
Create a new owned LStr
with a size of zero.
Sourcepub fn from_data(data: &[u8]) -> Result<Self>
pub fn from_data(data: &[u8]) -> Result<Self>
§Example
use labview_interop::types::{LStrHandle, LStrOwned};
use labview_interop::types::LVStatusCode;
#[no_mangle]
pub extern "C" fn hello_world(mut strn: String, output_string: *mut LStrHandle) {
let handle = LStrOwned::from_data(strn.as_bytes()).unwrap();
unsafe {
handle.clone_into_pointer(output_string).unwrap();
}
}
Methods from Deref<Target = UHandle<'static, T>>§
Sourcepub fn try_to_owned(&self) -> Result<OwnedUHandle<T>>
pub fn try_to_owned(&self) -> Result<OwnedUHandle<T>>
Try to create an owned handle from the current handle.
The owned handle will have its own handle to the data and will be responsible for freeing it.
§Errors
- If there is not enough memory to create the handle this may error.
- If the source handle is not valid this will error.
Sourcepub unsafe fn clone_into_pointer(
&self,
other: *mut UHandle<'_, T>,
) -> Result<()>
pub unsafe fn clone_into_pointer( &self, other: *mut UHandle<'_, T>, ) -> Result<()>
Copy the contents of one handle into another.
If other points to a null value then this will allocate a handle for the contents.
The data in the handle must be 'static
or copy as this will only perform a shallow copy.
§Safety
- If the other pointer is invalid this may cause UB.
- If the other pointer points to null, you must wrap the value as an owned handle otherwise it will leak memory.
§Examples
§Allowed Types
use labview_interop::labview_layout;
use labview_interop::memory::{UHandle, OwnedUHandle};
use labview_interop::types::LStrHandle;
labview_layout! {
#[derive(Copy, Clone)]
struct ClusterWithNumbers {
float: f64,
int: i32
}
}
fn copy_handles(input: UHandle<ClusterWithNumbers>) {
let cluster = ClusterWithNumbers { float: 3.14, int: 42 };
let mut new_owned = OwnedUHandle::new(&cluster).unwrap();
unsafe {
let mut target_handle = new_owned.handle_to_inner();
input.clone_into_pointer(&mut target_handle).unwrap();
}
}
§Lifetime Guarantees - Fails with Sub-Handles
use labview_interop::labview_layout;
use labview_interop::memory::{UHandle, LvOwned};
use labview_interop::types::LStrHandle;
labview_layout! {
struct ClusterWithString<'a> {
string_handle: LStrHandle<'a>,
int: i32
}
}
fn copy_handles(input: UHandle<ClusterWithString>) {
let mut new_owned = LvOwned::<ClusterWithString>::new().unwrap();
unsafe {
let mut target_handle = new_owned.handle_to_inner();
input.clone_into_pointer(&mut target_handle).unwrap();
}
}
§Lifetime Guarantees - Fails with Owned Handle
use labview_interop::labview_layout;
use labview_interop::memory::{UHandle, LvOwned};
use labview_interop::types::LStrOwned;
labview_layout! {
struct ClusterWithString {
string_handle: LStrOwned,
int: i32
}
}
fn copy_handles(input: UHandle<ClusterWithString>, mut output: UHandle<ClusterWithString>) {
unsafe {
input.clone_into_pointer(&mut output).unwrap();
}
}
Sourcepub unsafe fn as_ref(&self) -> Result<&T>
pub unsafe fn as_ref(&self) -> Result<&T>
Get a reference to the internal type. Errors if the pointer is null.
§Safety
This is a wrapper around pointer::as_ref
and so must follow its safety rules. Namely:
- When calling this method, you have to ensure that either the pointer is null or all of the following is true:
- The pointer must be properly aligned.
- It must be “dereferenceable” in the sense defined in [the module documentation].
- The pointer must point to an initialized instance of T.
- You must enforce Rust’s aliasing rules, since the returned lifetime ’a is arbitrarily chosen and does not necessarily reflect the actual lifetime of the data. In particular, while this reference exists, the memory the pointer points to must not get mutated (except inside UnsafeCell).
Sourcepub unsafe fn as_ref_mut(&self) -> Result<&mut T>
pub unsafe fn as_ref_mut(&self) -> Result<&mut T>
Get a mutable reference to the internal type. Errors if handle contains a null.
§Safety
This method wraps the pointer::as_mut
method and so follows its safety rules which require all of the following is true:
- The pointer must be properly aligned.
- It must be “dereferenceable” in the sense defined in the module documentation.
- The pointer must point to an initialized instance of T.
- You must enforce Rust’s aliasing rules, since the returned lifetime ’a is arbitrarily chosen and does not necessarily reflect the actual lifetime of the data. In particular, while this reference exists, the memory the pointer points to must not get accessed (read or written) through any other pointer.
Sourcepub fn valid(&self) -> bool
pub fn valid(&self) -> bool
Check the validity of the handle to ensure it wont panic later.
A valid handle is:
. Not Null. . Points to a pointer. . That pointer is in the LabVIEW memory zone.
The last 2 checks are done by LabVIEW and require the link
feature.
If the link
feature is not enabled then we just check it is not null.
§Panics/Safety
This will cause a segfault if the handle doesn’t point to a valid address.
Trait Implementations§
Source§impl<T: ?Sized> Deref for OwnedUHandle<T>
impl<T: ?Sized> Deref for OwnedUHandle<T>
Source§impl<T: ?Sized> DerefMut for OwnedUHandle<T>
impl<T: ?Sized> DerefMut for OwnedUHandle<T>
Source§impl<T: ?Sized> Drop for OwnedUHandle<T>
impl<T: ?Sized> Drop for OwnedUHandle<T>
impl<T: ?Sized> Send for OwnedUHandle<T>
§Safety
- LvOwned memory is access through UHandle which is managed by the Labview Memory Manager, which is thread safe