12
12
// See the License for the specific language governing permissions and
13
13
// limitations under the License.
14
14
15
- #define GUICS
16
15
using System . Diagnostics . CodeAnalysis ;
17
16
using System . Runtime . InteropServices ;
18
17
@@ -27,81 +26,6 @@ namespace Unix.Terminal;
27
26
/// </summary>
28
27
internal class UnmanagedLibrary
29
28
{
30
- private const string UnityEngineApplicationClassName = "UnityEngine.Application, UnityEngine" ;
31
- private const string XamarinAndroidObjectClassName = "Java.Lang.Object, Mono.Android" ;
32
- private const string XamarinIOSObjectClassName = "Foundation.NSObject, Xamarin.iOS" ;
33
- private static readonly bool IsWindows ;
34
- private static readonly bool IsLinux ;
35
- private static readonly bool Is64Bit ;
36
- #if GUICS
37
- private static readonly bool IsMono ;
38
- #else
39
- static bool IsMono , IsUnity , IsXamarinIOS , IsXamarinAndroid , IsXamarin ;
40
- #endif
41
- private static bool IsNetCore ;
42
- public static bool IsMacOSPlatform { get ; }
43
-
44
- [ DllImport ( "libc" ) ]
45
- private static extern int uname ( nint buf ) ;
46
-
47
- private static string GetUname ( )
48
- {
49
- nint buffer = Marshal . AllocHGlobal ( 8192 ) ;
50
-
51
- try
52
- {
53
- if ( uname ( buffer ) == 0 )
54
- {
55
- return Marshal . PtrToStringAnsi ( buffer ) ;
56
- }
57
-
58
- return string . Empty ;
59
- }
60
- catch
61
- {
62
- return string . Empty ;
63
- }
64
- finally
65
- {
66
- if ( buffer != nint . Zero )
67
- {
68
- Marshal . FreeHGlobal ( buffer ) ;
69
- }
70
- }
71
- }
72
-
73
- [ UnconditionalSuppressMessage ( "AOT" , "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling." , Justification = "<Pending>" ) ]
74
- static UnmanagedLibrary ( )
75
- {
76
- PlatformID platform = Environment . OSVersion . Platform ;
77
-
78
- IsMacOSPlatform = platform == PlatformID . Unix && GetUname ( ) == "Darwin" ;
79
- IsLinux = platform == PlatformID . Unix && ! IsMacOSPlatform ;
80
-
81
- IsWindows = platform == PlatformID . Win32NT
82
- || platform == PlatformID . Win32S
83
- || platform == PlatformID . Win32Windows ;
84
- Is64Bit = Marshal . SizeOf ( typeof ( nint ) ) == 8 ;
85
- IsMono = Type . GetType ( "Mono.Runtime" ) != null ;
86
-
87
- if ( ! IsMono )
88
- {
89
- IsNetCore = Type . GetType ( "System.MathF" ) != null ;
90
- }
91
- #if GUICS
92
-
93
- //IsUnity = IsXamarinIOS = IsXamarinAndroid = IsXamarin = false;
94
- #else
95
- IsUnity = Type . GetType ( UnityEngineApplicationClassName ) != null ;
96
- IsXamarinIOS = Type . GetType ( XamarinIOSObjectClassName ) != null ;
97
- IsXamarinAndroid = Type . GetType ( XamarinAndroidObjectClassName ) != null ;
98
- IsXamarin = IsXamarinIOS || IsXamarinAndroid ;
99
- #endif
100
- }
101
-
102
- // flags for dlopen
103
- private const int RTLD_LAZY = 1 ;
104
- private const int RTLD_GLOBAL = 8 ;
105
29
public readonly string LibraryPath ;
106
30
public nint NativeLibraryHandle { get ; }
107
31
@@ -114,15 +38,25 @@ public UnmanagedLibrary (string [] libraryPathAlternatives, bool isFullPath)
114
38
{
115
39
if ( isFullPath )
116
40
{
117
- LibraryPath = FirstValidLibraryPath ( libraryPathAlternatives ) ;
118
- NativeLibraryHandle = PlatformSpecificLoadLibrary ( LibraryPath ) ;
41
+ foreach ( string path in libraryPathAlternatives )
42
+ {
43
+ if ( File . Exists ( path ) )
44
+ {
45
+ LibraryPath = path ;
46
+ break ;
47
+ }
48
+ }
49
+
50
+ if ( LibraryPath is null )
51
+ throw new FileNotFoundException ( $ "Error loading native library. Not found in any of the possible locations: { string . Join ( "," , libraryPathAlternatives ) } ") ;
52
+
53
+ NativeLibraryHandle = NativeLibrary . Load ( LibraryPath ) ;
119
54
}
120
55
else
121
56
{
122
57
foreach ( string lib in libraryPathAlternatives )
123
58
{
124
- NativeLibraryHandle = PlatformSpecificLoadLibrary ( lib ) ;
125
-
59
+ NativeLibraryHandle = NativeLibrary . Load ( lib ) ;
126
60
if ( NativeLibraryHandle != nint . Zero )
127
61
{
128
62
LibraryPath = lib ;
@@ -143,55 +77,7 @@ public UnmanagedLibrary (string [] libraryPathAlternatives, bool isFullPath)
143
77
/// <returns></returns>
144
78
public nint LoadSymbol ( string symbolName )
145
79
{
146
- if ( IsWindows )
147
- {
148
- // See http://stackoverflow.com/questions/10473310 for background on this.
149
- if ( Is64Bit )
150
- {
151
- return Windows . GetProcAddress ( NativeLibraryHandle , symbolName ) ;
152
- }
153
-
154
- // Yes, we could potentially predict the size... but it's a lot simpler to just try
155
- // all the candidates. Most functions have a suffix of @0, @4 or @8 so we won't be trying
156
- // many options - and if it takes a little bit longer to fail if we've really got the wrong
157
- // library, that's not a big problem. This is only called once per function in the native library.
158
- symbolName = "_" + symbolName + "@" ;
159
-
160
- for ( var stackSize = 0 ; stackSize < 128 ; stackSize += 4 )
161
- {
162
- nint candidate = Windows . GetProcAddress ( NativeLibraryHandle , symbolName + stackSize ) ;
163
-
164
- if ( candidate != nint . Zero )
165
- {
166
- return candidate ;
167
- }
168
- }
169
-
170
- // Fail.
171
- return nint . Zero ;
172
- }
173
-
174
- if ( IsLinux )
175
- {
176
- if ( IsMono )
177
- {
178
- return Mono . dlsym ( NativeLibraryHandle , symbolName ) ;
179
- }
180
-
181
- if ( IsNetCore )
182
- {
183
- return CoreCLR . dlsym ( NativeLibraryHandle , symbolName ) ;
184
- }
185
-
186
- return Linux . dlsym ( NativeLibraryHandle , symbolName ) ;
187
- }
188
-
189
- if ( IsMacOSPlatform )
190
- {
191
- return MacOSX . dlsym ( NativeLibraryHandle , symbolName ) ;
192
- }
193
-
194
- throw new InvalidOperationException ( "Unsupported platform." ) ;
80
+ return NativeLibrary . GetExport ( NativeLibraryHandle , symbolName ) ;
195
81
}
196
82
197
83
public T GetNativeMethodDelegate < T > ( string methodName )
@@ -206,128 +92,4 @@ public T GetNativeMethodDelegate<T> (string methodName)
206
92
207
93
return Marshal . GetDelegateForFunctionPointer < T > ( ptr ) ; // non-generic version is obsolete
208
94
}
209
-
210
- /// <summary>Loads library in a platform specific way.</summary>
211
- private static nint PlatformSpecificLoadLibrary ( string libraryPath )
212
- {
213
- if ( IsWindows )
214
- {
215
- return Windows . LoadLibrary ( libraryPath ) ;
216
- }
217
-
218
- if ( IsLinux )
219
- {
220
- if ( IsMono )
221
- {
222
- return Mono . dlopen ( libraryPath , RTLD_GLOBAL + RTLD_LAZY ) ;
223
- }
224
-
225
- if ( IsNetCore )
226
- {
227
- try
228
- {
229
- return CoreCLR . dlopen ( libraryPath , RTLD_GLOBAL + RTLD_LAZY ) ;
230
- }
231
- catch ( Exception )
232
- {
233
- IsNetCore = false ;
234
- }
235
- }
236
-
237
- return Linux . dlopen ( libraryPath , RTLD_GLOBAL + RTLD_LAZY ) ;
238
- }
239
-
240
- if ( IsMacOSPlatform )
241
- {
242
- return MacOSX . dlopen ( libraryPath , RTLD_GLOBAL + RTLD_LAZY ) ;
243
- }
244
-
245
- throw new InvalidOperationException ( "Unsupported platform." ) ;
246
- }
247
-
248
- private static string FirstValidLibraryPath ( string [ ] libraryPathAlternatives )
249
- {
250
- foreach ( string path in libraryPathAlternatives )
251
- {
252
- if ( File . Exists ( path ) )
253
- {
254
- return path ;
255
- }
256
- }
257
-
258
- throw new FileNotFoundException (
259
- string . Format (
260
- "Error loading native library. Not found in any of the possible locations: {0}" ,
261
- string . Join ( "," , libraryPathAlternatives )
262
- )
263
- ) ;
264
- }
265
-
266
- private static class Windows
267
- {
268
- [ DllImport ( "kernel32.dll" ) ]
269
- internal static extern nint GetProcAddress ( nint hModule , string procName ) ;
270
-
271
- [ DllImport ( "kernel32.dll" ) ]
272
- internal static extern nint LoadLibrary ( string filename ) ;
273
- }
274
-
275
- private static class Linux
276
- {
277
- [ DllImport ( "libdl.so" ) ]
278
- internal static extern nint dlopen ( string filename , int flags ) ;
279
-
280
- [ DllImport ( "libdl.so" ) ]
281
- internal static extern nint dlsym ( nint handle , string symbol ) ;
282
- }
283
-
284
- private static class MacOSX
285
- {
286
- [ DllImport ( "libSystem.dylib" ) ]
287
- internal static extern nint dlopen ( string filename , int flags ) ;
288
-
289
- [ DllImport ( "libSystem.dylib" ) ]
290
- internal static extern nint dlsym ( nint handle , string symbol ) ;
291
- }
292
-
293
- /// <summary>
294
- /// On Linux systems, using dlopen and dlsym results in DllNotFoundException("libdl.so not found") if
295
- /// libc6-dev is not installed. As a workaround, we load symbols for dlopen and dlsym from the current process as on
296
- /// Linux Mono sure is linked against these symbols.
297
- /// </summary>
298
- private static class Mono
299
- {
300
- [ DllImport ( "__Internal" ) ]
301
- internal static extern nint dlopen ( string filename , int flags ) ;
302
-
303
- [ DllImport ( "__Internal" ) ]
304
- internal static extern nint dlsym ( nint handle , string symbol ) ;
305
- }
306
-
307
- /// <summary>
308
- /// Similarly as for Mono on Linux, we load symbols for dlopen and dlsym from the "libcoreclr.so", to avoid the
309
- /// dependency on libc-dev Linux.
310
- /// </summary>
311
- private static class CoreCLR
312
- {
313
- // Custom resolver to support true single-file apps
314
- // (those which run directly from bundle; in-memory).
315
- // -1 on Unix means self-referencing binary (libcoreclr.so)
316
- // 0 means fallback to CoreCLR's internal resolution
317
- // Note: meaning of -1 stay the same even for non-single-file form factors.
318
- static CoreCLR ( )
319
- {
320
- NativeLibrary . SetDllImportResolver (
321
- typeof ( CoreCLR ) . Assembly ,
322
- ( libraryName , assembly , searchPath ) =>
323
- libraryName == "libcoreclr.so" ? - 1 : nint . Zero
324
- ) ;
325
- }
326
-
327
- [ DllImport ( "libcoreclr.so" ) ]
328
- internal static extern nint dlopen ( string filename , int flags ) ;
329
-
330
- [ DllImport ( "libcoreclr.so" ) ]
331
- internal static extern nint dlsym ( nint handle , string symbol ) ;
332
- }
333
95
}
0 commit comments