refactor(c/sedona-proj): replace C dynamic loading with pure Rust using libloading#672
Merged
Kontinuation merged 6 commits intoapache:mainfrom Mar 3, 2026
Merged
Conversation
… libloading
Replace the C-based dlopen/dlsym dynamic PROJ loading (proj_dyn.c/h) with
a pure Rust implementation using the libloading crate. This eliminates the
cc build dependency and ~250 lines of C code while maintaining the same
ProjApi struct-of-function-pointers architecture.
Changes:
- Add dyn_load.rs with load_fn! macro and load_proj_from_path()
- Remove build.rs, proj_dyn.c, proj_dyn.h
- Remove extern C { proj_dyn_api_init } from proj_dyn_bindgen.rs
- Update ProjApi to hold Option<Library> for shared library lifetime
- Replace C release callback in Drop with automatic Library drop
- Replace cc build-dependency with libloading in dependencies
This reverts commit 63259b6.
Contributor
There was a problem hiding this comment.
Pull request overview
This PR refactors sedona-proj’s dynamic PROJ loading by removing the C-based dlopen/dlsym shim and replacing it with a Rust-only loader built on libloading, while preserving the existing ProjApi function-pointer table consumed by the rest of the crate.
Changes:
- Removed the C dynamic loader (
proj_dyn.c/proj_dyn.h) and the Rust FFI entrypoint that initialized it. - Added a Rust
dyn_loadmodule that loads required PROJ symbols vialibloadingand returns(Library, ProjApi)to keep the library alive. - Updated crate/workspace dependencies: removed
ccbuild dependency and addedlibloading.
Reviewed changes
Copilot reviewed 9 out of 10 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
c/sedona-proj/src/proj_dyn_bindgen.rs |
Removes the FFI declaration for the old C initializer. |
c/sedona-proj/src/proj_dyn.h |
Deletes the C header for the old dynamic loader API. |
c/sedona-proj/src/proj_dyn.c |
Deletes the old C implementation of symbol loading and library lifetime management. |
c/sedona-proj/src/proj.rs |
Switches shared-library initialization to the new Rust loader and keeps the Library handle alive in ProjApi. |
c/sedona-proj/src/lib.rs |
Adds the new dyn_load module. |
c/sedona-proj/src/dyn_load.rs |
New Rust implementation of symbol loading using libloading. |
c/sedona-proj/build.rs |
Removes the build script that compiled the deleted C code. |
c/sedona-proj/Cargo.toml |
Drops cc build-dependency and adds libloading. |
Cargo.toml |
Adds libloading to workspace dependencies. |
Cargo.lock |
Locks libloading and updates sedona-proj dependency set accordingly. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
b8aeb74 to
3b05eac
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Replace the C-based
dlopen/dlsymdynamic PROJ loading (proj_dyn.c/proj_dyn.h) with a pure Rust implementation using thelibloadingcrate. This eliminates ~250 lines of C code while maintaining the sameProjApistruct-of-function-pointers architecture used by all existing call sites.Approach
The
libloadingcrate provides safe, cross-platform dynamic library loading (dlopen/LoadLibrary). Each PROJ symbol is loaded via aload_fn!macro that:*const ()pointerProjApi#[repr(C)]structThe
Libraryhandle is stored as_lib: Option<Library>in the RustProjApiwrapper —Somewhen loaded from a shared library,Nonewhen usingproj-sys. This ensures the library stays loaded for the lifetime of the function pointers.Tests
Temporarily enabled python-wheels test and passed on all major platforms: https://github.com/apache/sedona-db/actions/runs/22518558723
Upcoming Changes
We'll implement c/sedona-gdal using similar approach.