export_plugin!() { /* proc-macro */ }Expand description
Generates the two symbols loaded by ETS2 or ATS for one plugin instance.
After the framework validates the SDK version, initialization pointer, and
idle lifecycle state, the input is evaluated exactly once for that accepted
initialization attempt. It may be a constructor, a struct literal, or any
other expression whose value implements
scs_sdk_plugin::TelemetryPlugin. The compiler enforces that trait bound
when the generated factory coerces the value into the framework’s plugin
object; an expression returning another type is a compile-time error.
The expansion owns a process-lifetime runtime object and emits:
scs_telemetry_init, using the SCS system calling convention;scs_telemetry_shutdown, which drains registrations before dropping the active plugin value.
ABI functions and raw SDK pointers exist only inside the expansion and
scs-sdk-plugin; the invoking application’s source remains ordinary safe
Rust.
Invoke this macro exactly once in a plugin cdylib. Both exported names are
fixed by the SCS loader contract, so two invocations in one link unit would
define the same process runtime and symbols twice.
§Compile fixtures
The example below remains ignored as a rustdoc test because this proc-macro
crate cannot depend back on scs-sdk-plugin without creating a Cargo
dependency cycle. The same consumer code is compiled independently in
scs-sdk-plugin/tests/fixtures/export-plugin/pass. A sibling fixture omits
the trait implementation and must fail with E0277. Windows and Linux fixture
builds also inspect the finished dynamic export tables for both SCS symbols.
§Example
#[derive(Default)]
struct MyPlugin;
impl scs_sdk_plugin::TelemetryPlugin for MyPlugin {
fn metadata(&self) -> scs_sdk_plugin::PluginMetadata {
scs_sdk_plugin::PluginMetadata::new("My Plugin", env!("CARGO_PKG_VERSION"))
}
fn compatibility(&self) -> scs_sdk_plugin::PluginCompatibility {
use scs_sdk_plugin::sdk::{TelemetryApiVersion, game};
use scs_sdk_plugin::{Game, GameCompatibility, PluginCompatibility};
const GAMES: &[GameCompatibility] = &[GameCompatibility::new(
Game::EuroTruckSimulator2,
game::ets2::V1_00,
)];
PluginCompatibility::new(TelemetryApiVersion::V1_00, GAMES)
}
fn initialize(
&mut self,
_context: &mut scs_sdk_plugin::PluginContext<'_>,
) -> scs_sdk_plugin::PluginResult {
Ok(())
}
}
scs_sdk_plugin::export_plugin!(MyPlugin::default());