website icon indicating copy to clipboard operation
website copied to clipboard

Add more information about developing desktop plugins

Open GroovinChip opened this issue 2 years ago • 2 comments

What information is missing?

The Developing Packages & Plugins document should go into more detail about writing plugins for desktop platforms. As a desktop plugin author myself, I have struggled mightily with the nuances of writing a plugin in Swift for macOS, C/C++ for Windows, and C/C++ for Linux (which seems to be different than the C/C++ for Windows). Doing something as simple as reading PlatformChannel arguments required a frustrating level of researching. The API docs for the native Flutter platform code (things like FlutterResult, etc etc) are super hard to find and are also poorly documented. The only existing codelab for desktop provides zero explanation for the step that covers writing a plugin.

Basically, there is little to no documentation available on this subject as it relates to desktop. Given that all three desktop platforms are now officially stable, I believe it is past time for in-depth documentation to be provided by Flutter on writing desktop plugin.

A section of this document that might be good for (some, if not all of) these details is Step 2: Implement the package. Alternatively, it could be its own section, or even its own page.

Here are some of the topics I have struggled with in the past. All code snippets are from a real plugin I'm working on to generate thumbnails from videos:

  • How to properly read, store, and handle PlatformChannel arguments
    • Swift (macOS)
      • Reading Map arguments
        if let arguments = call.arguments as? Dictionary<String, Any>,
          let path = arguments["filePath"] as? String,
          let position = arguments["position"] as? Int64 {
            // do something
          }
        
      • Returning Map arguments back to Flutter
        let resultMap = ["data": base64String, "videoLength": durationTime] as [String : Any]
        result(resultMap)
        
    • C/C++ (Windows)
      • Reading Map arguments
        const auto* arguments = std::get_if<flutter::EncodableMap>(method_call.arguments());
        auto* path = std::get_if<std::string>(&(arguments->find(flutter::EncodableValue("filePath"))->second));
        auto* position = std::get_if<double>(&(arguments->find(flutter::EncodableValue("position"))->second));
        
      • Returning Map arguments back to Flutter
        result->Success(flutter::EncodableMap{
            { "width" , static_cast<int64_t>(width)  },
            { "height", static_cast<int64_t>(height) },
            { "depth" , static_cast<int64_t>(depth)  },
            { "videoDuration" , static_cast<double>(((double)duration) / 10000000.0 )  },
            { "data"  , pixels },
          });
        
    • C/C++ (Linux)
      • Reading Map arguments (real code sample):
        if (strcmp(method, "generateThumbnail") == 0) {
          FlValue *args = fl_method_call_get_args(method_call);
          FlValue *filePath = fl_value_lookup_string(args, "filePath");
          FlValue *position = fl_value_lookup_string(args, "position");
        }
        
  • Properly listening to EventChannels (not related to the thumbnail plugin)
    • Some third-party content can be found on this, but not for desktop specifically. There is open source code available to read and try to emulate, but it was still a difficult process and it would be nice if there were some official guides on this. I've also only done this for macOS so far, so I can't speak to the difficulty/nuance of doing it on Windows & Linux.
  • How to use external libraries
    • macOS
      • I haven't needed to do this yet so I'm unclear on what's required or how difficult it is
    • Windows
      • This plugin required use of the Microsoft MediaFoundation library. Linking that library to the windows runner was infuriatingly difficult, and it took several days, a lot of research, and help from several people to get this working. It required creating a dedicated cmake file to find the library and modifying CMakeLists.txt, and the nuances of both of those steps work were hard to figure out. Documentation from Flutter on this would have been quite helpful.
    • Linux
      • I have started on the Linux variant of the afore-mentioned plugin, which will require the ffmpeg library, but stopped because its such an enormous headache. Again, documentation on this would be super helpful.

I'm sure that there are many more nuances related to writing desktop plugins for Flutter that people struggle with.

How would you like us to fix this problem?

Please consider writing in-depth documentation on this subject. I'd be happy to collaborate on this, if desired.

GroovinChip avatar May 19 '22 15:05 GroovinChip

Yup, that's a good call-out. https://github.com/flutter/website/issues/7123 is related...

On the Windows side, https://pub.dev/packages/win32 gets us ever closer to supporting everything you might do with a plugin using just Dart code in a package. It provides solid wrappers for Win32 and COM, we're continuing to develop WinRT support.

timsneath avatar May 25 '22 02:05 timsneath

I support this so much. I've been struggling so hard. Heck that's how I ended up here lol. I've managed to figure the basic things out using the url_launcher and path_provider packages. Currently struggling with figuring out how, on the c++ side, do I access the data passed from the dart side.

Thanks for this basic guide. Helps me out a ton.

Chappie74 avatar Jun 22 '22 01:06 Chappie74