linuxcnc-hal-sys 0.1.7

Generated, unsafe Rust bindings to the LinuxCNC HAL submodule
Documentation

LinuxCNC HAL Rust bindings

CircleCI Crates.io Docs.rs Liberapay

Provides unsafe, non-realtime Rust bindings for the LinuxCNC hal module. Useful for writing drivers for external hardware.

For a safe, high-level interface see the linuxcnc-hal crate.

cargo add linuxcnc-hal-sys

Please consider becoming a sponsor so I may continue to maintain this crate in my spare time!

Binding versions

This crate LinuxCNC version
v0.1.7 v2.7.15
v0.1.6 v2.7.15

Documentation

Example

More examples can be found in the examples/ folder.

use linuxcnc_hal_sys::*;
use signal_hook::iterator::Signals;
use std::{ffi::CString, mem, thread, time::Duration};

unsafe {
    let ret = hal_init(CString::new("pins").unwrap().as_ptr() as *const i8);

    // Check that component was created successfully
    let component_id = match ret {
        x if x == -(EINVAL as i32) => panic!("Failed to initialise component"),
        x if x == -(ENOMEM as i32) => panic!("Not enough memory to initialise component"),
        id if id > 0 => id,
        code => unreachable!("Hit unreachable error code {}", code),
    };

    println!("Component registered with ID {}", component_id);

    let signals = Signals::new(&[signal_hook::SIGTERM, signal_hook::SIGINT]).unwrap();

    let storage = hal_malloc(mem::size_of::<*mut f64>() as i64) as *mut *mut f64;

    if storage.is_null() {
        panic!("Failed to allocate storage");
    }

    let pin_name = CString::new("pins.input-1").unwrap();

    let ret = hal_pin_float_new(
        pin_name.as_ptr() as *const i8,
        hal_pin_dir_t_HAL_IN,
        storage,
        component_id,
    );

    // Check that pin was registered successfully
    match ret {
        0 => println!("Pin registered successfully"),
        x if x == -(EINVAL as i32) => panic!("Failed to register pin"),
        x if x == -(EPERM as i32) => {
            panic!("HAL is locked. Register pins before calling hal_ready()`")
        }
        x if x == -(ENOMEM as i32) => panic!("Failed to register pin"),
        code => unreachable!("Hit unreachable error code {}", code),
    }

    let ret = hal_ready(component_id);

    // Check that component is ready
    match ret {
        0 => println!("Component is ready"),
        x if x == -(EINVAL as i32) => panic!("HAL component was not found or is already ready"),
        code => unreachable!("Hit unreachable error code {}", code),
    }

    while !signals.pending().any(|signal| match signal {
        signal_hook::SIGTERM | signal_hook::SIGINT | signal_hook::SIGKILL => true,
        _ => false,
    }) {
        println!("Input {:?}", **storage);

        thread::sleep(Duration::from_millis(500));
    }
}

Development

Setup

bindgen must be set up correctly. Follow the requirements section of its docs.

To run and debug any HAL components, the LinuxCNC simulator can be set up. There's a guide here for Linux Mint (and other Debian derivatives).

Build

cargo build

You can also run ./build.sh to run all the commands that would normally be run in CI.

Test

cargo test

Build docs

The docs make heavy use of intra-rustdoc-links. To get the links to render correctly, run with nightly:

rustup toolchain add nightly
cargo +nightly doc

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.