Skip to content

Expanded callback context #303

@Powerbyte7

Description

@Powerbyte7

When trying to process OSDP events, I would like access to additional context like the PD address and vendor code. Right now that's inconvenient, because there's no direct way to access the CP handle from inside the callback. In C/C++, you have to pass the pointer using the callback data, or statically store it in memory. Rust's borrow checking forbids both entirely, requiring events to be stored so the context can be retrieved after the callback.

int event_handler(void *data, int pd, struct osdp_event *event) {
    auto cp = reinterpret_cast<ControlPanel*>(data); // This works
    struct osdp_pd_id pd_info;
    int error = cp.get_pd_id(pd, &pd_info);
    return 0;
}

cp.setup(&cp_channel, 1, pd_info);
cp.set_event_callback(event_handler, &cp); // ... but now we cannot move cp anymore
let pd_info = vec! [ PdInfo::new(...), ... ];
let mut cp = ControlPanel::new(pd_info)?;
let events = vec![];
cp.set_event_callback(|pd, event| {
    // No way to access cp, it's borrowed. A Refcell does not solve this.
    events.push(event); // Only solution is to process events outside callback. 
});
loop {
    cp.refresh();
    cp.send_command(0, OsdpCommand::new(...));
}

I think this problem can be solved by passing const osdp_t *ctx to CP callbacks, and exposing it as &ControlPanel in the Rust crate. This would break existing code, but make the API a lot more convenient. My problem would also be solved by passing additional PD info in the callback, but I think the former is more futureproof and convenient.

If this sounds good, I can get started on a PR. This might be a nice addition for v4.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions