Skip to content

Commit 0177f66

Browse files
committed
Add support for custom path resolution
1 parent 63914b5 commit 0177f66

File tree

2 files changed

+78
-7
lines changed

2 files changed

+78
-7
lines changed

HexaGen.Runtime/HexaGen.Runtime.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
<IsAotCompatible>true</IsAotCompatible>
1515

1616
<AssemblyVersion>1.1.0</AssemblyVersion>
17-
<PackageVersion>1.1.16</PackageVersion>
17+
<PackageVersion>1.1.17</PackageVersion>
1818
<Description>The C Runtime for all C Wrappers generated with the HexaGen Code Generator.</Description>
1919
<Authors>Juna Meinhold</Authors>
2020
<Copyright>Copyright (c) 2024 Juna Meinhold</Copyright>

HexaGen.Runtime/LibraryLoader.cs

Lines changed: 77 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ public enum TargetPlatform
3030
Any = FreeBSD | Linux | OSX | Windows | Android | IOS | Tizen | ChromeOS | WebAssembly | Solaris | WatchOS | TVO
3131
}
3232

33+
public delegate void ResolvePathHandler(string libraryName, out string? pathToLibrary);
34+
35+
public delegate void LibraryNameInterceptor(ref string libraryName);
36+
3337
public static class LibraryLoader
3438
{
3539
public static OSPlatform FreeBSD { get; } = OSPlatform.Create("FREEBSD");
@@ -56,6 +60,12 @@ public static class LibraryLoader
5660

5761
public static OSPlatform TVOS { get; } = OSPlatform.Create("TVOS");
5862

63+
public static List<string> CustomLoadFolders { get; } = [];
64+
65+
public static ResolvePathHandler? ResolvePath;
66+
67+
public static LibraryNameInterceptor? InterceptLibraryName;
68+
5969
public static string GetExtension()
6070
{
6171
// Default extension based on platform
@@ -120,6 +130,8 @@ public static nint LoadLibrary(LibraryNameCallback libraryNameCallback, LibraryE
120130
{
121131
var libraryName = libraryNameCallback();
122132

133+
InterceptLibraryName?.Invoke(ref libraryName);
134+
123135
var extension = libraryExtensionCallback != null ? libraryExtensionCallback() : GetExtension();
124136

125137
if (!libraryName.EndsWith(extension, StringComparison.OrdinalIgnoreCase))
@@ -145,6 +157,12 @@ public static nint LoadLibrary(LibraryNameCallback libraryNameCallback, LibraryE
145157

146158
private static string GetNativeAssemblyPath(string osPlatform, string architecture, string libraryName)
147159
{
160+
if (ResolvePath != null)
161+
{
162+
ResolvePath.Invoke(libraryName, out var pathToLibrary);
163+
if (pathToLibrary != null) return pathToLibrary;
164+
}
165+
148166
#if ANDROID
149167
// Get the application info
150168
ApplicationInfo appInfo = Application.Context.ApplicationInfo!;
@@ -156,13 +174,25 @@ private static string GetNativeAssemblyPath(string osPlatform, string architectu
156174
string assemblyLocation = AppContext.BaseDirectory;
157175
#endif
158176

159-
var paths = new[]
177+
List<string> paths =
178+
[
179+
Path.Combine(assemblyLocation, libraryName),
180+
Path.Combine(assemblyLocation, "runtimes", osPlatform, "native", libraryName),
181+
Path.Combine(assemblyLocation, "runtimes", $"{osPlatform}-{architecture}", "debug", libraryName), // allows debug builds sideload.
182+
Path.Combine(assemblyLocation, "runtimes", $"{osPlatform}-{architecture}", "native", libraryName),
183+
];
184+
185+
foreach (var customPath in CustomLoadFolders)
160186
{
161-
Path.Combine(assemblyLocation, libraryName),
162-
Path.Combine(assemblyLocation, "runtimes", osPlatform, "native", libraryName),
163-
Path.Combine(assemblyLocation, "runtimes", $"{osPlatform}-{architecture}", "debug", libraryName), // allows debug builds sideload.
164-
Path.Combine(assemblyLocation, "runtimes", $"{osPlatform}-{architecture}", "native", libraryName),
165-
};
187+
if (IsPathFullyQualified(customPath))
188+
{
189+
paths.Add(Path.Combine(customPath, libraryName));
190+
}
191+
else
192+
{
193+
paths.Add(Path.Combine(assemblyLocation, customPath, libraryName));
194+
}
195+
}
166196

167197
foreach (var path in paths)
168198
{
@@ -175,6 +205,47 @@ private static string GetNativeAssemblyPath(string osPlatform, string architectu
175205
return libraryName;
176206
}
177207

208+
public static bool IsPathFullyQualified(string path)
209+
{
210+
if (path.Length == 0)
211+
{
212+
return false;
213+
}
214+
215+
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
216+
{
217+
return IsFullyQualifiedWindows(path);
218+
}
219+
220+
return IsFullyQualifiedUnix(path);
221+
}
222+
223+
private static bool IsFullyQualifiedWindows(string path)
224+
{
225+
if (path.Length < 2)
226+
{
227+
return false;
228+
}
229+
230+
if (char.IsLetter(path[0]) && path[1] == ':' &&
231+
(path.Length > 2 && (path[2] == '\\' || path[2] == '/')))
232+
{
233+
return true;
234+
}
235+
236+
if (path.Length > 1 && path[0] == '\\' && path[1] == '\\')
237+
{
238+
return true;
239+
}
240+
241+
return false;
242+
}
243+
244+
private static bool IsFullyQualifiedUnix(string path)
245+
{
246+
return path.Length > 0 && path[0] == '/';
247+
}
248+
178249
private static string GetArchitecture()
179250
{
180251
return RuntimeInformation.ProcessArchitecture switch

0 commit comments

Comments
 (0)