This is an automated email from the ASF dual-hosted git repository.

kontinuation pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/sedona-db.git


The following commit(s) were added to refs/heads/main by this push:
     new a8750988 refactor(c/sedona-proj): replace C dynamic loading with pure 
Rust using libloading (#672)
a8750988 is described below

commit a8750988955f375304239adee580ff0af54abad8
Author: Kristin Cowalcijk <[email protected]>
AuthorDate: Tue Mar 3 18:46:03 2026 +0800

    refactor(c/sedona-proj): replace C dynamic loading with pure Rust using 
libloading (#672)
    
    ## Summary
    
    Replace the C-based `dlopen`/`dlsym` dynamic PROJ loading 
(`proj_dyn.c`/`proj_dyn.h`) with a pure Rust implementation using the 
`libloading` crate. This eliminates ~250 lines of C code while maintaining the 
same `ProjApi` struct-of-function-pointers architecture used by all existing 
call sites.
    
    ## Approach
    
    The `libloading` crate provides safe, cross-platform dynamic library 
loading (`dlopen`/`LoadLibrary`). Each PROJ symbol is loaded via a `load_fn!` 
macro that:
    1. Loads the symbol as a raw `*const ()` pointer
    2. Transmutes it to the expected function pointer type
    3. Stores it in the existing `ProjApi` `#[repr(C)]` struct
    
    The `Library` handle is stored as `_lib: Option<Library>` in the Rust 
`ProjApi` wrapper — `Some` when loaded from a shared library, `None` when using 
`proj-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.
    
    Co-authored-by: Copilot <[email protected]>
---
 Cargo.lock                            |  12 ++-
 Cargo.toml                            |   1 +
 c/sedona-proj/Cargo.toml              |   4 +-
 c/sedona-proj/build.rs                |  22 -----
 c/sedona-proj/src/dyn_load.rs         |  99 ++++++++++++++++++++++
 c/sedona-proj/src/lib.rs              |   1 +
 c/sedona-proj/src/proj.rs             |  50 +++---------
 c/sedona-proj/src/proj_dyn.c          | 150 ----------------------------------
 c/sedona-proj/src/proj_dyn.h          |  97 ----------------------
 c/sedona-proj/src/proj_dyn_bindgen.rs |  12 +--
 10 files changed, 127 insertions(+), 321 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 7292f3dc..ac91274b 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3700,6 +3700,16 @@ dependencies = [
  "windows-link",
 ]
 
+[[package]]
+name = "libloading"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "754ca22de805bb5744484a5b151a9e1a8e837d5dc232c2d7d8c2e3492edc8b60"
+dependencies = [
+ "cfg-if",
+ "windows-link",
+]
+
 [[package]]
 name = "libm"
 version = "0.2.15"
@@ -5466,12 +5476,12 @@ dependencies = [
  "approx",
  "arrow-array",
  "arrow-schema",
- "cc",
  "criterion",
  "datafusion-common",
  "datafusion-expr",
  "geo-traits",
  "geo-types",
+ "libloading 0.9.0",
  "proj-sys",
  "rstest",
  "sedona-common",
diff --git a/Cargo.toml b/Cargo.toml
index 9ba32574..abe66917 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -105,6 +105,7 @@ geos = { version = "11.0.1", features = ["geo", "v3_12_0"] }
 glam = "0.32.0"
 libmimalloc-sys = { version = "0.1", default-features = false }
 log = "^0.4"
+libloading = "0.9"
 lru = "0.16"
 mimalloc = { version = "0.1", default-features = false }
 num-traits = { version = "0.2", default-features = false, features = ["libm"] }
diff --git a/c/sedona-proj/Cargo.toml b/c/sedona-proj/Cargo.toml
index 0a145fd1..072f15bb 100644
--- a/c/sedona-proj/Cargo.toml
+++ b/c/sedona-proj/Cargo.toml
@@ -28,9 +28,6 @@ readme.workspace = true
 edition.workspace = true
 rust-version.workspace = true
 
-[build-dependencies]
-cc = { version = "1" }
-
 [dev-dependencies]
 approx = { workspace = true }
 geo-types = { workspace = true }
@@ -44,6 +41,7 @@ default = [ "proj-sys" ]
 proj-sys = [ "dep:proj-sys" ]
 
 [dependencies]
+libloading = { workspace = true }
 serde_json = { workspace = true }
 arrow-schema = { workspace = true }
 arrow-array = { workspace = true }
diff --git a/c/sedona-proj/build.rs b/c/sedona-proj/build.rs
deleted file mode 100644
index f62fd8a6..00000000
--- a/c/sedona-proj/build.rs
+++ /dev/null
@@ -1,22 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-
-fn main() {
-    println!("cargo:rerun-if-changed=src/proj_dyn.c");
-
-    cc::Build::new().file("src/proj_dyn.c").compile("proj_dyn");
-}
diff --git a/c/sedona-proj/src/dyn_load.rs b/c/sedona-proj/src/dyn_load.rs
new file mode 100644
index 00000000..ee7f6495
--- /dev/null
+++ b/c/sedona-proj/src/dyn_load.rs
@@ -0,0 +1,99 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+use std::path::Path;
+
+use libloading::Library;
+
+use crate::error::SedonaProjError;
+use crate::proj_dyn_bindgen::ProjApi;
+
+/// Load a single symbol from the library and write it into the given field.
+///
+/// We load as a raw `*const ()` pointer and transmute to the target function 
pointer
+/// type. This is the standard pattern for dynamic symbol loading where the 
loaded
+/// symbol's signature is known but cannot be expressed as a generic parameter 
to
+/// `Library::get` (because each field has a different signature).
+///
+/// On failure returns a `SedonaProjError` with the symbol name and the
+/// underlying OS error message.
+macro_rules! load_fn {
+    ($lib:expr, $api:expr, $name:ident) => {
+        // The target types here are too verbose to annotate for each call site
+        #[allow(clippy::missing_transmute_annotations)]
+        {
+            $api.$name = Some(unsafe {
+                let sym = $lib
+                    .get::<*const ()>(concat!(stringify!($name), 
"\0").as_bytes())
+                    .map_err(|e| {
+                        SedonaProjError::LibraryError(format!(
+                            "Failed to load symbol {}: {}",
+                            stringify!($name),
+                            e
+                        ))
+                    })?;
+                std::mem::transmute(sym.into_raw().into_raw())
+            });
+        }
+    };
+}
+
+/// Populate all 21 function-pointer fields of [`ProjApi`] from the given
+/// [`Library`] handle.
+fn load_all_symbols(lib: &Library, api: &mut ProjApi) -> Result<(), 
SedonaProjError> {
+    load_fn!(lib, api, proj_area_create);
+    load_fn!(lib, api, proj_area_destroy);
+    load_fn!(lib, api, proj_area_set_bbox);
+    load_fn!(lib, api, proj_context_create);
+    load_fn!(lib, api, proj_context_destroy);
+    load_fn!(lib, api, proj_context_errno_string);
+    load_fn!(lib, api, proj_context_errno);
+    load_fn!(lib, api, proj_context_set_database_path);
+    load_fn!(lib, api, proj_context_set_search_paths);
+    load_fn!(lib, api, proj_create_crs_to_crs_from_pj);
+    load_fn!(lib, api, proj_create);
+    load_fn!(lib, api, proj_cs_get_axis_count);
+    load_fn!(lib, api, proj_destroy);
+    load_fn!(lib, api, proj_errno_reset);
+    load_fn!(lib, api, proj_errno);
+    load_fn!(lib, api, proj_info);
+    load_fn!(lib, api, proj_log_level);
+    load_fn!(lib, api, proj_normalize_for_visualization);
+    load_fn!(lib, api, proj_trans);
+    load_fn!(lib, api, proj_trans_array);
+    load_fn!(lib, api, proj_as_projjson);
+
+    Ok(())
+}
+
+/// Load a PROJ shared library from `path` and populate a [`ProjApi`] struct.
+///
+/// Returns the `(Library, ProjApi)` pair. The caller is responsible for
+/// keeping the `Library` alive for the lifetime of the function pointers.
+pub(crate) fn load_proj_from_path(path: &Path) -> Result<(Library, ProjApi), 
SedonaProjError> {
+    let lib = unsafe { Library::new(path.as_os_str()) }.map_err(|e| {
+        SedonaProjError::LibraryError(format!(
+            "Failed to load PROJ library from {}: {}",
+            path.display(),
+            e
+        ))
+    })?;
+
+    let mut api = ProjApi::default();
+    load_all_symbols(&lib, &mut api)?;
+    Ok((lib, api))
+}
diff --git a/c/sedona-proj/src/lib.rs b/c/sedona-proj/src/lib.rs
index 6cc48eab..3cffe6fe 100644
--- a/c/sedona-proj/src/lib.rs
+++ b/c/sedona-proj/src/lib.rs
@@ -14,6 +14,7 @@
 // KIND, either express or implied.  See the License for the
 // specific language governing permissions and limitations
 // under the License.
+mod dyn_load;
 pub mod error;
 mod proj;
 mod proj_dyn_bindgen;
diff --git a/c/sedona-proj/src/proj.rs b/c/sedona-proj/src/proj.rs
index e52eb295..b267af41 100644
--- a/c/sedona-proj/src/proj.rs
+++ b/c/sedona-proj/src/proj.rs
@@ -42,7 +42,9 @@ use std::{
     sync::Arc,
 };
 
-use crate::{error::SedonaProjError, proj_dyn_bindgen};
+use libloading::Library;
+
+use crate::{dyn_load, error::SedonaProjError, proj_dyn_bindgen};
 
 /// A macro to safely call a function pointer from a ProjApi
 ///
@@ -449,24 +451,16 @@ impl Proj {
 /// loaded using C code; however, this could be migrated to Rust which also
 /// provides dynamic library loading capabilities.
 ///
-/// This API is thread safe and is marked as such; however, clients must not
-/// call the inner release callback. Doing so will set function pointers to
-/// null, which will cause subsequent calls to panic.
-#[derive(Default)]
+/// This API is thread safe and is marked as such. When loading PROJ from a
+/// shared library, the `_lib` field holds the `Library` handle, ensuring that
+/// the underlying library and its function pointers remain valid for the
+/// lifetime of this `ProjApi` instance.
 struct ProjApi {
     inner: proj_dyn_bindgen::ProjApi,
     name: String,
-}
-
-unsafe impl Send for ProjApi {}
-unsafe impl Sync for ProjApi {}
-
-impl Drop for ProjApi {
-    fn drop(&mut self) {
-        if let Some(releaser) = self.inner.release {
-            unsafe { releaser(&mut self.inner) }
-        }
-    }
+    /// Keep the dynamically loaded library alive for the lifetime of the 
function pointers.
+    /// `None` when using `proj-sys` (statically linked), `Some` when loaded 
from a shared library.
+    _lib: Option<Library>,
 }
 
 impl Debug for ProjApi {
@@ -477,31 +471,12 @@ impl Debug for ProjApi {
 
 impl ProjApi {
     fn try_from_shared_library(shared_library: PathBuf) -> Result<Arc<Self>, 
SedonaProjError> {
-        let mut inner = proj_dyn_bindgen::ProjApi::default();
-        let mut err_message = (0..1024).map(|_| 0).collect::<Vec<u8>>();
-        let shared_library_c = 
CString::new(shared_library.to_string_lossy().to_string())
-            .map_err(|_| SedonaProjError::Invalid("embedded nul in Rust 
string".to_string()))?;
-
-        let err = unsafe {
-            proj_dyn_bindgen::proj_dyn_api_init(
-                &mut inner as _,
-                shared_library_c.as_ptr(),
-                err_message.as_mut_ptr() as _,
-                err_message.len().try_into().unwrap(),
-            )
-        };
-
-        let c_err_message = CStr::from_bytes_until_nul(&err_message)
-            .map_err(|_| SedonaProjError::Invalid("embedded nul in C 
string".to_string()))?;
-        if err != 0 {
-            return Err(SedonaProjError::LibraryError(
-                c_err_message.to_string_lossy().to_string(),
-            ));
-        }
+        let (lib, inner) = dyn_load::load_proj_from_path(&shared_library)?;
 
         Ok(Arc::new(Self {
             inner,
             name: shared_library.to_string_lossy().to_string(),
+            _lib: Some(lib),
         }))
     }
 
@@ -624,6 +599,7 @@ impl ProjApi {
         Self {
             inner,
             name: "proj_sys".to_string(),
+            _lib: None,
         }
     }
 }
diff --git a/c/sedona-proj/src/proj_dyn.c b/c/sedona-proj/src/proj_dyn.c
deleted file mode 100644
index 69c54217..00000000
--- a/c/sedona-proj/src/proj_dyn.c
+++ /dev/null
@@ -1,150 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-
-#include "proj_dyn.h"
-
-// Original source:
-// 
https://github.com/apache/sedona/blob/670bb4c4a6fea49f0b0159ebdf2a92f00d3ed07a/python/src/geos_c_dyn.c
-
-#if defined(_WIN32)
-#define TARGETING_WINDOWS
-#include <tchar.h>
-#include <windows.h>
-#else
-#include <dlfcn.h>
-#include <errno.h>
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#ifdef TARGETING_WINDOWS
-static void win32_get_last_error(char* err_msg, int len) {
-  wchar_t info[256];
-  unsigned int error_code = GetLastError();
-  int info_length = FormatMessageW(
-      FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, /* flags */
-      NULL,                                                       /* message 
source*/
-      error_code,                                /* the message (error) ID */
-      MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* default language */
-      info,                                      /* the buffer */
-      sizeof(info) / sizeof(wchar_t),            /* size in wchars */
-      NULL);
-  int num_bytes =
-      WideCharToMultiByte(CP_UTF8, 0, info, info_length, err_msg, len, NULL, 
NULL);
-  num_bytes = (num_bytes < (len - 1)) ? num_bytes : (len - 1);
-  err_msg[num_bytes] = '\0';
-}
-#endif
-
-static void* try_load_proj_symbol(void* handle, const char* func_name) {
-#ifndef TARGETING_WINDOWS
-  return dlsym(handle, func_name);
-#else
-  return GetProcAddress((HMODULE)handle, func_name);
-#endif
-}
-
-static int load_proj_symbol(void* handle, const char* func_name, void** p_func,
-                            char* err_msg, int len) {
-  void* func = try_load_proj_symbol(handle, func_name);
-  if (func == NULL) {
-#ifndef TARGETING_WINDOWS
-    snprintf(err_msg, len, "%s", dlerror());
-#else
-    win32_get_last_error(err_msg, len);
-#endif
-    return -1;
-  }
-  *p_func = func;
-  return 0;
-}
-
-#define LOAD_PROJ_FUNCTION(api, func)                                          
     \
-  if (load_proj_symbol(handle, #func, (void**)(&(api)->func), err_msg, len) != 
0) { \
-    proj_dyn_release_api(api);                                                 
     \
-    return -1;                                                                 
     \
-  }
-
-static void proj_dyn_release_api(struct ProjApi* api) {
-#ifdef TARGETING_WINDOWS
-  FreeLibrary((HMODULE)api->private_data);
-#else
-  dlclose(api->private_data);
-#endif
-  memset(api, 0, sizeof(struct ProjApi));
-}
-
-static int load_proj_from_handle(struct ProjApi* api, void* handle, char* 
err_msg,
-                                 int len) {
-  LOAD_PROJ_FUNCTION(api, proj_area_create);
-  LOAD_PROJ_FUNCTION(api, proj_area_destroy);
-  LOAD_PROJ_FUNCTION(api, proj_area_set_bbox);
-  LOAD_PROJ_FUNCTION(api, proj_context_create);
-  LOAD_PROJ_FUNCTION(api, proj_context_destroy);
-  LOAD_PROJ_FUNCTION(api, proj_context_errno_string);
-  LOAD_PROJ_FUNCTION(api, proj_context_errno);
-  LOAD_PROJ_FUNCTION(api, proj_context_set_database_path);
-  LOAD_PROJ_FUNCTION(api, proj_context_set_search_paths);
-  LOAD_PROJ_FUNCTION(api, proj_create_crs_to_crs_from_pj);
-  LOAD_PROJ_FUNCTION(api, proj_create);
-  LOAD_PROJ_FUNCTION(api, proj_cs_get_axis_count);
-  LOAD_PROJ_FUNCTION(api, proj_destroy);
-  LOAD_PROJ_FUNCTION(api, proj_errno_reset);
-  LOAD_PROJ_FUNCTION(api, proj_errno);
-  LOAD_PROJ_FUNCTION(api, proj_info);
-  LOAD_PROJ_FUNCTION(api, proj_log_level);
-  LOAD_PROJ_FUNCTION(api, proj_normalize_for_visualization);
-  LOAD_PROJ_FUNCTION(api, proj_trans);
-  LOAD_PROJ_FUNCTION(api, proj_trans_array);
-  LOAD_PROJ_FUNCTION(api, proj_as_projjson);
-
-  api->release = &proj_dyn_release_api;
-  api->private_data = handle;
-
-  return 0;
-}
-
-#undef LOAD_PROJ_FUNCTION
-
-int proj_dyn_api_init(struct ProjApi* api, const char* shared_object_path, 
char* err_msg,
-                      int len) {
-#ifndef TARGETING_WINDOWS
-  void* handle = dlopen(shared_object_path, RTLD_LOCAL | RTLD_NOW);
-  if (handle == NULL) {
-    snprintf(err_msg, len, "%s", dlerror());
-    return -1;
-  }
-#else
-  int num_chars = MultiByteToWideChar(CP_UTF8, 0, shared_object_path, -1, 
NULL, 0);
-  wchar_t* wpath = calloc(num_chars, sizeof(wchar_t));
-  if (wpath == NULL) {
-    snprintf(err_msg, len, "%s", "Cannot allocate memory for wpath");
-    return -1;
-  }
-  MultiByteToWideChar(CP_UTF8, 0, shared_object_path, -1, wpath, num_chars);
-  HMODULE module = LoadLibraryW(wpath);
-  free(wpath);
-  if (module == NULL) {
-    win32_get_last_error(err_msg, len);
-    return -1;
-  }
-  void* handle = module;
-#endif
-  return load_proj_from_handle(api, handle, err_msg, len);
-}
diff --git a/c/sedona-proj/src/proj_dyn.h b/c/sedona-proj/src/proj_dyn.h
deleted file mode 100644
index 81e80503..00000000
--- a/c/sedona-proj/src/proj_dyn.h
+++ /dev/null
@@ -1,97 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-
-#include <stddef.h>
-
-#ifndef PROJ_DYN_H_INCLUDED
-#define PROJ_DYN_H_INCLUDED
-
-// Type definitions copied from proj.h
-struct pj_ctx;
-typedef struct pj_ctx PJ_CONTEXT;
-
-struct PJ_AREA;
-typedef struct PJ_AREA PJ_AREA;
-
-struct PJconsts;
-typedef struct PJconsts PJ;
-
-typedef struct {
-  double x, y, z, t;
-} PJ_XYZT;
-
-typedef union {
-  double v[4];
-  PJ_XYZT xyzt;
-} PJ_COORD;
-
-typedef enum { PJ_FWD = 1, PJ_IDENT = 0, PJ_INV = -1 } PJ_DIRECTION;
-
-typedef enum PJ_LOG_LEVEL {
-  PJ_LOG_NONE = 0,
-  PJ_LOG_ERROR = 1,
-  PJ_LOG_DEBUG = 2,
-  PJ_LOG_TRACE = 3,
-  PJ_LOG_TELL = 4,
-} PJ_LOG_LEVEL;
-
-typedef struct {
-  int major;
-  int minor;
-  int patch;
-  const char* release;
-  const char* version;
-  const char* searchpath;
-} PJ_INFO;
-
-struct ProjApi {
-  PJ_AREA* (*proj_area_create)(void);
-  void (*proj_area_destroy)(PJ_AREA* area);
-  int (*proj_area_set_bbox)(PJ_AREA* area, double west_lon_degree,
-                            double south_lat_degree, double east_lon_degree,
-                            double north_lat_degree);
-  PJ_CONTEXT* (*proj_context_create)(void);
-  void (*proj_context_destroy)(PJ_CONTEXT* ctx);
-  int (*proj_context_errno)(PJ_CONTEXT* ctx);
-  const char* (*proj_context_errno_string)(PJ_CONTEXT* ctx, int err);
-  int (*proj_context_set_database_path)(PJ_CONTEXT* ctx, const char* dbPath,
-                                        const char* const* auxDbPaths,
-                                        const char* const* options);
-  void (*proj_context_set_search_paths)(PJ_CONTEXT* ctx, int count_paths,
-                                        const char* const* paths);
-  PJ* (*proj_create)(PJ_CONTEXT* ctx, const char* definition);
-  PJ* (*proj_create_crs_to_crs_from_pj)(PJ_CONTEXT* ctx, PJ* source_crs, PJ* 
target_crs,
-                                        PJ_AREA* area, const char* const* 
options);
-  int (*proj_cs_get_axis_count)(PJ_CONTEXT* ctx, const PJ* cs);
-  void (*proj_destroy)(PJ* P);
-  int (*proj_errno)(const PJ* P);
-  void (*proj_errno_reset)(PJ* P);
-  PJ_INFO (*proj_info)(void);
-  PJ_LOG_LEVEL (*proj_log_level)(PJ_CONTEXT* ctx, PJ_LOG_LEVEL level);
-  PJ* (*proj_normalize_for_visualization)(PJ_CONTEXT* ctx, const PJ* obj);
-  PJ_COORD (*proj_trans)(PJ* P, PJ_DIRECTION direction, PJ_COORD coord);
-  PJ_COORD (*proj_trans_array)(PJ* P, PJ_DIRECTION direction, size_t n, 
PJ_COORD* coord);
-  const char* (*proj_as_projjson)(PJ_CONTEXT* ctx, const PJ* obj,
-                                  const char* const* options);
-  void (*release)(struct ProjApi*);
-  void* private_data;
-};
-
-int proj_dyn_api_init(struct ProjApi* api, const char* shared_object_path, 
char* err_msg,
-                      int len);
-
-#endif
diff --git a/c/sedona-proj/src/proj_dyn_bindgen.rs 
b/c/sedona-proj/src/proj_dyn_bindgen.rs
index 55ea2d9a..3e5c41b9 100644
--- a/c/sedona-proj/src/proj_dyn_bindgen.rs
+++ b/c/sedona-proj/src/proj_dyn_bindgen.rs
@@ -18,7 +18,7 @@
 #![allow(non_snake_case)]
 #![allow(dead_code)]
 
-use std::os::raw::{c_char, c_int, c_uint, c_void};
+use std::os::raw::{c_char, c_int, c_uint};
 
 #[repr(C)]
 #[derive(Debug, Copy, Clone)]
@@ -153,14 +153,4 @@ pub struct ProjApi {
         ) -> *const c_char,
     >,
     pub release: Option<unsafe extern "C" fn(arg1: *mut ProjApi)>,
-    pub private_data: *mut c_void,
-}
-
-unsafe extern "C" {
-    pub fn proj_dyn_api_init(
-        api: *mut ProjApi,
-        shared_object_path: *const c_char,
-        err_msg: *mut c_char,
-        len: c_int,
-    ) -> c_int;
 }

Reply via email to