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.)

img



end.