DartMetal

DartMetal — Touch the Metal from Dart.

DartMetal is a low-level system programming library for Dart. It provides manual memory management, raw syscalls, and direct CPU introspection via FFI — essentially bringing Dart into the world of systems programming.

⚠️ Warning: This library is unsafe by design. You can crash the Dart VM, corrupt memory, or perform invalid syscalls. Use at your own risk.


✨ Features

  • 🧠 UnsafePointer<T> — C-style typed pointers with read/write and arithmetic.
  • 💾 Manual memory control — malloc, free, memcpy, memset.
  • ⚙️ Native syscalls — cross-platform process and I/O access.
  • 🎩 RAII - safely allocate and free native memory buffers
  • 🧩 Raw FFI bridge to C for native execution.
  • 🧬 CPU feature detection (SSE, AVX, AES-NI, etc.) using real CPUID.
  • 🔧 Cross-platform builds (Windows, Linux, macOS).

📦 Installation

Add to your pubspec.yaml:

dependencies:
  dartmetal: ^0.1.0

Then build the native library for your platform:

cd lib
cd native
dart run build.dart

This will produce:

Platform Output file
Windows dartmetal.dll
Linux libdartmetal.so
macOS libdartmetal.dylib

Ensure it resides in lib/native/.


🧩 Basic Usage

Memory Allocation

import 'package:dartmetal/dartmetal.dart';

void main() {
  final ptr = UnsafePointer<Uint32>.allocate(4);
  ptr.write(0, 0xDEADBEEF);
  print('Memory first 4 bytes: 0x${ptr.read<int>(0).toRadixString(16)}');
  ptr.free();
}

Pointer Arithmetic

final ptr = UnsafePointer<Uint32>.allocate(2);
ptr.write(0, 0xCAFEBABE);
ptr.write(1, 0xFEEDFACE);

final second = ptr.offset(1);
print('Second value: 0x${second.read<int>(0).toRadixString(16)}');

ptr.free();

⚙️ Syscalls

// test/syscall_test.dart
import 'dart:ffi';
import 'dart:io';
import 'package:ffi/ffi.dart';
import 'package:dartmetal/dartmetal.dart';

void main() {
  print('===== DartMetal Syscall Test =====\n');

  // ---------- PID ----------
  final pid = MetalSyscall.getpid();
  print('Current PID: $pid\n');

  // ---------- Write to stdout ----------
  print('Writing to stdout using DartMetal:');
  MetalSyscall.writeStdout('Hello from DartMetal!\n');
  MetalSyscall.writeBytes([72, 105, 32, 102, 114, 111, 109, 32, 98, 121, 116, 101, 115, 10]);
  print(''); // newline

  // ---------- Sleep ----------
  print('Sleeping for 1 second...');
  MetalSyscall.sleepMs(1000);
  print('Awake!\n');

  // ---------- Current Working Directory ----------
  final cwd = MetalSyscall.getCwd();
  print('Current working directory: $cwd');

  // ---------- Change Directory ----------
  final parentDir = Directory.current.parent.path;
  final changeResult = MetalSyscall.chdir(parentDir);
  print('Changed to parent directory: ${changeResult == 0 ? "Success" : "Fail"}');
  print('New cwd: ${MetalSyscall.getCwd()}\n');

  // ---------- Environment Variables ----------
  const envKey = 'DARTMETAL_TEST';
  MetalSyscall.setenv(envKey, 'foobar');
  final envValue = MetalSyscall.getenv(envKey);
  print('Environment variable $envKey = $envValue\n');

  // ---------- Unlink / File Deletion ----------
  final testFile = File('dartmetal_temp.txt');
  testFile.writeAsStringSync('test');
  print('Created temporary file: ${testFile.path}');
  final unlinkResult = MetalSyscall.unlink(testFile.path);
  print('Deleted temporary file: ${unlinkResult == 0 ? "Success" : "Fail"}');
}

🧬 CPU Feature Detection

You can inspect real CPU capabilities directly from Dart, through FFI bindings to native CPUID.

Example

// test/cpu_test.dart
import 'package:dartmetal/dartmetal.dart';

void main() {
  print('===== DartMetal CPU Test =====\n');

  // Show general CPU info
  CPU.info();

  print('\n--- Individual Properties ---');
  print('Architecture: ${CPU.architecture}');
  print('Cores       : ${CPU.coreCount}');
  print('Endianness  : ${CPU.endianness}');
  print('Vendor      : ${CPU.vendor}');

  // Check some key features
  final features = CPU.featureFlags;
  print('\n--- Selected Feature Checks ---');
  print('SSE:   ${features['SSE'] ?? false}');
  print('SSE2:  ${features['SSE2'] ?? false}');
  print('SSE3:  ${features['SSE3'] ?? false}');
  print('SSE4_1:${features['SSE4_1'] ?? false}');
  print('SSE4_2:${features['SSE4_2'] ?? false}');
  print('AVX:   ${features['AVX'] ?? false}');
  print('AES-NI:${features['AES'] ?? false}');
  print('MMX:   ${features['MMX'] ?? false}');

  print('\n✅ CPU test completed successfully!');
}

Example Output

===== DartMetal CPU Test =====

CPU Info
├─ Architecture : x86_64
├─ Cores        : 4
├─ Endianness   : LittleEndian
✅ Loaded native library: C:\Users\Eudald\Desktop\Projectes\Dart\dartmetal\lib\native\dartmetal.dll
└─ Vendor       : GenuineIntel
Features:
  └─ FPU
  └─ VME
  └─ PSE
  └─ TSC
  └─ MSR
  └─ PAE
  └─ MCE
  └─ APIC
  └─ SEP
  └─ MTRR
  └─ CMOV
  └─ PAT
  └─ CLFSH
  └─ MMX
  └─ FXSR
  └─ SSE
  └─ SSE2
  └─ HTT
  └─ SSE3
  └─ PCLMULQDQ
  └─ SSSE3
  └─ SSE4_1
  └─ SSE4_2
  └─ AES
  └─ AVX
  └─ FMA
  └─ MOVBE
  └─ POPCNT

--- Individual Properties ---
Architecture: x86_64
Cores       : 4
Endianness  : LittleEndian
Vendor      : GenuineIntel

--- Selected Feature Checks ---
SSE:   true
SSE2:  true
SSE3:  true
SSE4_1:true
SSE4_2:true
AVX:   true
AES-NI:true
MMX:   true

✅ CPU test completed successfully!

🧪 Running Tests

Run the included test suite:

dart run test/cpu_test.dart

or for memory/syscall tests:

dart run test/dartmetal_test.dart

Example of a memory test:

import 'package:dartmetal/dartmetal.dart';

void main() {
  // Allocate zeroed memory
  final mem = MetalMemory.calloc(8, 4);
  mem.writeUint32(0, 1234);
  mem.writeUint32(4, 5678);
  print(mem.readUint32(0)); // -> 1234
  print(mem.readUint32(4)); // -> 5678

  // Compute checksum
  print('Checksum: ${mem.checksum32()}');

  // Reallocate (grow)
  final larger = mem.realloc(64);
  print('New size: ${larger.size}');

  // Clean up
  larger.zeroSecure();
  larger.free();
}

Example result:

✅ Loaded native library: dartmetal.dll
✅ CPU test completed successfully!
✅ All tests passed!

RAII Memory Management in DartMetal

DartMetal provides a RAII-style memory manager for safely allocating and freeing native memory buffers in Dart using FFI. RAII ensures that memory is automatically cleaned up, preventing leaks and making buffer management safer and easier.

Features

  • Allocate memory of any size.
  • Typed allocations for SizedNativeType (e.g., Uint8, Uint16, Uint32, Float, Double).
  • Clone buffers (deep copy).
  • Move ownership of buffers.
  • Scoped allocations automatically freed after use.

Basic Usage

import 'package:dartmetal/src/raii.dart';
import 'dart:ffi';

void main() {
  // Allocate 16 bytes of raw memory
  final raii = RAII.allocate(16);
  final ptr = raii.ptr.cast<Uint32>();

  ptr[0] = 123;
  ptr[1] = 456;
  print('Memory contents: [${ptr[0]}, ${ptr[1]}]');

  // Free manually (optional if using finalizers)
  raii.free();
}

Use RAIITyped for type-safe allocations:

import 'package:dartmetal/src/raii.dart';
import 'dart:ffi';

void main() {
  // Allocate 4 Uint32 elements (16 bytes)
  final raii32 = RAIITyped.allocateTyped<Uint32>(4);
  final ptr32 = raii32.typedPtr;

  ptr32[0] = 123;
  ptr32[1] = 456;
  print('Typed memory contents: [${ptr32[0]}, ${ptr32[1]}]');

  // Clone the buffer (deep copy)
  final clone = raii32.clone();
  clone.typedPtr[0] = 999;
  print('Original: ${ptr32[0]}, Clone: ${clone.typedPtr[0]}');

  // Move ownership
  final moved = raii32.move();
  print('Moved buffer size: ${moved.size} bytes');

  // Clean up
  clone.free();
  moved.free();
}

Scoped Typed Allocations

Automatically free memory after a block:

RAIITyped.withScopedTyped<Uint16>(2, (ptr16) {
  ptr16[0] = 0xABCD;
  ptr16[1] = 0x1234;
  print('Inside scoped block: [${ptr16[0].toRadixString(16)}, ${ptr16[1].toRadixString(16)}]');
});
// Memory is freed automatically here

Notes

  • RAIITyped.allocateTyped<T>() only works for SizedNativeType (Uint8, Uint16, Uint32, Int32, Float, Double, etc.).
  • RAII automatically attaches a finalizer, so memory is freed when the object is garbage collected.
  • Manual free() is optional but can be used for immediate cleanup.
  • Use typedPtr for safe pointer access, avoiding manual casts.

🤝 Contributing

DartMetal is experimental and evolving. Contributions are welcome, especially for:

  • New syscalls and platform bindings
  • Advanced CPU topology parsing
  • Threading & atomic ops
  • macOS and Linux testing

⚖️ License

MIT License © 2025 MuerteSeguraZ