samcrow / rust-xplm

Rust interfaces to the X-Plane plugin SDK
Apache License 2.0
41 stars 15 forks source link

FlightLoop handler isn't called #6

Closed ISO50 closed 3 years ago

ISO50 commented 3 years ago

Hi,

I fail to setup a FlightLoophandler.

  1. I wrote a flight loop handler that uses xplm::debug to write a log message. The handler was registered in the enable function.
  2. When the plugin loads, debug message from start and enable appear in the log.
  3. After starting a flight the Plugin is visible in the PluginAdmin. But it doesn't show an callback handlers beeing active for the plugin. Also Xplane never calls flight_loop_callback while debugging shows that a loop-id is returned, also this line to schedule the loop seems to be executed.

System info:

samcrow commented 3 years ago

Thanks for reporting this. I don't have a working test setup to try to reproduce the problem, but if you share your plugin code I can look at it and try to find the cause.

ISO50 commented 3 years ago

Hi thanks for your reply.

The code is based on your example code and I tried to move it into a flight loop. But got stuck already on the handler thing.

I am not sure if the way I build the project can influence runtime bindings. I started with the simple shell script. I tried the same but setting up the xpl in a aircraft folder but also did not work.

cargo build --lib --release
copy  target\release\test_plugin.dll "..\..\..\X-Plane 11\Resources\plugins\test_plugin.xpl"
#[macro_use(xplane_plugin)]
extern crate xplm;

use std::time::Duration;

use xplm::plugin::{Plugin, PluginInfo};
use xplm::flight_loop::{FlightLoop, LoopState};

use xplm::data::borrowed::{DataRef, FindError};
use xplm::data::{ReadOnly, ReadWrite, DataRead, ArrayRead, StringRead};

struct DatarefPlugin {
    has_joystick: DataRef<bool, ReadOnly>,
    earth_mu: DataRef<f32, ReadOnly>,
    date: DataRef<i32, ReadWrite>,
    sim_build_string: DataRef<[u8], ReadOnly>,
    latitude: DataRef<f64, ReadOnly>,
    joystick_axis_values: DataRef<[f32], ReadOnly>,
    battery_on: DataRef<[i32], ReadWrite>,
}

impl DatarefPlugin {
    fn test_datarefs(&mut self) {
        xplm::debug(format!("has joystick: {}\n", self.has_joystick.get()));
        xplm::debug(format!("earth mu: {}\n", self.earth_mu.get()));
        xplm::debug(format!("date: {}\n", self.date.get()));
        xplm::debug(format!(
            "simulator build: {}\n",
            self.sim_build_string.get_as_string().unwrap_or(
                "unknown".into(),
            )
        ));
        xplm::debug(format!("latitude: {}\n", self.latitude.get()));
        xplm::debug(format!(
            "joystick axis values: {:?}\n",
            self.joystick_axis_values.as_vec()
        ));
        xplm::debug(format!("battery on: {:?}\n", self.battery_on.as_vec()));
    }

    fn activate_log_in_flight(&mut self) {

        let handler = |loop_state: &mut LoopState| {
            println!("Flight loop callback running");
            xplm::debug(format!("Flight loop callback was called: \n"));
        };

        xplm::debug(format!("Init Flight loop (activate_log_in_flight)\n"));
        let mut flight_loop = FlightLoop::new(handler);
        // flight_loop.schedule_immediate();
        flight_loop.schedule_after_loops(1);
        xplm::debug(format!("called schedule_after_loops()\n"));
    }
}

impl Plugin for DatarefPlugin {
    type Error = FindError;
    fn start() -> Result<Self, Self::Error> {
        xplm::debug(format!("Plugin Start was called\n"));
        let mut plugin = DatarefPlugin {
            has_joystick: DataRef::find("sim/joystick/has_joystick")?,
            earth_mu: DataRef::find("sim/physics/earth_mu")?,
            date: DataRef::find("sim/time/local_date_days")?.writeable()?,
            sim_build_string: DataRef::find("sim/version/sim_build_string")?,
            latitude: DataRef::find("sim/flightmodel/position/latitude")?,
            joystick_axis_values: DataRef::find("sim/joystick/joystick_axis_values")?,
            battery_on: DataRef::find("sim/cockpit2/electrical/battery_on")?.writeable()?,
        };
        plugin.test_datarefs();
        Ok(plugin)
    }

    fn info(&self) -> PluginInfo {
        xplm::debug(format!("Plugin info was called\n"));
        PluginInfo {
            name: "Dataref test".into(),
            signature: "c31afe5a-0d3e-4711-afcb-65eb5ad15cd6".into(),
            description: "Dataref reader".into(),
        }
    }

    fn enable(&mut self) -> Result<(), Self::Error> {
        // self.test_datarefs();
        xplm::debug(format!("Plugin enable was called\n"));
        self.activate_log_in_flight();
        Ok(())
    }

    fn disable(&mut self) {
        xplm::debug(format!("Plugin disable was called!\n"));
        self.test_datarefs();
    }
}

xplane_plugin!(DatarefPlugin);
samcrow commented 3 years ago

I think the problem is that the flight loop object goes out of scope at the end of the activate_log_in_flight function. Its Drop implementation calls XPLMDestroyFlightLoop, so X-Plane never calls the callback.

If you make the flight loop part of the DatarefPlugin struct, it should work.

ISO50 commented 3 years ago

@samcrow that was the correct hint. Adding the handler to the main plugin data structure solved the issue.

Thank you very much 😊