android - Rust instead of c++
Rust instead of c++
I made a simple example to use a Rust DLL from Flutter instead of C++.
It reads the mouse position on Windows.
Create a Rust project
Create a library project.
cargo new mousepos --lib // --bin (cargo run)
cd mousepos
// cargo build --release
Build the mouse position code.
Cargo.toml
[package]
name = "mousepos"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["cdylib"]
[dependencies]
windows = { version = "0.62.2", features = ["Win32_UI_WindowsAndMessaging"] }
lib.rs
use windows::Win32::Foundation::POINT;
use windows::Win32::UI::WindowsAndMessaging::GetCursorPos;
#[repr(C)]
pub struct Point {
pub x: i32,
pub y: i32,
}
#[no_mangle]
pub extern "C" fn get_cursor_pos(out: *mut Point) -> u8 {
if out.is_null() {
return 0;
}
unsafe {
let mut p = POINT { x: 0, y: 0 };
// windows 0.5x: GetCursorPos -> Result<(), Error>
if GetCursorPos(&mut p as *mut POINT).is_ok() {
(*out).x = p.x;
(*out).y = p.y;
1
} else {
0
}
}
}
Build the DLL and copy the file somewhere safe.
Flutter setup
Load the DLL.
mousepos_ffi.dart
import 'dart:ffi';
import 'package:ffi/ffi.dart' as ffi;
base class Point extends Struct {
@Int32()
external int x;
@Int32()
external int y;
}
typedef _GetCursorPosNative = Uint8 Function(Pointer<Point>);
typedef _GetCursorPosDart = int Function(Pointer<Point>);
class MousePos {
final DynamicLibrary _lib;
late final _GetCursorPosDart _getCursorPos;
MousePos._(this._lib) {
_getCursorPos = _lib
.lookupFunction<_GetCursorPosNative, _GetCursorPosDart>('get_cursor_pos');
}
static MousePos load({String? path}) {
final lib = DynamicLibrary.open(path ?? 'mousepos.dll');
return MousePos._(lib);
}
({int x, int y})? getCursorPos() {
final out = ffi.calloc<Point>();
try {
final ok = _getCursorPos(out);
if (ok == 1) {
return (x: out.ref.x, y: out.ref.y);
}
return null;
} finally {
ffi.calloc.free(out);
}
}
}
Build the UI.
main.dart
import 'dart:async';
import 'package:flutter/material.dart';
import 'mousepos_ffi.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
debugShowCheckedModeBanner: false,
home: MousePosPage(),
);
}
}
class MousePosPage extends StatefulWidget {
const MousePosPage({super.key});
@override
State<MousePosPage> createState() => _MousePosPageState();
}
class _MousePosPageState extends State<MousePosPage> {
late final MousePos _mousePos;
Timer? _timer;
String _text = 'reading position...';
@override
void initState() {
super.initState();
_mousePos = MousePos.load(); // mousepos.dll
_timer = Timer.periodic(const Duration(milliseconds: 33), (_) {
final p = _mousePos.getCursorPos();
if (!mounted) return;
setState(() {
_text = p == null ? 'fail to read' : 'X: ${p.x} , Y: ${p.y}';
});
});
}
@override
void dispose() {
_timer?.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Position (Rust + Flutter)'),
backgroundColor: Colors.grey,
),
body: Center(child: Text(_text, style: const TextStyle(fontSize: 28))),
);
}
}
DLL location
build/windows/x64/runner/Debug
build/windows/x64/runner/Release
Copy mousepos.dll into the folder next to the exe.
If the DLL is missing, the exe fails to load.
Result
Compared to writing a C++ DLL, Rust felt less dependent on Visual Studio settings, and the code was much simpler.
Not sure how far I’ll push it, though. (Rust and C++ are both hard.)

end.