Struct OwnedUHandle

Source
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>

Source

pub fn new(value: &T) -> Result<Self>

Create a new handle to a sized value of T.

It will copy the data from the provided value.

Source§

impl<T: ?Sized> OwnedUHandle<T>

Source

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>

Source

pub fn try_clone(&self) -> Result<Self>

Try to clone the handle.

This will create a new handle to the same data.

§Errors
  • If there is not enough memory to create the handle this may error.
Source§

impl<const D: usize, T: NumericArrayResizable + Sized + Copy> OwnedUHandle<LVArray<D, T>>

Source

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>

Source

pub fn empty_string() -> Result<Self>

Create a new owned LStr with a size of zero.

Source

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>>§

Source

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.
Source

pub unsafe fn resize(&mut self, desired_size: usize) -> Result<()>

Resize the handle to the desired size.

§Safety
  • The handle must be valid.
Source

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();
  }
}
Source

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).
Source

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.
Source

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 + LVCopy + 'static> Clone for OwnedUHandle<T>

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<T: Debug + ?Sized> Debug for OwnedUHandle<T>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<T: ?Sized> Deref for OwnedUHandle<T>

Source§

type Target = UHandle<'static, T>

The resulting type after dereferencing.
Source§

fn deref(&self) -> &Self::Target

Dereferences the value.
Source§

impl<T: ?Sized> DerefMut for OwnedUHandle<T>

Source§

fn deref_mut(&mut self) -> &mut Self::Target

Mutably dereferences the value.
Source§

impl<T: ?Sized> Drop for OwnedUHandle<T>

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

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
Source§

impl<T: ?Sized> Sync for OwnedUHandle<T>

Auto Trait Implementations§

§

impl<T> Freeze for OwnedUHandle<T>
where T: ?Sized,

§

impl<T> RefUnwindSafe for OwnedUHandle<T>
where T: RefUnwindSafe + ?Sized,

§

impl<T> Unpin for OwnedUHandle<T>
where T: ?Sized,

§

impl<T> UnwindSafe for OwnedUHandle<T>
where T: RefUnwindSafe + ?Sized,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<P, T> Receiver for P
where P: Deref<Target = T> + ?Sized, T: ?Sized,

Source§

type Target = T

🔬This is a nightly-only experimental API. (arbitrary_self_types)
The target type on which the method may be called.
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.