dart_bclibc
Dart FFI bindings for the bclibc ballistics engine.
A thin, zero-copy Dart wrapper around libbclibc_ffi — a high-performance 3-DOF + spin drift ballistic solver engine with RK4/Euler integration. Ships with the bclibc C++ source as a git submodule; no pre-built binaries required.
Pure Dart — no Flutter dependency. For Flutter apps (Android/iOS/Linux/macOS/Windows native bundling, plus Web/WebAssembly support), depend on dart_bclibc_flutter instead, which re-exports everything here.
Table of Contents
Quick start
import 'package:dart_bclibc/bclibc.dart';
final bc = BcLibC.open(); // loads the native library once
final shot = BcShot(
bc: 0.295,
weightGrain: 168.0,
diameterInch: 0.308,
lengthInch: 1.22,
muzzleVelocityFps: 2750.0,
sightHeightFt: 0.1148,
twistInch: 10.0,
tempC: 15.0,
pressureHpa: 1013.25,
altitudeFt: 0.0,
dragTable: [BcDragPoint(0.0, 0.0), /* … Mach / CD pairs … */],
lookAngleRad: 0.0,
barrelElevationRad: 0.0,
);
final hit = bc.integrateShot(
shot,
BcTrajectoryRequest(rangeLimitFt: 3000.0, rangeStepFt: 100.0),
);
for (final pt in hit.trajectory) {
print('${pt.distanceFt} ft ${pt.velocityFps} fps ${pt.heightFt} ft');
}
API
Input types
| Dart type | Description |
|---|---|
BcShot |
Preferred shot input (natural units). All physics conversion — atmosphere density, Coriolis trig, PCHIP drag curve, cant — is performed inside C++ via BCLIBCFFI_Shot::to_shot_props(). |
BcShotProps |
Legacy shot input (pre-computed BcAtmosphere/BcCoriolis structs). |
BcTrajectoryRequest |
Step size, range limit, and BCLIBCFFI_TrajFlag filter bitmask. |
BcConfig |
Solver knobs (step multiplier, accuracy, gravity constant, etc.). |
BcDragPoint |
One Mach / CD entry for the drag table. |
BcWind |
One wind segment (velocity, direction, distance bounds). |
Result types
| Dart type | Description |
|---|---|
BcTrajectoryData |
One filtered trajectory record. |
BcHitResult |
Full trajectory list + BCLIBCFFI_TerminationReason. |
BcInterception |
Single interpolated point from integrateAtShot. |
BcMaxRangeResult |
Max range (ft) + angle (rad) from findMaxRangeShot. |
BcLibC methods
| Method | Description |
|---|---|
BcLibC.open() |
Load the native library (call once at startup). |
integrateShot(BcShot, BcTrajectoryRequest) |
Full filtered trajectory. |
integrateAtShot(BcShot, key, value) |
Single interpolated point at a trajectory key. |
findZeroAngleShot(BcShot, distanceFt) |
Barrel elevation to zero at distance. |
findApexShot(BcShot) |
Highest point of the trajectory arc. |
findMaxRangeShot(BcShot) |
Maximum range and corresponding angle. |
getCorrection(distanceFt, offsetFt) |
Angular correction (rad) for a linear offset. |
calculateEnergy(grains, fps) |
Kinetic energy (ft-lb). |
calculateOgw(grains, fps) |
Optimal Game Weight. |
Legacy BcShotProps-based overloads (findApex, findMaxRange, etc.) are retained for backwards compatibility.
Enums
| Dart enum | Description |
|---|---|
BCLIBCFFI_TrajFlag |
Trajectory filter flags (BCLIBCFFI_TRAJ_FLAG_RANGE, BCLIBCFFI_TRAJ_FLAG_APEX, …) |
BcTerminationReason |
Why integration stopped (BcHitResult.reason). |
BcBaseTrajInterpKey |
Key field selector for integrateAtShot (.posX, .time, .mach, …). |
BcIntegrationMethod |
BcIntegrationMethod.rk4 (default) or .euler (BcShot.method). |
BcTerminationReason, BcBaseTrajInterpKey, and BcIntegrationMethod (from
lib/ffi/bclibc_types.dart) are platform-agnostic — the same types work with
both BcLibC (native) and BcLibCWeb (web). They replace the raw
ffigen-generated BCLIBCFFI_* enum classes in the public API; those still
exist in bclibc_bindings.g.dart but are native-internal implementation
detail now.
Async API
AsyncCalculator — the Future-returning counterpart to Calculator that
also works on Flutter Web (wasm-backed) — lives in
dart_bclibc_flutter instead of this package, since a real web
implementation only makes sense inside a Flutter Web app (see that package's
README for Web / WebAssembly). This package (dart_bclibc) exposes the
synchronous Calculator only; wrap it in your own Isolate.run if you want
off-isolate execution in a plain Dart project:
import 'dart:isolate';
import 'package:dart_bclibc/bclibc.dart';
final result = await Isolate.run(
() => Calculator().fire(shot: shot, trajectoryRange: Distance.meter(1000)),
);
Atmosphere and Coriolis
When using BcShot:
- Pass
pressureHpa: 0for vacuum (zero drag). - Pass
latitudeDeg: double.nanto disable Coriolis (defaultBcShotvalue). - Pass
azimuthDeg: double.nanfor flat-fire drift only.
Unit system
lib/unit.dart provides typed unit wrappers with an in_() / toDouble() API:
import 'package:dart_bclibc/unit.dart';
final t = Temperature.celsius(15.0);
print(t.in_(TemperatureUnit.fahrenheit)); // 59.0
final d = Distance.meters(100.0);
print(d.in_(DistanceUnit.feet)); // 328.084...
Available types: Distance, Velocity, Temperature, Pressure, Angular, Weight, Energy.
Building
Prerequisites
- Dart SDK ≥ 3.11.4
- CMake ≥ 3.13
- C++17 compiler (GCC / Clang on Linux/macOS, MSVC 2022 on Windows)
- LLVM/Clang dev headers (only for regenerating FFI bindings)
Clone
git clone --recurse-submodules https://github.com/ballistics-lab/dart-bclibc.git
cd dart-bclibc/dart
If you cloned without --recurse-submodules:
git submodule update --init
Build native library
From the repo root:
make build
Or directly, from dart/:
dart run bin/build_native.dart
Both build libbclibc_ffi via CMake and copy it into dart/lib/native/<platform>/
— resolved automatically at runtime via a package: URI, independent of the
caller's working directory. BcLibC.open() also checks the BCLIBC_FFI_PATH
environment variable first, if set.
For Flutter apps the native library is instead built and bundled automatically by
flutter build, viadart_bclibc_flutter's platformCMakeLists.txt/Gradle/podspec integration — no changes to the app's own platform config are required. Seedart_bclibc_flutter's README for details.
Consuming apps: dart test
Apps that depend on dart_bclibc (not dart_bclibc_flutter) need to build the
native library explicitly before testing/running, since plain dart test/dart run
never run a platform build:
dart run dart_bclibc:build_native
Wire it into your own test target, e.g. in a Makefile:
test: build-bclibc
dart test
build-bclibc:
dart run dart_bclibc:build_native
Regenerate FFI bindings
# Install LLVM first:
# Linux: sudo apt install libclang-dev clang
# macOS: brew install llvm
# Windows: winget install LLVM
make ffigen
The generated file is lib/ffi/bclibc_bindings.g.dart.
Run tests
make test
Native library
| Platform | Library name |
|---|---|
| Linux | libbclibc_ffi.so |
| macOS | libbclibc_ffi.dylib |
| Windows | bclibc_ffi.dll |
Android, iOS, and WebAssembly are covered by
dart_bclibc_flutter instead, since they only ever run inside
a Flutter app. During development the path can be overridden via the
BCLIBC_FFI_PATH environment variable.
Dependencies
| Dependency | Role |
|---|---|
| bclibc | C++ ballistic solver engine (3-DOF + spin drift, RK4) — LGPL-3.0, bundled as a git submodule |
| ffi | Dart ↔ C FFI bindings |
| path | Cross-platform path joining, used by the native build/load helpers |
License
Copyright (C) 2026 Yaroshenko Dmytro (o-murphy)
This library is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License v3.0 as published by the Free Software Foundation.
See LICENSE for the full text. See CHANGELOG for release history.
Note
bclibc (the ballistic solver engine, located in bclibc/) is licensed separately under the GNU Lesser General Public License v3.0. See bclibc/LICENSE.
Warning
Risk notice. This package performs approximate simulations of complex physical processes. Calculation results must not be considered as completely or reliably reflecting actual projectile behaviour. Results may be used for educational purposes only and must not be relied upon in any context where an incorrect calculation could cause financial harm or put a human life at risk.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Libraries
- bclibc
- ffi/bclibc_bindings.g
- ffi/bclibc_bindings_stub_web
- ffi/bclibc_ffi
- Thin Dart wrapper over the bclibc C FFI layer.
- ffi/bclibc_ffi_stub_web
- ffi/bclibc_types
- unit