跳到主要内容

PDO 输入输出

通过 slave.pdo 访问。对齐 C#:请用 CopyInputPdo / WriteOutputPdo generation 整帧 API。

PDO 周期与邮箱的关系

邮箱通信自动附带在 PDO 周期中,不占用额外帧。邮箱响应延迟约 2-3 个 PDO 周期。

应用层不是零拷贝指针

Python 主路径是 generation 整帧复制:读走 CopySlaveInputPdoslave.pdo.inputs / as_memoryview),写走 WriteSlaveOutputPdoslave.pdo.write_outputs)。调用方拿到的是 owned 快照,不是 IOmap 指针。

内核 SHM 零拷贝只存在于驱动内部,不向应用层暴露指针。不要再把 get_input_data_pointerPDOArrayInstancebind_pdo_struct 当成 live overlay——指针入口已退场(固定返回 0 / fail-closed);bind_pdo_struct 只是 from_buffer_copy 独立快照,改字段不会写回。

主路径:generation 整帧

inputs / write_outputs

@property
def inputs(self) -> Optional[bytes] # CopySlaveInputPdo 完整 TxPDO 快照

@property
def outputs(self) -> Optional[bytes] # CopySlaveOutputPdo 完整 RxPDO 快照

def write_outputs(self, data: bytes) -> bool # WriteSlaveOutputPdo;长度必须相等,无截断

write_outputs 是单 owner 完整帧入口,禁止当局部/typed/batch 读改写用。局部更新走版本化 Copy→patch→commit。

示例:

import struct

raw_input = slave.pdo.inputs
if raw_input and len(raw_input) >= 6:
status_word, actual_pos = struct.unpack_from('<Hi', raw_input, 0)
print(f"StatusWord=0x{status_word:04X} pos={actual_pos}")

frame = bytearray(slave.pdo.outputs or b'')
if len(frame) >= 6:
struct.pack_into('<Hi', frame, 0, 0x000F, 10000)
ok = slave.pdo.write_outputs(bytes(frame))
if not ok:
# 如实处理失败,不要假定已写入
pass

as_memoryview()

def as_memoryview(dll, master_index, slave_index, is_input: bool = True) -> memoryview

owned 只读快照,不是 live IOmap view。输出修改必须走 write_outputs / 版本化事务。

read_input_data_direct() / write_output_data_direct()

def read_input_data_direct(self, buffer: bytearray, offset: int = 0, length: int = 0) -> int
def write_output_data_direct(self, data: bytes, offset: int = 0, length: int = 0) -> int

读:native 整帧复制后写入目标缓冲。写:局部数据先合并进完整 RxPDO,再版本化提交(不是 GetIO overlay)。

同一路径上的便捷包装

下列入口不是第二套 PDO API,内部仍走 Copy/Write 整帧。

类型化读写

read_uint16(offset) / write_uint16(offset, val) 等从完整帧快照解析或版本化 patch。错误读折叠为 0,无法区分真零值;新代码应先取 inputsstruct.unpack_from

bind_pdo_struct()

def bind_pdo_struct(self, struct_type, is_input: bool = True)

实际语义:对完整帧快照做 ctypes.Structure.from_buffer_copy不持有 native live pointer。改结构体字段不会写回 RxPDO;写入请组完整帧后 write_outputs

batch_read() / batch_write()

一次完整输入快照切片;批量写走单个版本化事务。越界整批失败,不静默截断。

已退场(不要再用)

旧写法现状
get_input_data_pointer() / get_output_data_pointer()GetIO 已退场,固定返回 0
PDOArrayInstance / PDODataItem 裸指针构造即 DeprecationWarning,访问抛错
get_input_memoryview() 当 live 可写 IOmap只读 owned 快照
bind_pdo_struct 当零拷贝 overlay独立快照,改了不写回
inputs_mapping_info['pointer']固定为 0

需要结构体视图时:先 inputs / CopySlaveInputPdo,再 struct.unpack_fromfrom_buffer_copy。不要假设能拿到跨周期仍有效的 IOmap 指针。