This is an automated email from the ASF dual-hosted git repository.
CurtHagenlocher pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-adbc.git
The following commit(s) were added to refs/heads/main by this push:
new f143572846 fix(csharp): try fallback entrypoint on .NET Framework
(#4977)
f143572846 is described below
commit f1435728467ae03184b439770c073856b4a2b96e
Author: Bryce Mecum <[email protected]>
AuthorDate: Wed Oct 28 16:55:20 2026 -0700
fix(csharp): try fallback entrypoint on .NET Framework (#4977)
When no entrypoint is specified, the driver manager tries the entrypoint
derived from the driver's file name (e.g. `AdbcDriverSqliteInit`) and
then falls back to `AdbcDriverInit`. On the netstandard2.0 build (used
on .NET Framework), the fallback was never tried: that build uses its
own `NativeLibrary` shim, whose `GetExport` returns `IntPtr.Zero` for a
missing export instead of throwing `EntryPointNotFoundException`, and
the fallback only ran when an exception was thrown. So on .NET
Framework, a driver that exports only `AdbcDriverInit` failed to load
with "Unable to find ... export", while the same driver loaded fine on
.NET 8 and later.
This PR adds a test for this case and tries the fallback entrypoint
whether the first lookup throws or returns `IntPtr.Zero`.
Bug found and PR created with Opus 5.5.
---
.../src/Apache.Arrow.Adbc/C/CAdbcDriverImporter.cs | 6 +++
.../CAdbcDriverImporterFallbackTests.cs | 44 ++++++++++++++++++++++
2 files changed, 50 insertions(+)
diff --git a/csharp/src/Apache.Arrow.Adbc/C/CAdbcDriverImporter.cs
b/csharp/src/Apache.Arrow.Adbc/C/CAdbcDriverImporter.cs
index 603e4d7e49..6d4fc59e7a 100644
--- a/csharp/src/Apache.Arrow.Adbc/C/CAdbcDriverImporter.cs
+++ b/csharp/src/Apache.Arrow.Adbc/C/CAdbcDriverImporter.cs
@@ -93,6 +93,12 @@ namespace Apache.Arrow.Adbc.C
export = NativeLibrary.GetExport(library, entryPoint);
}
catch (EntryPointNotFoundException) when (fallbackEntryPoint
!= null)
+ {
+ export = IntPtr.Zero;
+ }
+ // The runtime's NativeLibrary.GetExport throws for a missing
export,
+ // but the netstandard2.0 NativeLibrary shim returns
IntPtr.Zero
+ if (export == IntPtr.Zero && fallbackEntryPoint != null)
{
export = NativeLibrary.GetExport(library,
fallbackEntryPoint);
}
diff --git
a/csharp/test/Apache.Arrow.Adbc.Tests/CAdbcDriverImporterFallbackTests.cs
b/csharp/test/Apache.Arrow.Adbc.Tests/CAdbcDriverImporterFallbackTests.cs
new file mode 100644
index 0000000000..aeb8c8686c
--- /dev/null
+++ b/csharp/test/Apache.Arrow.Adbc.Tests/CAdbcDriverImporterFallbackTests.cs
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+using System.IO;
+using System.Runtime.InteropServices;
+using Apache.Arrow.Adbc.C;
+using Xunit;
+
+namespace Apache.Arrow.Adbc.Tests
+{
+ public class CAdbcDriverImporterFallbackTests
+ {
+ // When the library doesn't export the requested entrypoint, the
fallback
+ // entrypoint should be used. DuckDB only exports duckdb_adbc_init.
+ [Fact]
+ public void LoadWithFallback_MissingEntrypoint_UsesFallback()
+ {
+ string duckDb = Path.Combine(
+ Directory.GetCurrentDirectory(),
+ RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ?
"duckdb.dll"
+ : RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ?
"libduckdb.dylib"
+ : "libduckdb.so");
+
+ using AdbcDriver driver = CAdbcDriverImporter.LoadWithFallback(
+ duckDb, "AdbcTestNoSuchEntrypoint", "duckdb_adbc_init");
+
+ Assert.NotNull(driver);
+ }
+ }
+}