#[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,
) -> HurrayStatusExpand 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_tensorMUST be a valid, non-null, writable pointer.descriptor_bytesMUST point to at leastdescriptor_lenreadable bytes.buffersMUST be a live list fromhurray_buffer_list_newthat nothing else owns.ownerMUST remain valid untilowner_releaseis 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