Skip to main content

hurray_tensor_new

Function hurray_tensor_new 

Source
#[unsafe(no_mangle)]
pub unsafe extern "C" fn hurray_tensor_new( abi_version: u32, descriptor_bytes: *const u8, descriptor_len: u64, buffers: *mut HurrayBufferList, owner: *mut c_void, owner_release: HurrayOwnerReleaseFn, out_tensor: *mut *mut HurrayTensor, ) -> HurrayStatus
Expand description

Creates a HurrayTensor from an encoded descriptor and a finished buffer list.

abi_version MUST be the producing build’s HURRAY_C_ABI_VERSION; a consumer compares it against its own before trusting anything else about the handle.

descriptor_bytes is decoded during this call and only the decoded form is kept, so a producer cannot export a tensor whose descriptor does not parse: bytes that fail to decode are rejected with the status the decode failed with. A null pointer or a descriptor_len of 0 is rejected with HURRAY_ERR_NULL_POINTER — a tensor with no descriptor is a carrier for bytes nothing can interpret.

On success buffers is owned by the tensor, and the caller MUST NOT push into it, destroy it, or use the handle at all. On failure ownership stays with the caller, who MUST destroy it — the discipline hurray_buffer_list_push already follows.

owner and owner_release are optional and opaque. When owner_release is non-null it is invoked exactly once, with owner, during hurray_tensor_destroy.

§Safety

  • out_tensor MUST be a valid, non-null, writable pointer.
  • descriptor_bytes MUST point to at least descriptor_len readable bytes.
  • buffers MUST be a live list from hurray_buffer_list_new that nothing else owns.
  • owner MUST remain valid until owner_release is invoked.

§Examples

use hurray_core::{
    BufferHandle, DeviceTag, ElementType, LayoutDescriptor, Shape, SyncMode,
    TensorDescriptor, MIN_BUFFER_ALIGNMENT,
};
use hurray_ffi::tensor::{hurray_tensor_destroy, hurray_tensor_new};
use hurray_ffi::{
    hurray_buffer_list_new, HurrayBufferList, HurrayTensor, HURRAY_C_ABI_VERSION, HURRAY_OK,
};

let handle = BufferHandle::new(
    16,
    MIN_BUFFER_ALIGNMENT,
    DeviceTag::Cpu,
    SyncMode::ProducerSynced,
)?;
let descriptor = TensorDescriptor::new(
    1,
    0,
    ElementType::Float32,
    Shape::new(vec![4])?,
    0,
    LayoutDescriptor::RowMajor,
    vec![handle],
    None,
    None,
    None,
    None,
)?;
let encoded = descriptor.encode()?;

// An empty list is enough to show the ownership transfer; a real producer pushes
// one buffer per descriptor buffer-table entry first.
let mut buffers: *mut HurrayBufferList = std::ptr::null_mut();
assert_eq!(unsafe { hurray_buffer_list_new(1, &mut buffers) }, HURRAY_OK);

let mut tensor: *mut HurrayTensor = std::ptr::null_mut();
assert_eq!(
    unsafe {
        hurray_tensor_new(
            HURRAY_C_ABI_VERSION,
            encoded.as_ptr(),
            encoded.len() as u64,
            buffers, // ownership transfers on success
            std::ptr::null_mut(),
            None,
            &mut tensor,
        )
    },
    HURRAY_OK,
);

// One call ends the whole tensor: descriptor, buffers, and the owner reference.
assert_eq!(unsafe { hurray_tensor_destroy(&mut tensor) }, HURRAY_OK);
assert!(tensor.is_null()); // destroy nulls the caller's pointer