Struct UHandle

Source
#[repr(transparent)]
pub struct UHandle<'a, T: ?Sized + 'a>(pub *mut *mut T, pub PhantomData<&'a T>);
Expand description

A handle from LabVIEW for the data.

A handle is a double pointer so the underlying data can be resized and moved.

Deref is implemented for this type so you can access the data using * but this can panic if the handle is invalid.

fn print_value(handle: UHandle<i32>) {
  println!("{}", *handle);
}

If you want to handle the error you can use the UHandle::as_ref or UHandle::as_ref_mut method.

Tuple Fields§

§0: *mut *mut T§1: PhantomData<&'a T>

Implementations§

Source§

impl<T: ?Sized + LVCopy + 'static> UHandle<'_, 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§

impl<T: ?Sized> UHandle<'_, T>

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§

impl<T: ?Sized + LVCopy + 'static> UHandle<'_, T>

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§

impl<T: ?Sized> UHandle<'_, T>

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.

Source§

impl<const D: usize, T: NumericArrayResizable> UHandle<'_, LVArray<D, T>>

Source

pub fn resize_array(&mut self, new_dims: LVArrayDims<D>) -> Result<()>

Resize the array to the new size.

Source§

impl UHandle<'_, LStr>

Implement features that require a full string handle rather than just the LStr type.

Requires the link feature.

Source

pub fn set(&mut self, value: &[u8]) -> Result<()>

Set the string as a binary value against the handle.

This function will resize the handle based on the size of the input value.

§Errors
  • This will error if the string handle is invalid (likely a null pointer).
§Example
use labview_interop::types::{LVStatusCode, LStrHandle};
#[no_mangle]
pub extern "C" fn hello_world(mut string: LStrHandle) -> LVStatusCode {
   let result = string.set(b"Hello World");
   result.into()
}
Source

pub fn set_str(&mut self, value: &str) -> Result<()>

Set string takes a Rust string and puts it into the LabVIEW String.

This is a two step process:

  1. Encode from Rust (UTF8) to LabVIEW encoding (based on system code page on Windows).
  2. Write this encoding into the LabVIEW string.

If the input is valid ASCII then no additional data copies are made. If not then this will allocate a new intermediate buffer to hold the decoded results before writing to the LabVIEW string.

Source

pub fn set_str_with_encoding( &mut self, encoder: &'static Encoding, value: &str, ) -> Result<()>

Set string with encoder takes a Rust string and puts it into the LabVIEW String.

This is a two step process:

  1. Encode from Rust (UTF8) to LabVIEW encoding with the provided encoder.
  2. Write this encoding into the LabVIEW string.

If the input is valid ASCII then no additional data copies are made. If not then this will allocate a new intermediate buffer to hold the decoded results before writing to the LabVIEW string.

The encoder should be an encoder provided by the encoding_rs crate.

Trait Implementations§

Source§

impl<T: Debug + ?Sized> Debug for UHandle<'_, T>

Source§

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

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

impl<T: ?Sized> Deref for UHandle<'_, T>

Source§

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

Extract the target type.

This will panic if the handle or internal pointer is null.

Source§

type Target = T

The resulting type after dereferencing.
Source§

impl<T: ?Sized> DerefMut for UHandle<'_, T>

Source§

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

Deref to a mutable reference.

This will panic if the handle or internal pointer is null.

Source§

impl<'a, T: PartialEq + ?Sized + 'a> PartialEq for UHandle<'a, T>

Source§

fn eq(&self, other: &UHandle<'a, T>) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl<'a, T: Eq + ?Sized + 'a> Eq for UHandle<'a, T>

Source§

impl<T: ?Sized> Send for UHandle<'_, T>

§Safety

  • UHandle memory is managed by the Labview Memory Manager, which is thread safe
Source§

impl<'a, T: ?Sized + 'a> StructuralPartialEq for UHandle<'a, T>

Source§

impl<T: ?Sized> Sync for UHandle<'_, T>

Auto Trait Implementations§

§

impl<'a, T> Freeze for UHandle<'a, T>
where T: ?Sized,

§

impl<'a, T> RefUnwindSafe for UHandle<'a, T>
where T: RefUnwindSafe + ?Sized,

§

impl<'a, T> Unpin for UHandle<'a, T>
where T: ?Sized,

§

impl<'a, T> UnwindSafe for UHandle<'a, 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> 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, 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.