1
1
using System ;
2
+ using System . ComponentModel ;
2
3
using System . Runtime . InteropServices ;
3
4
4
5
namespace Python . Runtime . Platform
@@ -9,7 +10,7 @@ interface ILibraryLoader
9
10
10
11
IntPtr GetFunction ( IntPtr hModule , string procedureName ) ;
11
12
12
- bool Free ( IntPtr hModule ) ;
13
+ void Free ( IntPtr hModule ) ;
13
14
}
14
15
15
16
static class LibraryLoader
@@ -25,7 +26,7 @@ public static ILibraryLoader Get(OperatingSystemType os)
25
26
case OperatingSystemType . Linux :
26
27
return new LinuxLoader ( ) ;
27
28
default :
28
- throw new Exception ( $ "This operating system ({ os } ) is not supported") ;
29
+ throw new PlatformNotSupportedException ( $ "This operating system ({ os } ) is not supported") ;
29
30
}
30
31
}
31
32
}
@@ -37,15 +38,23 @@ class LinuxLoader : ILibraryLoader
37
38
private static IntPtr RTLD_DEFAULT = IntPtr . Zero ;
38
39
private const string NativeDll = "libdl.so" ;
39
40
40
- public IntPtr Load ( string fileName )
41
+ public IntPtr Load ( string dllToLoad )
41
42
{
42
- return dlopen ( $ "lib{ fileName } .so", RTLD_NOW | RTLD_GLOBAL ) ;
43
+ var filename = $ "lib{ dllToLoad } .so";
44
+ ClearError ( ) ;
45
+ var res = dlopen ( filename , RTLD_NOW | RTLD_GLOBAL ) ;
46
+ if ( res == IntPtr . Zero )
47
+ {
48
+ var err = GetError ( ) ;
49
+ throw new DllNotFoundException ( $ "Could not load { filename } with flags RTLD_NOW | RTLD_GLOBAL: { err } ") ;
50
+ }
51
+
52
+ return res ;
43
53
}
44
54
45
- public bool Free ( IntPtr handle )
55
+ public void Free ( IntPtr handle )
46
56
{
47
57
dlclose ( handle ) ;
48
- return true ;
49
58
}
50
59
51
60
public IntPtr GetFunction ( IntPtr dllHandle , string name )
@@ -56,22 +65,35 @@ public IntPtr GetFunction(IntPtr dllHandle, string name)
56
65
dllHandle = RTLD_DEFAULT ;
57
66
}
58
67
59
- // clear previous errors if any
60
- dlerror ( ) ;
68
+ ClearError ( ) ;
61
69
IntPtr res = dlsym ( dllHandle , name ) ;
62
- IntPtr errPtr = dlerror ( ) ;
63
- if ( errPtr != IntPtr . Zero )
70
+ if ( res == IntPtr . Zero )
64
71
{
65
- throw new Exception ( "dlsym: " + Marshal . PtrToStringAnsi ( errPtr ) ) ;
72
+ var err = GetError ( ) ;
73
+ throw new MissingMethodException ( $ "Failed to load symbol { name } : { err } ") ;
66
74
}
67
75
return res ;
68
76
}
69
77
78
+ void ClearError ( )
79
+ {
80
+ dlerror ( ) ;
81
+ }
82
+
83
+ string GetError ( )
84
+ {
85
+ var res = dlerror ( ) ;
86
+ if ( res != IntPtr . Zero )
87
+ return Marshal . PtrToStringAnsi ( res ) ;
88
+ else
89
+ return null ;
90
+ }
91
+
70
92
[ DllImport ( NativeDll , CallingConvention = CallingConvention . Cdecl , CharSet = CharSet . Ansi ) ]
71
- public static extern IntPtr dlopen ( String fileName , int flags ) ;
93
+ public static extern IntPtr dlopen ( string fileName , int flags ) ;
72
94
73
95
[ DllImport ( NativeDll , CallingConvention = CallingConvention . Cdecl , CharSet = CharSet . Ansi ) ]
74
- private static extern IntPtr dlsym ( IntPtr handle , String symbol ) ;
96
+ private static extern IntPtr dlsym ( IntPtr handle , string symbol ) ;
75
97
76
98
[ DllImport ( NativeDll , CallingConvention = CallingConvention . Cdecl ) ]
77
99
private static extern int dlclose ( IntPtr handle ) ;
@@ -87,15 +109,23 @@ class DarwinLoader : ILibraryLoader
87
109
private const string NativeDll = "/usr/lib/libSystem.dylib" ;
88
110
private static IntPtr RTLD_DEFAULT = new IntPtr ( - 2 ) ;
89
111
90
- public IntPtr Load ( string fileName )
112
+ public IntPtr Load ( string dllToLoad )
91
113
{
92
- return dlopen ( $ "lib{ fileName } .dylib", RTLD_NOW | RTLD_GLOBAL ) ;
114
+ var filename = $ "lib{ dllToLoad } .dylib";
115
+ ClearError ( ) ;
116
+ var res = dlopen ( filename , RTLD_NOW | RTLD_GLOBAL ) ;
117
+ if ( res == IntPtr . Zero )
118
+ {
119
+ var err = GetError ( ) ;
120
+ throw new DllNotFoundException ( $ "Could not load { filename } with flags RTLD_NOW | RTLD_GLOBAL: { err } ") ;
121
+ }
122
+
123
+ return res ;
93
124
}
94
125
95
- public bool Free ( IntPtr handle )
126
+ public void Free ( IntPtr handle )
96
127
{
97
128
dlclose ( handle ) ;
98
- return true ;
99
129
}
100
130
101
131
public IntPtr GetFunction ( IntPtr dllHandle , string name )
@@ -106,17 +136,30 @@ public IntPtr GetFunction(IntPtr dllHandle, string name)
106
136
dllHandle = RTLD_DEFAULT ;
107
137
}
108
138
109
- // clear previous errors if any
110
- dlerror ( ) ;
139
+ ClearError ( ) ;
111
140
IntPtr res = dlsym ( dllHandle , name ) ;
112
- IntPtr errPtr = dlerror ( ) ;
113
- if ( errPtr != IntPtr . Zero )
141
+ if ( res == IntPtr . Zero )
114
142
{
115
- throw new Exception ( "dlsym: " + Marshal . PtrToStringAnsi ( errPtr ) ) ;
143
+ var err = GetError ( ) ;
144
+ throw new MissingMethodException ( $ "Failed to load symbol { name } : { err } ") ;
116
145
}
117
146
return res ;
118
147
}
119
148
149
+ void ClearError ( )
150
+ {
151
+ dlerror ( ) ;
152
+ }
153
+
154
+ string GetError ( )
155
+ {
156
+ var res = dlerror ( ) ;
157
+ if ( res != IntPtr . Zero )
158
+ return Marshal . PtrToStringAnsi ( res ) ;
159
+ else
160
+ return null ;
161
+ }
162
+
120
163
[ DllImport ( NativeDll , CallingConvention = CallingConvention . Cdecl , CharSet = CharSet . Ansi ) ]
121
164
public static extern IntPtr dlopen ( String fileName , int flags ) ;
122
165
@@ -134,20 +177,32 @@ class WindowsLoader : ILibraryLoader
134
177
{
135
178
private const string NativeDll = "kernel32.dll" ;
136
179
137
- [ DllImport ( NativeDll ) ]
138
- static extern IntPtr LoadLibrary ( string dllToLoad ) ;
139
180
140
- public IntPtr Load ( string dllToLoad ) => WindowsLoader . LoadLibrary ( dllToLoad ) ;
181
+ public IntPtr Load ( string dllToLoad )
182
+ {
183
+ var res = WindowsLoader . LoadLibrary ( dllToLoad ) ;
184
+ if ( res == IntPtr . Zero )
185
+ throw new DllNotFoundException ( $ "Could not load { dllToLoad } ", new Win32Exception ( ) ) ;
186
+ return res ;
187
+ }
188
+
189
+ public IntPtr GetFunction ( IntPtr hModule , string procedureName )
190
+ {
191
+ var res = WindowsLoader . GetProcAddress ( hModule , procedureName ) ;
192
+ if ( res == IntPtr . Zero )
193
+ throw new MissingMethodException ( $ "Failed to load symbol { procedureName } ", new Win32Exception ( ) ) ;
194
+ return res ;
195
+ }
141
196
142
- [ DllImport ( NativeDll ) ]
143
- static extern IntPtr GetProcAddress ( IntPtr hModule , string procedureName ) ;
197
+ public void Free ( IntPtr hModule ) => WindowsLoader . FreeLibrary ( hModule ) ;
144
198
145
- public IntPtr GetFunction ( IntPtr hModule , string procedureName ) => WindowsLoader . GetProcAddress ( hModule , procedureName ) ;
199
+ [ DllImport ( NativeDll , SetLastError = true ) ]
200
+ static extern IntPtr LoadLibrary ( string dllToLoad ) ;
146
201
202
+ [ DllImport ( NativeDll , SetLastError = true ) ]
203
+ static extern IntPtr GetProcAddress ( IntPtr hModule , string procedureName ) ;
147
204
148
205
[ DllImport ( NativeDll ) ]
149
206
static extern bool FreeLibrary ( IntPtr hModule ) ;
150
-
151
- public bool Free ( IntPtr hModule ) => WindowsLoader . FreeLibrary ( hModule ) ;
152
207
}
153
208
}
0 commit comments