Skip to content

Expose engineId on native plugin registrars on Linux and Windows - #196032

Open
tarrinneal wants to merge 2 commits into
flutter:masterfrom
tarrinneal:expose-plugin-registrar-engine-id-desktop
Open

tarrinneal wants to merge 2 commits into
flutter:masterfrom
tarrinneal:expose-plugin-registrar-engine-id-desktop

Conversation

@tarrinneal

@tarrinneal tarrinneal commented Nov 5, 2026 •

Copy link
Copy Markdown
Contributor

Follow-up to #195881, completing platform parity by exposing the engine identifier (corresponding to PlatformDispatcher.instance.engineId in Dart) directly on native plugin registrars on Linux and Windows so that FFI plugins can associate and clean up per-engine native state during plugin registration and detachment without access to internal engine APIs:

  • Linux: Adds fl_plugin_registrar_get_engine_id(FlPluginRegistrar*) to FlPluginRegistrar (fl_plugin_registrar.h).
  • Windows: Adds FlutterDesktopPluginRegistrarGetEngineId(FlutterDesktopPluginRegistrarRef) to the C API (flutter_windows.h) and PluginRegistrarWindows::GetEngineId() to the C++ client wrapper (plugin_registrar_windows.h).

Fixes #195876

Breaking Change Assessment

Unlike the @required Objective-C protocol property added on iOS and macOS in #195881 (which required updating custom FlutterPluginRegistrar test stubs in flutter/packages#13574 and has been tagged c: API break on #195881 / #195876 for release notes), this PR is non-breaking for both production plugins and custom test fakes/mocks:

  • Linux (FlPluginRegistrar): get_engine_id is appended to _FlPluginRegistrarInterface. GLib zero-initializes GTypeInterface structs prior to iface_init, and fl_plugin_registrar_get_engine_id guards against iface->get_engine_id == nullptr (returning 0), so existing GObject mock/fake FlPluginRegistrar implementations that do not assign iface->get_engine_id continue to compile and run without changes (verified by FlPluginRegistrarTest.LegacyFakeWithoutGetEngineId).
  • Windows (FlutterDesktopPluginRegistrarRef / PluginRegistrarWindows): FlutterDesktopPluginRegistrarGetEngineId is a standalone C function and PluginRegistrarWindows::GetEngineId() is a concrete, non-virtual method on a concrete class, requiring no overrides in existing test doubles.

Pre-launch Checklist

@tarrinneal
tarrinneal requested review from a team as code owners November 5, 2026 08:44
@flutter-dashboard flutter-dashboard Bot added the CICD Run CI/CD label Nov 5, 2026
@github-actions github-actions Bot added engine flutter/engine related. See also e: labels. platform-windows Building on or for Windows specifically platform-linux Building on or for Linux specifically a: desktop Running on desktop team-windows Owned by the Windows platform team team-linux Owned by the Linux platform team labels Nov 5, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces APIs to retrieve the unique engine identifier from the plugin registrar on both Linux and Windows platforms, along with corresponding unit tests. The review feedback points out a portability issue in fl_engine.cc, fl_view.cc, and flutter_windows.cc, where pointers are directly cast to int64_t using reinterpret_cast. To align with the Google C++ Style Guide, these pointers should be cast to intptr_t or uintptr_t first to avoid compilation issues on 32-bit platforms.

return fl_plugin_registrar_new(nullptr, self->binary_messenger,
self->texture_registrar);
self->texture_registrar,
reinterpret_cast<int64_t>(self));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

According to the Google C++ Style Guide (referenced by the Repository Style Guide), when casting a pointer to an integer, you should only cast to/from intptr_t or uintptr_t. Direct casting to int64_t using reinterpret_cast can lead to compilation errors or warnings on 32-bit platforms where pointer sizes differ from 64-bit integers. Casting to intptr_t first is portable and safe, and it will be implicitly promoted to int64_t.

                                 reinterpret_cast<intptr_t>(self));
References
  1. Google C++ Style Guide: When casting a pointer to an integer, use reinterpret_cast to intptr_t or uintptr_t. (link)

fl_engine_get_binary_messenger(self->engine),
fl_engine_get_texture_registrar(self->engine));
fl_engine_get_texture_registrar(self->engine),
reinterpret_cast<int64_t>(self->engine));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

According to the Google C++ Style Guide (referenced by the Repository Style Guide), when casting a pointer to an integer, you should only cast to/from intptr_t or uintptr_t. Direct casting to int64_t using reinterpret_cast can lead to compilation errors or warnings on 32-bit platforms where pointer sizes differ from 64-bit integers. Casting to intptr_t first is portable and safe, and it will be implicitly promoted to int64_t.

                                 reinterpret_cast<intptr_t>(self->engine));
References
  1. Google C++ Style Guide: When casting a pointer to an integer, use reinterpret_cast to intptr_t or uintptr_t. (link)

if (!registrar) {
return 0;
}
return reinterpret_cast<int64_t>(registrar->engine);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

According to the Google C++ Style Guide (referenced by the Repository Style Guide), when casting a pointer to an integer, you should only cast to/from intptr_t or uintptr_t. Direct casting to int64_t using reinterpret_cast can lead to compilation errors or warnings on 32-bit platforms where pointer sizes differ from 64-bit integers. Casting to intptr_t first is portable and safe, and it will be implicitly promoted to int64_t.

  return reinterpret_cast<intptr_t>(registrar->engine);
References
  1. Google C++ Style Guide: When casting a pointer to an integer, use reinterpret_cast to intptr_t or uintptr_t. (link)

if (!registrar) {
return 0;
}
return reinterpret_cast<intptr_t>(registrar->engine);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we centralize the casting logic to ensure it doesn't drift? Currently both FlutterDesktopPluginRegistrarGetEngineId and FlutterWindowsEngine have logic to convert a FlutterWindowsEngine* into an ID. I'd consider:

  1. Adding a int64_t FlutterWindowsEngine::id()
  2. Updating this to call registrar->engine->id()
  3. Updating this line to call id():
    args.engine_id = reinterpret_cast<int64_t>(this);

//
// This corresponds to PlatformDispatcher.instance.engineId in Dart.
FLUTTER_EXPORT int64_t FlutterDesktopPluginRegistrarGetEngineId(
FlutterDesktopPluginRegistrarRef registrar);

@loic-sharma loic-sharma Nov 6, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: could you introduce a FlutterDesktopEngineId typedef, similar to the existing FlutterDesktopViewId above:

https://github.com/tarrinneal/flutter/blob/c19d3980351ceb6e2a22f76cbfea5efca97eb2bf/engine/src/flutter/shell/platform/windows/public/flutter_windows.h#L35-L36

You'll get some type safety benefits if we ever add an API that accepts an engine ID.

return fl_plugin_registrar_new(nullptr, self->binary_messenger,
self->texture_registrar);
self->texture_registrar,
reinterpret_cast<intptr_t>(self));

@loic-sharma loic-sharma Nov 6, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd consider adding a private int64_t fl_engine_get_id(FlEngine*) helper function so that we can keep this logic unified. This would be a good spot for it:

https://github.com/tarrinneal/flutter/blob/76395508545ff366c171bf5ab39fc893a9ca3e71/engine/src/flutter/shell/platform/linux/fl_engine_private.h#L656-L668


// Returns the unique identifier for the engine associated with this registrar.
//
// This corresponds to PlatformDispatcher.instance.engineId in Dart.

@loic-sharma loic-sharma Nov 6, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's call out thread-safety here since this can be used from any thread:

Suggested change
// This corresponds to PlatformDispatcher.instance.engineId in Dart.
// This corresponds to PlatformDispatcher.instance.engineId in Dart.
// This can be called on any thread.

@mattkae mattkae left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One nit on Linux, and I +1 Loic's Windows review


FlPluginRegistrarInterface* iface = FL_PLUGIN_REGISTRAR_GET_IFACE(self);
if (iface->get_engine_id == nullptr) {
return 0;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a constant that we can pin this too somewhere, e.g. kDefaultEngineId if that exists in the repo?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

a: desktop Running on desktop CICD Run CI/CD engine flutter/engine related. See also e: labels. platform-linux Building on or for Linux specifically platform-windows Building on or for Windows specifically team-linux Owned by the Linux platform team team-windows Owned by the Windows platform team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Expose engineId on native plugin bindings/registrars (FlutterPluginBinding, FlutterPluginRegistrar) for FFI/JNI plugins

3 participants