pub struct FunctionObject(/* private fields */);Expand description
Wrapper over the openDAQ daqFunction interface.
Implementations§
Source§impl FunctionObject
impl FunctionObject
Sourcepub fn from_fn(
function: impl Fn(&[Value]) -> Result<Value> + Send + Sync + 'static,
) -> Result<FunctionObject>
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?
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}Sourcepub fn call(&self, args: &[Value]) -> Result<Value>
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?
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
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>§
Sourcepub fn cast<T: Interface>(&self) -> Result<T>
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?
More examples
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(¬_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}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}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}Sourcepub fn try_cast<T: Interface>(&self) -> Option<T>
pub fn try_cast<T: Interface>(&self) -> Option<T>
Like BaseObject::cast, but returns None when the object does not
implement T.
Sourcepub fn is_a<T: Interface>(&self) -> bool
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.
Sourcepub fn equals<T: Interface>(&self, other: &T) -> Result<bool>
pub fn equals<T: Interface>(&self, other: &T) -> Result<bool>
True when openDAQ considers the two objects equal.
Sourcepub fn ptr_eq<T: Interface>(&self, other: &T) -> bool
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.)
Sourcepub fn dispose(&self) -> Result<()>
pub fn dispose(&self) -> Result<()>
Release the object’s internal resources early (openDAQ dispose).
The wrapper itself stays alive; most callers never need this.
Sourcepub fn component_kind(&self) -> Option<ComponentKind>
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.
Sourcepub fn to_value(&self) -> Result<Value>
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
impl Clone for FunctionObject
Source§fn clone(&self) -> FunctionObject
fn clone(&self) -> FunctionObject
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for FunctionObject
impl Debug for FunctionObject
Source§impl Deref for FunctionObject
impl Deref for FunctionObject
Source§type Target = BaseObject
type Target = BaseObject
Source§fn deref(&self) -> &BaseObject
fn deref(&self) -> &BaseObject
Source§impl Display for FunctionObject
impl Display for FunctionObject
Source§impl From<&FunctionObject> for Value
impl From<&FunctionObject> for Value
Source§fn from(value: &FunctionObject) -> Value
fn from(value: &FunctionObject) -> Value
Source§impl From<FunctionObject> for Value
impl From<FunctionObject> for Value
Source§fn from(value: FunctionObject) -> Value
fn from(value: FunctionObject) -> Value
Source§impl Interface for FunctionObject
impl Interface for FunctionObject
Source§fn interface_id() -> Option<IntfID>
fn interface_id() -> Option<IntfID>
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>
unsafe fn from_raw(ptr: *mut c_void) -> Option<Self>
None for null. Read moreSource§fn as_base_object(&self) -> &BaseObject
fn as_base_object(&self) -> &BaseObject
IBaseObject interface.Source§fn to_base_object(&self) -> BaseObject
fn to_base_object(&self) -> BaseObject
BaseObject handle to the same underlying object.