birkenfeld / ads-rs

Rust crate to access PLCs via the Beckhoff ADS protocol
https://crates.io/crates/ads
Apache License 2.0
45 stars 8 forks source link

Can you give me an example of read-write structs? #11

Closed puli1027 closed 1 year ago

puli1027 commented 1 year ago

I wanted to read and write structs, but I didn't succeed。

birkenfeld commented 1 year ago

Hi, can you be a bit more specific - what did you try, and how is your data laid out?

puli1027 commented 1 year ago

I try defined a Struct ,but there is a error.

use zerocopy::{AsBytes, FromBytes};
#[derive(Default,AsBytes,FromBytes)]
#[repr(C)]
pub struct TestStruct {
    pub var1: i16,
    pub var2: i32,
    pub var3: f32,
    pub var4: f64,
}

image

error[E0277]: the trait bound `TestStruct: HasPadding<false>` is not satisfied
 --> src\models\my_model.rs:5:12
  |
5 | pub struct TestStruct {
  |            ^^^^^^^^^^ the trait `HasPadding<false>` is not implemented for `TestStruct`
  |
  = help: the trait `HasPadding<true>` is implemented for `TestStruct`
note: required by a bound in `assert_no_padding`
 --> src\models\my_model.rs:3:18
  |
3 | #[derive(Default,AsBytes,FromBytes)]
  |                  ^^^^^^^ required by this bound in `assert_no_padding`
  = note: this error originates in the derive macro `AsBytes` (in Nightly builds, run with -Z macro-backtrace for more info)
birkenfeld commented 1 year ago

OK, that's because even if repr(C) padding is added if field layout requires it. Here, 16 bits of padding is inserted between var1 and var2 because the i32 needs to lie at a 32-bit boundary.

Can you try #[repr(C, packed)] instead, that should remove the padding?

puli1027 commented 1 year ago

The error on the structure disappeared

use zerocopy::{AsBytes, FromBytes};

#[derive(Default,AsBytes,FromBytes)]
#[repr(C,packed)]
pub struct TestStruct {
    pub var1: i16,
    pub var2: i32,
    pub var3: f32,
    pub var4: f64,
}

but,there are still errors in the code.

fn main() -> anyhow::Result<()> {
    // Open a connection to an ADS device identified by hostname/IP and port.
    // For TwinCAT devices, a route must be set to allow the client to connect.
    // The source AMS address is automatically generated from the local IP,
    // but can be explicitly specified as the third argument.
    let client = ads::Client::new(("plchost", ads::PORT), ads::Timeouts::none(),
                                  ads::Source::Auto)?;

    // Specify the target ADS device to talk to, by NetID and AMS port.
    // Port 851 usually refers to the first PLC instance.
    let device = client.device(ads::AmsAddr::new([5, 32, 116, 5, 1, 1].into(), 851));

    // Ensure that the PLC instance is running.
    assert!(device.get_state()?.0 == ads::AdsState::Run);

    // Request a handle to a named symbol in the PLC instance.
    let handle = Handle::new(device, "MY_SYMBOL")?;

    // Read data in form of an u32 from the handle.
    let value = handle.read_value::<TestStruct>()?;
    println!("MY_SYMBOL value is {}", value);

    // Connection will be closed when the client is dropped.
    Ok(())
}

Below is the error message

error[E0277]: the trait bound `TestStruct: zerocopy::AsBytes` is not satisfied
  --> src\ads_ffi\data_ffi.rs:72:37
   |
72 |     let value = handle.read_value::<TestStruct>()?;
   |                                     ^^^^^^^^^^ the trait `zerocopy::AsBytes` is not implemented for `TestStruct`
   |
   = help: the following other types implement trait `zerocopy::AsBytes`:
             ()
             AmsNetId
             PhantomData<T>
             String80
             WString80
             [T; 0]
             [T; 1024]
             [T; 10]
           and 100 others
note: required by a bound in `Handle::<'c>::read_value`
  --> D:\AppInstall\rust\.cargo\registry\src\mirrors.tuna.tsinghua.edu.cn-2eab394af869c8a2\ads-0.4.3\src\symbol.rs:54:36
   |
54 |     pub fn read_value<T: Default + AsBytes + FromBytes>(&self) -> Result<T> {
   |                                    ^^^^^^^ required by this bound in `Handle::<'c>::read_value`

Please give me some guidance,thanks

birkenfeld commented 1 year ago

I don't get this error. Please make sure that the version of zerocopy you depend on is the same as the one ads depends on (0.3.0). Otherwise there will be two incompatible versions in the dependency tree.

puli1027 commented 1 year ago

Indeed, when I changed the version of zerocopy to 0.3.0, the error disappeared. thanks so much!