The general approach for NImpeller is to treat impeller.h as the only source of truth and manually write only some convenience code or code dealing with native->managed callbacks (there is only a few of those). The generator is supposed to generate the entire P/Invoke layer and at least 90% of .NET classes exposed as the public API.
Generated bindings file is NOT checked out into the repo, because right now the bindings considered to be versionless, i. e. being compatible with any version of impeller.h. You can find an example of generated code here if you don't want to clone/build the repo and want a sneak peek.
- Run InteropGen with /path/to/impeller.h as an argument and pray that ClangSharp is not completely broken for you
- Run Sandbox with /path/to/impeller.so (or dll/dylib) as an argument. It will only work for platforms where SDL2 can create a GLES context. I've only tested it with Linux with an Intel iGPU, so good luck.
Flutter builds toolkit binaries on a nightly feed, that you can download from.
Typical link is https://storage.googleapis.com/flutter_infra_release/flutter/$FLUTTER_SHA/$PLATFORM_ARCH/impeller_sdk.zip
Where:
$FLUTTER_SHAis a commit hash$PLATFORM_ARCHis one oflinux-arm64,linux-x64,windows-arm64,windows-x64,darwin-arm64,darwin-x64orandroid-arm64
From this zip you will need include/impeller.h and lib/impeller.so (or impeller.dll/impeller.dylib).
See Impeller Toolkit: Prebuilt Artifacts
Native impeller handles are represented by two separate types:
- FooHandle - a SafeHandle passed to P/Invoke layer
- Foo - a managed wrapper around FooHandle that exposes actual methods and factories in idiomatic .NET style
There is no object tracking, for each call to a native function that returns you an existing Foo instance you will get a new Foo object with reference counter of the native one being increased by one.
The bindings are generated by InteropGen, a simple C# console app that uses CppAst library to parse impeller.h and conver it into NativeModel that has some .NET-specific stuff already mapped.
The model is then used to generate the bindings code. Generator is aware of impeller.h naming conventions, so it will place functions to appropriate classes, properly wrap factories for New-suffixed methods, call *Retain function when obtaining and existing object counter, etc.
# Update ninja files without attempting to rebuild THE ENTIRE FLUTTER
./engine/src/flutter/tools/gn --runtime-mode debug --no-stripped --no-lto --no-rbe --no-goma
# Compile just interop library and not THE ENTIRE FLUTTER
ninja -C engine/src/out/host_debug library
# Generate compile_commands.json for IDE integration for just the interop library and deps and not THE ENTIRE FLUTTER
mkdir -p ide
/path/to/1.13.1/ninja -C engine/src/out/host_debug -t compdb-targets library > ide/compile_commands.json
#jq 'map(select(.command | startswith("vpython") or startswith("rm") or startswith("ln") | not))'