10
10
11
11
public static class LibraryLoader
12
12
{
13
- public static nint LoadLibrary ( )
13
+ public static OSPlatform FreeBSD { get ; } = OSPlatform . Create ( "FREEBSD" ) ;
14
+
15
+ public static OSPlatform Linux { get ; } = OSPlatform . Create ( "LINUX" ) ;
16
+
17
+ public static OSPlatform OSX { get ; } = OSPlatform . Create ( "OSX" ) ;
18
+
19
+ public static OSPlatform Windows { get ; } = OSPlatform . Create ( "WINDOWS" ) ;
20
+
21
+ public static OSPlatform Android { get ; } = OSPlatform . Create ( "ANDROID" ) ;
22
+
23
+ public static OSPlatform IOS { get ; } = OSPlatform . Create ( "IOS" ) ;
24
+
25
+ public static OSPlatform Tizen { get ; } = OSPlatform . Create ( "TIZEN" ) ;
26
+
27
+ public static OSPlatform ChromeOS { get ; } = OSPlatform . Create ( "CHROMEOS" ) ;
28
+
29
+ public static OSPlatform WebAssembly { get ; } = OSPlatform . Create ( "WEBASSEMBLY" ) ;
30
+
31
+ public static OSPlatform Solaris { get ; } = OSPlatform . Create ( "SOLARIS" ) ;
32
+
33
+ public static OSPlatform WatchOS { get ; } = OSPlatform . Create ( "WATCHOS" ) ;
34
+
35
+ public static OSPlatform TVOS { get ; } = OSPlatform . Create ( "TVOS" ) ;
36
+
37
+ public static string GetExtension ( IEnumerable < NativeLibraryExtensionAttribute > extensionAttributes )
14
38
{
15
- if ( RuntimeInformation . IsOSPlatform ( OSPlatform . Windows ) )
39
+ foreach ( var extensionAttribute in extensionAttributes )
16
40
{
17
- return LoadLocalLibrary ( "bgfx" ) ;
41
+ if ( RuntimeInformation . IsOSPlatform ( extensionAttribute . TargetPlatform ) )
42
+ {
43
+ return extensionAttribute . Extension ;
44
+ }
18
45
}
19
- else if ( RuntimeInformation . IsOSPlatform ( OSPlatform . Linux ) )
46
+
47
+ // Default extension based on platform
48
+ if ( RuntimeInformation . IsOSPlatform ( Windows ) )
20
49
{
21
- return LoadLocalLibrary ( "bgfx" ) ;
50
+ return ".dll" ;
22
51
}
23
- else if ( RuntimeInformation . IsOSPlatform ( OSPlatform . OSX ) )
52
+ else if ( RuntimeInformation . IsOSPlatform ( OSX ) )
24
53
{
25
- return LoadLocalLibrary ( "bgfx" ) ;
54
+ return ".dylib" ;
26
55
}
27
- else
56
+ else if ( RuntimeInformation . IsOSPlatform ( Linux ) )
28
57
{
29
- return LoadLocalLibrary ( "bgfx" ) ;
58
+ return ".so" ;
30
59
}
31
- }
32
-
33
- public static string GetExtension ( )
34
- {
35
- if ( RuntimeInformation . IsOSPlatform ( OSPlatform . Windows ) )
60
+ else if ( RuntimeInformation . IsOSPlatform ( Android ) )
36
61
{
37
- return ".dll " ;
62
+ return ".so " ;
38
63
}
39
- else if ( RuntimeInformation . IsOSPlatform ( OSPlatform . OSX ) )
64
+ else if ( RuntimeInformation . IsOSPlatform ( IOS ) )
40
65
{
41
- return ".dylib" ;
66
+ return ".dylib" ; // iOS also uses .dylib for dynamic libraries
42
67
}
43
- else if ( RuntimeInformation . IsOSPlatform ( OSPlatform . Linux ) )
68
+ else if ( RuntimeInformation . IsOSPlatform ( FreeBSD ) )
69
+ {
70
+ return ".so" ;
71
+ }
72
+ else if ( RuntimeInformation . IsOSPlatform ( TVOS ) )
73
+ {
74
+ return ".dylib" ; // tvOS uses the same dynamic library extension as iOS
75
+ }
76
+ else if ( RuntimeInformation . IsOSPlatform ( WatchOS ) )
77
+ {
78
+ return ".dylib" ; // watchOS also uses .dylib
79
+ }
80
+ else if ( RuntimeInformation . IsOSPlatform ( Solaris ) )
81
+ {
82
+ return ".so" ;
83
+ }
84
+ else if ( RuntimeInformation . IsOSPlatform ( WebAssembly ) )
85
+ {
86
+ return ".wasm" ;
87
+ }
88
+ else if ( RuntimeInformation . IsOSPlatform ( Tizen ) )
89
+ {
90
+ return ".so" ;
91
+ }
92
+ else if ( RuntimeInformation . IsOSPlatform ( ChromeOS ) )
44
93
{
45
94
return ".so" ;
46
95
}
47
96
97
+ // Default to .so if no platform matches
48
98
return ".so" ;
49
99
}
50
100
51
- public static nint LoadLocalLibrary ( string libraryName )
101
+ public static nint LoadLibrary ( )
52
102
{
53
- var extension = GetExtension ( ) ;
103
+ var libraryAttributes = Assembly . GetCallingAssembly ( ) . GetCustomAttributes < NativeLibraryAttribute > ( ) ;
104
+ var extensionAttributes = Assembly . GetCallingAssembly ( ) . GetCustomAttributes < NativeLibraryExtensionAttribute > ( ) ;
105
+
106
+ var libraryName = GetLibraryName ( libraryAttributes ) ;
107
+
108
+ var extension = GetExtension ( extensionAttributes ) ;
54
109
55
110
if ( ! libraryName . EndsWith ( extension , StringComparison . OrdinalIgnoreCase ) )
56
111
{
@@ -59,74 +114,133 @@ public static nint LoadLocalLibrary(string libraryName)
59
114
60
115
var osPlatform = GetOSPlatform ( ) ;
61
116
var architecture = GetArchitecture ( ) ;
62
-
63
117
var libraryPath = GetNativeAssemblyPath ( osPlatform , architecture , libraryName ) ;
64
118
65
- static string GetOSPlatform ( )
66
- {
67
- if ( RuntimeInformation . IsOSPlatform ( OSPlatform . Windows ) )
68
- {
69
- return "win" ;
70
- }
71
- else if ( RuntimeInformation . IsOSPlatform ( OSPlatform . Linux ) )
72
- {
73
- return "linux" ;
74
- }
75
- else if ( RuntimeInformation . IsOSPlatform ( OSPlatform . OSX ) )
76
- {
77
- return "osx" ;
78
- }
119
+ nint handle ;
79
120
80
- throw new ArgumentException ( "Unsupported OS platform." ) ;
81
- }
121
+ handle = NativeLibrary . Load ( libraryPath ) ;
82
122
83
- static string GetArchitecture ( )
123
+ if ( handle == IntPtr . Zero )
84
124
{
85
- return RuntimeInformation . ProcessArchitecture switch
86
- {
87
- Architecture . X86 => "x86" ,
88
- Architecture . X64 => "x64" ,
89
- Architecture . Arm => "arm" ,
90
- Architecture . Arm64 => "arm64" ,
91
- _ => throw new ArgumentException ( "Unsupported architecture." ) ,
92
- } ;
125
+ throw new DllNotFoundException ( $ "Unable to load library '{ libraryName } '.") ;
93
126
}
94
127
95
- var attribute = Assembly . GetCallingAssembly ( ) . GetCustomAttribute < NativeLibraryAttribute > ( ) ;
96
- var methods = typeof ( string ) . GetMethods ( ) ;
128
+ return handle ;
129
+ }
97
130
98
- static string GetNativeAssemblyPath ( string osPlatform , string architecture , string libraryName )
99
- {
100
- var assemblyLocation = AppContext . BaseDirectory ;
131
+ private static string GetNativeAssemblyPath ( string osPlatform , string architecture , string libraryName )
132
+ {
133
+ var assemblyLocation = AppContext . BaseDirectory ;
101
134
102
- var paths = new [ ]
103
- {
135
+ var paths = new [ ]
136
+ {
104
137
Path . Combine ( assemblyLocation , libraryName ) ,
105
138
Path . Combine ( assemblyLocation , "runtimes" , osPlatform , "native" , libraryName ) ,
139
+ Path . Combine ( assemblyLocation , "runtimes" , $ "{ osPlatform } -{ architecture } ", "debug" , libraryName ) , // allows debug builds sideload.
106
140
Path . Combine ( assemblyLocation , "runtimes" , $ "{ osPlatform } -{ architecture } ", "native" , libraryName ) ,
107
141
} ;
108
142
109
- foreach ( var path in paths )
143
+ foreach ( var path in paths )
144
+ {
145
+ if ( File . Exists ( path ) )
110
146
{
111
- if ( File . Exists ( path ) )
112
- {
113
- return path ;
114
- }
147
+ return path ;
115
148
}
149
+ }
116
150
117
- return libraryName ;
151
+ return libraryName ;
152
+ }
153
+
154
+ private static string GetArchitecture ( )
155
+ {
156
+ return RuntimeInformation . ProcessArchitecture switch
157
+ {
158
+ Architecture . X86 => "x86" ,
159
+ Architecture . X64 => "x64" ,
160
+ Architecture . Arm => "arm" ,
161
+ Architecture . Arm64 => "arm64" ,
162
+ _ => throw new ArgumentException ( "Unsupported architecture." ) ,
163
+ } ;
164
+ }
165
+
166
+ private static string GetOSPlatform ( )
167
+ {
168
+ if ( RuntimeInformation . IsOSPlatform ( Windows ) )
169
+ {
170
+ return "win" ;
171
+ }
172
+ else if ( RuntimeInformation . IsOSPlatform ( Linux ) )
173
+ {
174
+ return "linux" ;
175
+ }
176
+ else if ( RuntimeInformation . IsOSPlatform ( OSX ) )
177
+ {
178
+ return "osx" ;
179
+ }
180
+ else if ( RuntimeInformation . IsOSPlatform ( Android ) )
181
+ {
182
+ return "android" ;
183
+ }
184
+ else if ( RuntimeInformation . IsOSPlatform ( IOS ) )
185
+ {
186
+ return "ios" ;
187
+ }
188
+ else if ( RuntimeInformation . IsOSPlatform ( OSPlatform . Create ( "FREEBSD" ) ) )
189
+ {
190
+ return "freebsd" ;
191
+ }
192
+ else if ( RuntimeInformation . IsOSPlatform ( OSPlatform . Create ( "TVOS" ) ) )
193
+ {
194
+ return "tvos" ;
195
+ }
196
+ else if ( RuntimeInformation . IsOSPlatform ( OSPlatform . Create ( "WATCHOS" ) ) )
197
+ {
198
+ return "watchos" ;
199
+ }
200
+ else if ( RuntimeInformation . IsOSPlatform ( OSPlatform . Create ( "SOLARIS" ) ) )
201
+ {
202
+ return "solaris" ;
203
+ }
204
+ else if ( RuntimeInformation . IsOSPlatform ( OSPlatform . Create ( "WEBASSEMBLY" ) ) )
205
+ {
206
+ return "webassembly" ;
207
+ }
208
+ else if ( RuntimeInformation . IsOSPlatform ( OSPlatform . Create ( "TIZEN" ) ) )
209
+ {
210
+ return "tizen" ;
211
+ }
212
+ else if ( RuntimeInformation . IsOSPlatform ( OSPlatform . Create ( "CHROMEOS" ) ) )
213
+ {
214
+ return "chromeos" ;
118
215
}
119
216
120
- nint handle ;
217
+ throw new ArgumentException ( "Unsupported OS platform." ) ;
218
+ }
121
219
122
- handle = NativeLibrary . Load ( libraryPath ) ;
220
+ private static string GetLibraryName ( IEnumerable < NativeLibraryAttribute > nativeLibraries )
221
+ {
222
+ NativeLibraryAttribute ? nativeLibrary = null ;
223
+ foreach ( NativeLibraryAttribute attri in nativeLibraries )
224
+ {
225
+ if ( attri . TargetPlatform == null )
226
+ {
227
+ nativeLibrary = attri ; // Default
228
+ continue ;
229
+ }
123
230
124
- if ( handle == IntPtr . Zero )
231
+ if ( RuntimeInformation . IsOSPlatform ( attri . TargetPlatform . Value ) )
232
+ {
233
+ nativeLibrary = attri ;
234
+ break ;
235
+ }
236
+ }
237
+
238
+ if ( nativeLibrary == null )
125
239
{
126
- throw new DllNotFoundException ( $ "Unable to load library ' { libraryName } '. ") ;
240
+ throw new Exception ( "Dll not specified for this platform ") ;
127
241
}
128
242
129
- return handle ;
243
+ return nativeLibrary . LibraryName ;
130
244
}
131
245
}
132
246
@@ -136,7 +250,6 @@ public sealed class NativeLibraryExtensionAttribute : Attribute
136
250
private readonly string extension ;
137
251
private readonly OSPlatform targetPlatform ;
138
252
139
-
140
253
public NativeLibraryExtensionAttribute ( string extension , OSPlatform targetPlatform )
141
254
{
142
255
this . extension = extension ;
@@ -152,24 +265,16 @@ public NativeLibraryExtensionAttribute(string extension, OSPlatform targetPlatfo
152
265
public sealed class NativeLibraryAttribute : Attribute
153
266
{
154
267
private readonly string libraryName ;
155
- private readonly OSPlatform targetPlatform ;
268
+ private readonly OSPlatform ? targetPlatform ;
156
269
157
- public NativeLibraryAttribute ( string libraryName , OSPlatform targetPlatform )
270
+ public NativeLibraryAttribute ( string libraryName , OSPlatform ? targetPlatform = null )
158
271
{
159
272
this . libraryName = libraryName ;
160
- this . TargetPlatform = targetPlatform ;
273
+ this . targetPlatform = targetPlatform ;
161
274
}
162
275
163
276
public string LibraryName => libraryName ;
164
277
165
- public OSPlatform TargetPlatform => targetPlatform ;
166
- }
167
-
168
- public enum TargetPlatform
169
- {
170
- Windows ,
171
- Linux ,
172
- OSX ,
173
- Android ,
278
+ public OSPlatform ? TargetPlatform => targetPlatform ;
174
279
}
175
280
}
0 commit comments