Getting CPU String and Passing It to LabVIEW
A simple exercise — how to obtain the CPU brand string using CPUID in Rust and pass it to LabVIEW.
Basic Rust code:
use raw_cpuid::CpuId;
fn main() {
let cpuid = CpuId::new();
if let Some(vf) = cpuid.get_processor_brand_string() {
println!("{:?}", vf);
}
}
Output:
ProcessorBrandString { as_str: “Intel(R) Core(TM) i7-4800MQ CPU @ 2.70GHz” }
or a little bit more elegant:
use raw_cpuid::CpuId;
fn main() {
let cpuid = CpuId::new();
if let Some(vf) = cpuid.get_processor_brand_string() {
let s = vf.as_str()
.replace("(R)", "®")
.replace("(TM)", "™");
println!("CPU: {}", s);
}
}
Output:
CPU: Intel® Core™ i7-4800MQ CPU @ 2.70GHz
cargo.toml same for both:
[package]
name = "hello_cpu"
version = "0.1.0"
edition = "2024"
[dependencies]
raw-cpuid = "11.6.0"
Passing the CPU string to LabVIEW
There are two ways to pass the string:
- As a C string pointer
Requires preallocating the buffer in LabVIEW. Works, but not elegant. - As a LabVIEW string handle (
LStrHandle)
The Rust function resizes the handle internally using LabVIEW’s memory manager. This is the preferred method.
C function prototypes
/* Call Library source file */
#include "extcode.h"
void funcName_c_ptr(char cpu_string_pointer[], int32_t length)
{
/* Insert code here */
}
void funcName_str_handle(LStrHandle cpu_string_handle)
{
/* Insert code here */
}
First we need cargo.toml:
[package]
name = "hello_cpu_lib"
version = "0.1.0"
edition = "2024"
# Cargo.toml
[lib]
crate-type = ["cdylib"]
[dependencies]
raw-cpuid = "11.6.0"
Then src\lib.rs:
// src/lib.rs
use raw_cpuid::CpuId;
use std::ffi::c_void;
use std::os::raw::{c_char, c_int};
use std::ptr::copy_nonoverlapping;
//
// LabVIEW LStr definition (from extcode.h)
//
#[repr(C)]
pub struct LStr {
pub cnt: i32, // number of bytes
pub str: [u8; 1], // flexible array member
}
pub type LStrPtr = *mut LStr;
pub type LStrHandle = *mut LStrPtr;
//
// LabVIEW Memory Manager
//
#[link(name = "labview")]
unsafe extern "C" {
fn DSSetHandleSize(handle: *mut c_void, new_size: usize) -> i32;
}
//
// Helper: get CPU brand string
//
fn get_cpu_brand_string() -> String {
let cpuid = CpuId::new();
cpuid
.get_processor_brand_string()
.map(|b| b.as_str().trim_end_matches('\0').to_string())
.unwrap_or_else(|| "Unknown CPU".to_string())
}
//
// 1) Fill preallocated C string buffer
//
#[unsafe(no_mangle)]
pub extern "C" fn cpu_string_c(buffer: *mut c_char, length: c_int) {
if buffer.is_null() || length <= 0 {
return;
}
let s = get_cpu_brand_string();
let bytes = s.as_bytes();
let max = (length - 1) as usize; // leave room for null terminator
let n = bytes.len().min(max);
unsafe {
copy_nonoverlapping(bytes.as_ptr(), buffer as *mut u8, n);
*buffer.add(n) = 0; // null terminate
}
}
//
// 2) Fill LabVIEW LStrHandle (auto-resize)
//
#[unsafe(no_mangle)]
pub extern "C" fn cpu_string_lv(h: LStrHandle) -> i32 {
if h.is_null() {
return 1; // mgArgErr
}
let s = get_cpu_brand_string();
let bytes = s.as_bytes();
let size = bytes.len() as usize;
unsafe {
// Resize handle: size = length + sizeof(int32)
let err = DSSetHandleSize(h as *mut c_void, size + 4);
if err != 0 {
return err;
}
let ptr = *h;
if ptr.is_null() {
return 1;
}
(*ptr).cnt = size as i32;
let dst = (*ptr).str.as_mut_ptr();
copy_nonoverlapping(bytes.as_ptr(), dst, size);
}
0 // mgNoErr
}
And called from LabVIEW:

So simple. And that’s it — clean, simple, and fully LabVIEW‑compatible.
Code.