@@ -30,6 +30,10 @@ public enum TargetPlatform
30
30
Any = FreeBSD | Linux | OSX | Windows | Android | IOS | Tizen | ChromeOS | WebAssembly | Solaris | WatchOS | TVO
31
31
}
32
32
33
+ public delegate void ResolvePathHandler ( string libraryName , out string ? pathToLibrary ) ;
34
+
35
+ public delegate void LibraryNameInterceptor ( ref string libraryName ) ;
36
+
33
37
public static class LibraryLoader
34
38
{
35
39
public static OSPlatform FreeBSD { get ; } = OSPlatform . Create ( "FREEBSD" ) ;
@@ -56,6 +60,12 @@ public static class LibraryLoader
56
60
57
61
public static OSPlatform TVOS { get ; } = OSPlatform . Create ( "TVOS" ) ;
58
62
63
+ public static List < string > CustomLoadFolders { get ; } = [ ] ;
64
+
65
+ public static ResolvePathHandler ? ResolvePath ;
66
+
67
+ public static LibraryNameInterceptor ? InterceptLibraryName ;
68
+
59
69
public static string GetExtension ( )
60
70
{
61
71
// Default extension based on platform
@@ -120,6 +130,8 @@ public static nint LoadLibrary(LibraryNameCallback libraryNameCallback, LibraryE
120
130
{
121
131
var libraryName = libraryNameCallback ( ) ;
122
132
133
+ InterceptLibraryName ? . Invoke ( ref libraryName ) ;
134
+
123
135
var extension = libraryExtensionCallback != null ? libraryExtensionCallback ( ) : GetExtension ( ) ;
124
136
125
137
if ( ! libraryName . EndsWith ( extension , StringComparison . OrdinalIgnoreCase ) )
@@ -145,6 +157,12 @@ public static nint LoadLibrary(LibraryNameCallback libraryNameCallback, LibraryE
145
157
146
158
private static string GetNativeAssemblyPath ( string osPlatform , string architecture , string libraryName )
147
159
{
160
+ if ( ResolvePath != null )
161
+ {
162
+ ResolvePath . Invoke ( libraryName , out var pathToLibrary ) ;
163
+ if ( pathToLibrary != null ) return pathToLibrary ;
164
+ }
165
+
148
166
#if ANDROID
149
167
// Get the application info
150
168
ApplicationInfo appInfo = Application . Context . ApplicationInfo ! ;
@@ -156,13 +174,25 @@ private static string GetNativeAssemblyPath(string osPlatform, string architectu
156
174
string assemblyLocation = AppContext . BaseDirectory ;
157
175
#endif
158
176
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 )
160
186
{
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
+ }
166
196
167
197
foreach ( var path in paths )
168
198
{
@@ -175,6 +205,47 @@ private static string GetNativeAssemblyPath(string osPlatform, string architectu
175
205
return libraryName ;
176
206
}
177
207
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
+
178
249
private static string GetArchitecture ( )
179
250
{
180
251
return RuntimeInformation . ProcessArchitecture switch
0 commit comments