Skip to main content

FunctionObject

Struct FunctionObject 

Source
pub struct FunctionObject(/* private fields */);
Expand description

Wrapper over the openDAQ daqFunction interface.

Implementations§

Source§

impl FunctionObject

Source

pub fn from_fn( function: impl Fn(&[Value]) -> Result<Value> + Send + Sync + 'static, ) -> Result<FunctionObject>

Wrap a Rust closure as an openDAQ function. openDAQ invokes it – from Rust or from native code – with the decoded arguments; the returned Value is boxed back for the caller.

Calls the openDAQ C function daqFunction_createFunction().

Examples found in repository?
examples/smoke.rs (lines 54-58)
7fn main() -> opendaq::Result<()> {
8    let instance = Instance::new()?;
9
10    println!("Available devices:");
11    for info in instance.available_devices()? {
12        println!(" - {}: {}", info.connection_string()?, info.name()?);
13    }
14
15    let device = instance.add_device("daqref://device0")?.expect("device");
16    println!("Added device: {}", device.name()?);
17
18    let channel = instance
19        .find_component("Dev/RefDev0/IO/AI/RefCh0")?
20        .expect("reference channel not found")
21        .cast::<Channel>()?;
22    let signal = &channel.signals()?[0];
23
24    // Batched property updates.
25    {
26        let batch = BatchedPropertyUpdate::new(&[&device, &channel])?;
27        device.set_property_value("GlobalSampleRate", 1000)?;
28        channel.set_property_value("Frequency", 50.0)?;
29        batch.commit()?;
30    }
31    println!(
32        "GlobalSampleRate = {}",
33        device.property_value("GlobalSampleRate")?
34    );
35
36    // Stream reading with domain + tick conversion.
37    let reader = StreamReader::<f64>::new(signal)?;
38    let (samples, ticks) = reader.read_with_domain(100, 2000)?;
39    println!(
40        "read {} samples, {} ticks",
41        samples.sample_count(),
42        ticks.len()
43    );
44    let converter = TickConverter::from_signal(signal)?;
45    if let Some(first) = ticks.first() {
46        println!(
47            "first tick {} -> {:?}",
48            first,
49            converter.tick_to_system_time(*first)
50        );
51    }
52
53    // Callables: a Rust closure as an openDAQ function, called through openDAQ.
54    let sum = FunctionObject::from_fn(|args| {
55        let a = args[0].as_i64().unwrap_or(0);
56        let b = args[1].as_i64().unwrap_or(0);
57        Ok(Value::from(a + b))
58    })?;
59    let result = sum.call(&[Value::from(20), Value::from(22)])?;
60    println!("sum(20, 22) = {result}");
61
62    // Events: subscribe to property changes on the channel.
63    let events = channel
64        .on_property_value_write("Amplitude")?
65        .expect("event");
66    let handler = events.subscribe(|_sender, args| {
67        if let Some(args) = args {
68            println!("  event fired: {args}");
69        }
70    })?;
71    channel.set_property_value("Amplitude", 2.5)?;
72    events.unsubscribe(&handler)?;
73    channel.set_property_value("Amplitude", 1.0)?;
74    println!("Amplitude = {}", channel.property_value("Amplitude")?);
75
76    Ok(())
77}
Source

pub fn call(&self, args: &[Value]) -> Result<Value>

Call the function with natural Rust arguments and unbox its result.

Calls the openDAQ C function daqFunction_call().

Examples found in repository?
examples/call_function_property.rs (line 24)
17fn main() -> opendaq::Result<()> {
18    let instance = Instance::new()?;
19    let device = instance.add_device("daqref://device0")?.expect("device");
20
21    let sum = function_property(&device, "Protected.Sum")?;
22    println!(
23        "Protected.Sum(7, 5)   = {}",
24        sum.call(&[Value::from(7), Value::from(5)])?
25    );
26    println!(
27        "Protected.Sum(40, 2)  = {}",
28        sum.call(&[Value::from(40), Value::from(2)])?
29    );
30    println!(
31        "Protected.Sum(100, 1) = {}",
32        function_property(&device, "Protected.Sum")?.call(&[Value::from(100), Value::from(1)])?
33    );
34
35    // SumList takes a single argument: a list of numbers.
36    let sum_list = function_property(&device, "Protected.SumList")?;
37    println!(
38        "Protected.SumList([1, 2, 3, 4]) = {}",
39        sum_list.call(&[Value::from(vec![1, 2, 3, 4])])?
40    );
41    println!(
42        "Protected.SumList([]) = {}",
43        sum_list.call(&[Value::List(Vec::new())])?
44    );
45
46    // `call` passes arguments straight through, and an implementation is free
47    // to ignore extras (the reference device's Sum does).  The declared
48    // signature lives in the property's callable info -- check the arity
49    // there before calling when it matters.
50    let info = device
51        .property("Protected.Sum")?
52        .expect("Sum property")
53        .callable_info()?
54        .expect("callable info");
55    let expected = info.arguments()?.len();
56    let args = [Value::from(1), Value::from(2), Value::from(3)];
57    if args.len() == expected {
58        println!("\nProtected.Sum(1, 2, 3) = {}", sum.call(&args)?);
59    } else {
60        println!(
61            "\nWrong arity is rejected: Protected.Sum expects {expected} arguments, got {}.",
62            args.len()
63        );
64    }
65    Ok(())
66}
More examples
Hide additional examples
examples/smoke.rs (line 59)
7fn main() -> opendaq::Result<()> {
8    let instance = Instance::new()?;
9
10    println!("Available devices:");
11    for info in instance.available_devices()? {
12        println!(" - {}: {}", info.connection_string()?, info.name()?);
13    }
14
15    let device = instance.add_device("daqref://device0")?.expect("device");
16    println!("Added device: {}", device.name()?);
17
18    let channel = instance
19        .find_component("Dev/RefDev0/IO/AI/RefCh0")?
20        .expect("reference channel not found")
21        .cast::<Channel>()?;
22    let signal = &channel.signals()?[0];
23
24    // Batched property updates.
25    {
26        let batch = BatchedPropertyUpdate::new(&[&device, &channel])?;
27        device.set_property_value("GlobalSampleRate", 1000)?;
28        channel.set_property_value("Frequency", 50.0)?;
29        batch.commit()?;
30    }
31    println!(
32        "GlobalSampleRate = {}",
33        device.property_value("GlobalSampleRate")?
34    );
35
36    // Stream reading with domain + tick conversion.
37    let reader = StreamReader::<f64>::new(signal)?;
38    let (samples, ticks) = reader.read_with_domain(100, 2000)?;
39    println!(
40        "read {} samples, {} ticks",
41        samples.sample_count(),
42        ticks.len()
43    );
44    let converter = TickConverter::from_signal(signal)?;
45    if let Some(first) = ticks.first() {
46        println!(
47            "first tick {} -> {:?}",
48            first,
49            converter.tick_to_system_time(*first)
50        );
51    }
52
53    // Callables: a Rust closure as an openDAQ function, called through openDAQ.
54    let sum = FunctionObject::from_fn(|args| {
55        let a = args[0].as_i64().unwrap_or(0);
56        let b = args[1].as_i64().unwrap_or(0);
57        Ok(Value::from(a + b))
58    })?;
59    let result = sum.call(&[Value::from(20), Value::from(22)])?;
60    println!("sum(20, 22) = {result}");
61
62    // Events: subscribe to property changes on the channel.
63    let events = channel
64        .on_property_value_write("Amplitude")?
65        .expect("event");
66    let handler = events.subscribe(|_sender, args| {
67        if let Some(args) = args {
68            println!("  event fired: {args}");
69        }
70    })?;
71    channel.set_property_value("Amplitude", 2.5)?;
72    events.unsubscribe(&handler)?;
73    channel.set_property_value("Amplitude", 1.0)?;
74    println!("Amplitude = {}", channel.property_value("Amplitude")?);
75
76    Ok(())
77}

Methods from Deref<Target = BaseObject>§

Source

pub fn cast<T: Interface>(&self) -> Result<T>

Query this object for interface T, returning a wrapper that owns its own reference.

This is a genuine queryInterface: an object’s interfaces live at different virtual-table offsets, so the pointer for one interface is not binary-compatible with another and must be queried, not merely reinterpreted. Fails with an openDAQ error when the object does not implement T (use BaseObject::try_cast / BaseObject::is_a to probe first).

For the few interfaces the C API exposes no GUID for (T::interface_id() is None), the pointer is reinterpreted unchecked, which is sound only when the object really lies on T’s inheritance chain.

Examples found in repository?
examples/call_function_property.rs (line 14)
10fn function_property(device: &Device, name: &str) -> opendaq::Result<FunctionObject> {
11    device
12        .property_value(name)?
13        .into_object()?
14        .cast::<FunctionObject>()
15}
More examples
Hide additional examples
examples/component_tree.rs (line 48)
46fn children(component: &Component) -> opendaq::Result<Vec<Component>> {
47    if component.is_a::<Folder>() {
48        component.cast::<Folder>()?.items()
49    } else {
50        Ok(Vec::new())
51    }
52}
examples/multireader.rs (line 24)
20fn find_channel(instance: &Instance, path: &str) -> opendaq::Result<Channel> {
21    instance
22        .find_component(path)?
23        .unwrap_or_else(|| panic!("channel {path} not found"))
24        .cast::<Channel>()
25}
examples/search_filter.rs (line 25)
22fn show<T: Interface>(label: &str, components: Vec<T>) -> opendaq::Result<()> {
23    let ids = components
24        .iter()
25        .map(|c| c.to_base_object().cast::<Component>()?.local_id())
26        .collect::<opendaq::Result<Vec<_>>>()?;
27    let listing = if ids.is_empty() {
28        "(none)".to_string()
29    } else {
30        ids.join(", ")
31    };
32    println!("{label}\n    => {listing}\n");
33    Ok(())
34}
35
36fn main() -> opendaq::Result<()> {
37    let instance = Instance::new()?;
38    instance.add_device("daqref://device0")?;
39    let root = instance.root_device()?.expect("root device");
40
41    // Give a couple of channels some tags, so the tag filter has something to
42    // match.  (RefCh0 and RefCh1 come from the reference device unlabelled.)
43    let everything = SearchFilter::recursive(&SearchFilter::any()?)?;
44    for channel in root.channels_with(Some(&everything))? {
45        let tags = channel.tags()?.expect("tags").cast::<TagsPrivate>()?;
46        tags.add("analog")?;
47        if channel.local_id()? == "RefCh0" {
48            tags.add("primary")?;
49        }
50    }
51
52    show(
53        "channels, no filter (immediate children only)",
54        root.channels()?,
55    )?;
56
57    show(
58        "channels, recursive(any)",
59        root.channels_with(Some(&SearchFilter::recursive(&SearchFilter::any()?)?))?,
60    )?;
61
62    show(
63        "channels, recursive(id = RefCh1)",
64        root.channels_with(Some(&SearchFilter::recursive(&SearchFilter::local_id(
65            "RefCh1",
66        )?)?))?,
67    )?;
68
69    let ai0_or_ai1 = SearchFilter::or(
70        &SearchFilter::local_id("AI0")?,
71        &SearchFilter::local_id("AI1")?,
72    )?;
73    show(
74        "signals, recursive(id = AI0 OR id = AI1)",
75        root.signals_with(Some(&SearchFilter::recursive(&ai0_or_ai1)?))?,
76    )?;
77
78    let not_ref_ch1 = SearchFilter::not(&SearchFilter::local_id("RefCh1")?)?;
79    show(
80        "channels, recursive(NOT id = RefCh1)",
81        root.channels_with(Some(&SearchFilter::recursive(&not_ref_ch1)?))?,
82    )?;
83
84    let analog_and_not_ref_ch1 = SearchFilter::and(
85        &SearchFilter::required_tags(vec!["analog"])?,
86        &SearchFilter::not(&SearchFilter::local_id("RefCh1")?)?,
87    )?;
88    show(
89        "channels, recursive(tag = analog AND NOT id = RefCh1)",
90        root.channels_with(Some(&SearchFilter::recursive(&analog_and_not_ref_ch1)?))?,
91    )?;
92
93    Ok(())
94}
examples/streamreader.rs (line 15)
8fn main() -> opendaq::Result<()> {
9    let instance = Instance::new()?;
10    instance.add_device("daqref://device0")?;
11
12    let channel = instance
13        .find_component("Dev/RefDev0/IO/AI/RefCh0")?
14        .expect("reference channel not found")
15        .cast::<Channel>()?;
16    let signal = &channel.signals()?[0];
17
18    let reader = StreamReader::<f64>::new(signal)?;
19    println!("some samples: {:?}", reader.read(100, 1000)?.values());
20    println!("and more samples: {:?}", reader.read(100, 1000)?.values());
21    println!("and more still: {:?}", reader.read(100, 1000)?.values());
22    Ok(())
23}
examples/streamreader_with_timestamps.rs (line 46)
39fn main() -> opendaq::Result<()> {
40    let instance = Instance::new()?;
41    instance.add_device("daqref://device0")?;
42
43    let channel = instance
44        .find_component("Dev/RefDev0/IO/AI/RefCh0")?
45        .expect("reference channel not found")
46        .cast::<Channel>()?;
47    let signal = &channel.signals()?[0];
48
49    let reader = StreamReader::<f64>::new(signal)?;
50    let converter = TickConverter::from_signal(signal)?;
51
52    let (values, ticks) = reader.read_with_domain(10, 2000)?;
53    println!("Read {} samples:", values.sample_count());
54    for (value, tick) in values.iter().zip(&ticks) {
55        println!(
56            "  {value:.6} @ {}",
57            timestamp_to_string(converter.tick_to_unix_nanos(*tick))
58        );
59    }
60    Ok(())
61}
Source

pub fn try_cast<T: Interface>(&self) -> Option<T>

Like BaseObject::cast, but returns None when the object does not implement T.

Source

pub fn is_a<T: Interface>(&self) -> bool

True when the object implements interface T (a borrowInterface probe; adds no reference). Returns false for interfaces without a GUID in the C API, which cannot be probed.

Examples found in repository?
examples/component_tree.rs (line 47)
46fn children(component: &Component) -> opendaq::Result<Vec<Component>> {
47    if component.is_a::<Folder>() {
48        component.cast::<Folder>()?.items()
49    } else {
50        Ok(Vec::new())
51    }
52}
Source

pub fn hash_code(&self) -> Result<usize>

The object’s hash code.

Source

pub fn equals<T: Interface>(&self, other: &T) -> Result<bool>

True when openDAQ considers the two objects equal.

Source

pub fn ptr_eq<T: Interface>(&self, other: &T) -> bool

Identity comparison: both wrappers refer to the same native object. (Note that pointers to different interfaces of one object differ; this compares the raw interface pointers.)

Source

pub fn dispose(&self) -> Result<()>

Release the object’s internal resources early (openDAQ dispose). The wrapper itself stays alive; most callers never need this.

Source

pub fn component_kind(&self) -> Option<ComponentKind>

The most-derived component interface this object implements (probed most-derived first), or None when it is not a component.

Examples found in repository?
examples/component_tree.rs (line 10)
8fn type_label(component: &Component) -> String {
9    component
10        .component_kind()
11        .map_or_else(|| "Component".to_string(), |kind| format!("{kind:?}"))
12}
Source

pub fn to_value(&self) -> Result<Value>

The natural Rust value of this object: a boxed scalar yields its native value, a daq list a Vec, a daq dict key/value pairs – with elements converted recursively – and an object with no natural Rust form (a device, a property object, …) comes back as Value::Object, for the caller to BaseObject::cast.

Trait Implementations§

Source§

impl Clone for FunctionObject

Source§

fn clone(&self) -> FunctionObject

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for FunctionObject

Source§

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

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

impl Deref for FunctionObject

Source§

type Target = BaseObject

The resulting type after dereferencing.
Source§

fn deref(&self) -> &BaseObject

Dereferences the value.
Source§

impl Display for FunctionObject

Source§

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

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

impl From<&FunctionObject> for Value

Source§

fn from(value: &FunctionObject) -> Value

Converts to this type from the input type.
Source§

impl From<FunctionObject> for Value

Source§

fn from(value: FunctionObject) -> Value

Converts to this type from the input type.
Source§

impl Interface for FunctionObject

Source§

const NAME: &'static str = "daqFunction"

The openDAQ interface name, e.g. "daqDevice".
Source§

fn interface_id() -> Option<IntfID>

The interface’s GUID, or None for the few coretypes interfaces the C API exposes no id for (IBaseObject, IFunction, IProcedure, …).
Source§

unsafe fn from_raw(ptr: *mut c_void) -> Option<Self>

Adopt an owned raw interface pointer (takes ownership of one reference; does not add one). Returns None for null. Read more
Source§

fn as_base_object(&self) -> &BaseObject

This wrapper viewed as the root IBaseObject interface.
Source§

fn as_raw(&self) -> *mut c_void

The raw interface pointer (still owned by this wrapper).
Source§

fn to_base_object(&self) -> BaseObject

A new owning BaseObject handle to the same underlying object.

Auto Trait Implementations§

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> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. 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> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
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.