proj4rb provides Ruby bindings for the Proj coordinate transformation library using FFI. It supports Proj versions 4 through 9.x.
- FFI-based: Uses the
ffigem to bind to the nativelibprojshared library. No C extensions. - Dynamic loading: Code is loaded dynamically based on the installed Proj version (see
lib/api/). - Class hierarchy mirrors the Proj/OGC model:
PjObjectis the base classCrs,Conversion,Transformation,Datum,Ellipsoid,PrimeMeridian,CoordinateSystem, etc. are subclassesCoordinateOperationMixinis shared byConversionandTransformation
lib/proj.rb/lib/proj4.rb— Entry points (require 'proj'orrequire 'proj4')lib/api/— FFI bindings to native Proj C functions, organized by versionlib/proj/— Ruby wrapper classes (Crs, Transformation, Context, Coordinate, etc.)test/— Minitest test suite (test/*_test.rb)
gem install bundler
bundle install
bundle exec rake test
Tests use Minitest. Test files follow the pattern test/*_test.rb and inherit from AbstractTest in test/abstract_test.rb.
rake package
rake yard
PROJ_LIB_PATH— Override the path to thelibprojshared libraryPROJ_DATA— Path to the folder containingproj.db(Proj 6+). Must be set before Ruby launches.
When a new PROJ version is released, update ffi-bindings.yaml to include any new API functions. Here's the process:
Compare proj.h between the last supported version and the new release on GitHub:
https://raw.githubusercontent.com/OSGeo/PROJ/<VERSION>/src/proj.h
Extract all proj_* function declarations from each version and diff them. New functions are those present in the new version but absent in the previous one. Only minor releases (e.g., 9.5.0, 9.6.0) typically add new API functions — patch releases (e.g., 9.5.1) generally do not.
Check whether PROJ_SOVERSION changed in CMakeLists.txt:
https://raw.githubusercontent.com/OSGeo/PROJ/<VERSION>/CMakeLists.txt
If it changed, add the new SO version string to the library_versions list in ffi-bindings.yaml.
Add a new section under symbols.versions in ffi-bindings.yaml using the PROJ version number macro format (major * 10000 + minor * 100 + patch):
# 9.8.0
90800:
- proj_new_function_nameRun ruby-bindgen to regenerate the FFI bindings:
bundle exec ruby-bindgen ffi-bindings.yaml
Version guards in the generated bindings call proj_version, a method defined in lib/api/proj_version.rb. This file is user-maintained (not overwritten by ruby-bindgen) and reads the runtime library version via proj_info. No manual fixes are needed after regeneration.
PROJ version numbers are computed as major * 10000 + minor * 100 + patch. Examples:
- 5.0.0 → 50000 (baseline, no version guard)
- 6.0.0 → 60000
- 9.4.0 → 90400
- 9.7.0 → 90700
ghis available and authenticated with READ-ONLY access- DO NOT use
ghto create, update, or modify anything (no PRs, issues, comments, releases, etc.) - Use
ghonly to read information: view CI runs, check PR status, read issues, etc.
- Namespace:
Proj::(e.g.,Proj::Crs,Proj::Transformation,Proj::Coordinate) - Legacy namespace
Proj4::is supported viarequire 'proj4' - License: MIT
- Ruby version: >= 2.7
- Commits must not include a co-author or author line (no
Co-Authored-By) - Tests must not use mocks or stubs. Always call the real PROJ C API.
- Never manually edit auto-generated files (
lib/api/proj.rb,lib/api/proj_experimental.rb). Fix issues inffi-bindings.yamland regenerate instead.