C/C++ to C# β from UI to the bare metal, get it done.
Ferrum is a reusable native-compute framework for .NET MAUI. It provides the scaffolding that lets any MAUI app call into a C/C++ static library with:
- Zero-copy buffers β
NativeBuffer<T>pins aSpan<T>/Memory<T>region so you can pass a pointer directly to native code without copying. - NativeAOT-compatible P/Invoke β every binding uses
[LibraryImport](source-generated), not[DllImport]. iOS NativeAOT is a first-class target. - Code-generation tool β
ferrum-codegenparses a C header and emits ready-to-use[LibraryImport]bindings. It fails loudly (never silently) on constructs it cannot safely bind. - Cross-platform CMake templates β build an XCFramework for iOS or
.soper ABI for Android from any C/C++17 source tree.
Ferrum is domain-agnostic β it does not know or care what your native core does. Audio, ML inference, signal processing, computer vision β all equally welcome.
/native/ CMake project: iOS/Android toolchain files, test fixtures
/tools/codegen/ ferrum-codegen β header-to-[LibraryImport] generator
/src/Framework/ Ferrum.Framework C# library (NativeBuffer<T>, etc.)
/src/Framework.Tests/ xUnit tests for the framework and codegen
/samples/MinimalDemo/ End-to-end MAUI sample calling native test functions
/templates/maui-ferrum/ dotnet new template for scaffolding new Ferrum apps
/docs/ Architecture notes, getting-started guide, open questions
.github/workflows/ CI: native build (iOS/Android), codegen tests, MAUI build
Create a new Ferrum-enabled MAUI app in seconds:
# Install the template (from local repo)
dotnet new install templates/maui-ferrum
# Create a new project
dotnet new maui-ferrum -n MyApp
cd MyApp
# See README.md in the generated project for next stepsThe template creates a complete MAUI project with Ferrum.Framework already configured and example NativeBuffer<T> usage.
Clone this repository and run the MinimalDemo sample:
git clone https://github.com/ayersdecker/ferrum.git
cd ferrum
# Build native test fixtures for your target platform
# iOS (requires macOS + Xcode):
./native/scripts/build_ios.sh
# Android (requires NDK β set ANDROID_NDK_HOME):
export ANDROID_NDK_HOME=/path/to/ndk
./native/scripts/build_android.sh
# Open and run the sample
cd samples/MinimalDemo
dotnet build -f net9.0-android # or net9.0-iosSee samples/MinimalDemo/README.md for details.
dotnet add package Ferrum.Framework
dotnet tool install --global Ferrum.CodegenCreate your C/C++ library with a plain-C API header:
// mylib/include/mylib.h
#ifdef __cplusplus
extern "C" {
#endif
void process_samples(float* data, int count);
#ifdef __cplusplus
}
#endifBuild for iOS and Android using the provided CMake scripts (see docs/getting-started.md).
ferrum-codegen \
--input mylib/include/mylib.h \
--output Interop/MylibBindings.cs \
--ns MyApp.Interop \
--lib __Internalusing Ferrum.Framework.Buffers;
using MyApp.Interop;
using var buffer = new NativeBuffer<float>(1024);
for (int i = 0; i < buffer.Length; i++)
buffer.Span[i] = (float)i * 0.5f;
unsafe
{
MylibBindings.process_samples(buffer.TypedPointer, buffer.Length);
}
// Read results back from buffer.Spanπ Full Guide: docs/getting-started.md
ποΈ Architecture: docs/architecture.md
| Constraint | Detail |
|---|---|
| No domain logic | This repo is framework-only. Application-specific code is scope creep. |
| NativeAOT on iOS | No runtime codegen, no reflection-based marshalling. |
| Loud failures | The codegen tool exits non-zero rather than emitting an incorrect binding. |
| Blittable only | Only types with a 1:1 memory layout between C and C# are supported. |
Problem: The app crashes with DllNotFoundException when calling native code on iOS.
Solution: Ensure your native library is built as an XCFramework and properly referenced:
./native/scripts/build_ios.shThen add to your .csproj:
<ItemGroup Condition="$([MSBuild]::GetTargetFrameworkIdentifier('$(TargetFramework)')) == 'iOS'">
<NativeReference Include="path/to/libmylib.xcframework">
<Kind>Framework</Kind>
<SmartLink>true</SmartLink>
</NativeReference>
</ItemGroup>Use --lib __Internal in ferrum-codegen for iOS.
Problem: DllNotFoundException: libmylib on Android.
Solution: Build for all required ABIs and include them in your project:
export ANDROID_NDK_HOME=/path/to/ndk
./native/scripts/build_android.shAdd to .csproj:
<ItemGroup Condition="$([MSBuild]::GetTargetFrameworkIdentifier('$(TargetFramework)')) == 'Android'">
<AndroidNativeLibrary Include="artifacts/android/jniLibs/arm64-v8a/libmylib.so" />
<AndroidNativeLibrary Include="artifacts/android/jniLibs/armeabi-v7a/libmylib.so" />
<AndroidNativeLibrary Include="artifacts/android/jniLibs/x86_64/libmylib.so" />
</ItemGroup>Use --lib libmylib (without .so) in ferrum-codegen for Android.
Problem: ferrum-codegen exits with an error about unsupported types.
Solution: Check that your header only uses blittable types:
- β
int32_t,int64_t,float,double, pointers to structs - β
char*,long, function pointers, unions
Problem: Crash when accessing NativeBuffer.Span after disposal.
Solution: Keep the NativeBuffer alive while native code is using it:
using var buffer = new NativeBuffer<float>(1024);
unsafe { MyFunc(buffer.TypedPointer, buffer.Length); }
// Native call completes before 'using' disposes bufferFor more issues, see GitHub Issues or docs/getting-started.md.
We welcome contributions! See CONTRIBUTING.md for:
- How to build and test the framework
- Code style guidelines
- PR submission process
- NuGet package publication (
Ferrum.FrameworkandFerrum.Codegendotnet tool) -
dotnet newproject template for quick scaffolding (maui-ferrum) - Codegen parser decision (tokenizer-based, fails loudly on unsupported constructs)
- Windows and macOS desktop MAUI support
- Community samples (audio processing, ML inference, computer vision)
See docs/open-questions.md for detailed discussion on pending decisions.
MIT Β© 2026 Decker Ayers