11using System ;
2+ using System . ComponentModel ;
23using System . Runtime . InteropServices ;
34
45namespace Python . Runtime . Platform
@@ -9,7 +10,7 @@ interface ILibraryLoader
910
1011 IntPtr GetFunction ( IntPtr hModule , string procedureName ) ;
1112
12- bool Free ( IntPtr hModule ) ;
13+ void Free ( IntPtr hModule ) ;
1314 }
1415
1516 static class LibraryLoader
@@ -25,7 +26,7 @@ public static ILibraryLoader Get(OperatingSystemType os)
2526 case OperatingSystemType . Linux :
2627 return new LinuxLoader ( ) ;
2728 default :
28- throw new Exception ( $ "This operating system ({ os } ) is not supported") ;
29+ throw new PlatformNotSupportedException ( $ "This operating system ({ os } ) is not supported") ;
2930 }
3031 }
3132 }
@@ -37,15 +38,23 @@ class LinuxLoader : ILibraryLoader
3738 private static IntPtr RTLD_DEFAULT = IntPtr . Zero ;
3839 private const string NativeDll = "libdl.so" ;
3940
40- public IntPtr Load ( string fileName )
41+ public IntPtr Load ( string dllToLoad )
4142 {
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 ;
4353 }
4454
45- public bool Free ( IntPtr handle )
55+ public void Free ( IntPtr handle )
4656 {
4757 dlclose ( handle ) ;
48- return true ;
4958 }
5059
5160 public IntPtr GetFunction ( IntPtr dllHandle , string name )
@@ -56,22 +65,35 @@ public IntPtr GetFunction(IntPtr dllHandle, string name)
5665 dllHandle = RTLD_DEFAULT ;
5766 }
5867
59- // clear previous errors if any
60- dlerror ( ) ;
68+ ClearError ( ) ;
6169 IntPtr res = dlsym ( dllHandle , name ) ;
62- IntPtr errPtr = dlerror ( ) ;
63- if ( errPtr != IntPtr . Zero )
70+ if ( res == IntPtr . Zero )
6471 {
65- throw new Exception ( "dlsym: " + Marshal . PtrToStringAnsi ( errPtr ) ) ;
72+ var err = GetError ( ) ;
73+ throw new MissingMethodException ( $ "Failed to load symbol { name } : { err } ") ;
6674 }
6775 return res ;
6876 }
6977
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+
7092 [ 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 ) ;
7294
7395 [ 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 ) ;
7597
7698 [ DllImport ( NativeDll , CallingConvention = CallingConvention . Cdecl ) ]
7799 private static extern int dlclose ( IntPtr handle ) ;
@@ -87,15 +109,23 @@ class DarwinLoader : ILibraryLoader
87109 private const string NativeDll = "/usr/lib/libSystem.dylib" ;
88110 private static IntPtr RTLD_DEFAULT = new IntPtr ( - 2 ) ;
89111
90- public IntPtr Load ( string fileName )
112+ public IntPtr Load ( string dllToLoad )
91113 {
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 ;
93124 }
94125
95- public bool Free ( IntPtr handle )
126+ public void Free ( IntPtr handle )
96127 {
97128 dlclose ( handle ) ;
98- return true ;
99129 }
100130
101131 public IntPtr GetFunction ( IntPtr dllHandle , string name )
@@ -106,17 +136,30 @@ public IntPtr GetFunction(IntPtr dllHandle, string name)
106136 dllHandle = RTLD_DEFAULT ;
107137 }
108138
109- // clear previous errors if any
110- dlerror ( ) ;
139+ ClearError ( ) ;
111140 IntPtr res = dlsym ( dllHandle , name ) ;
112- IntPtr errPtr = dlerror ( ) ;
113- if ( errPtr != IntPtr . Zero )
141+ if ( res == IntPtr . Zero )
114142 {
115- throw new Exception ( "dlsym: " + Marshal . PtrToStringAnsi ( errPtr ) ) ;
143+ var err = GetError ( ) ;
144+ throw new MissingMethodException ( $ "Failed to load symbol { name } : { err } ") ;
116145 }
117146 return res ;
118147 }
119148
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+
120163 [ DllImport ( NativeDll , CallingConvention = CallingConvention . Cdecl , CharSet = CharSet . Ansi ) ]
121164 public static extern IntPtr dlopen ( String fileName , int flags ) ;
122165
@@ -134,20 +177,32 @@ class WindowsLoader : ILibraryLoader
134177 {
135178 private const string NativeDll = "kernel32.dll" ;
136179
137- [ DllImport ( NativeDll ) ]
138- static extern IntPtr LoadLibrary ( string dllToLoad ) ;
139180
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+ }
141196
142- [ DllImport ( NativeDll ) ]
143- static extern IntPtr GetProcAddress ( IntPtr hModule , string procedureName ) ;
197+ public void Free ( IntPtr hModule ) => WindowsLoader . FreeLibrary ( hModule ) ;
144198
145- public IntPtr GetFunction ( IntPtr hModule , string procedureName ) => WindowsLoader . GetProcAddress ( hModule , procedureName ) ;
199+ [ DllImport ( NativeDll , SetLastError = true ) ]
200+ static extern IntPtr LoadLibrary ( string dllToLoad ) ;
146201
202+ [ DllImport ( NativeDll , SetLastError = true ) ]
203+ static extern IntPtr GetProcAddress ( IntPtr hModule , string procedureName ) ;
147204
148205 [ DllImport ( NativeDll ) ]
149206 static extern bool FreeLibrary ( IntPtr hModule ) ;
150-
151- public bool Free ( IntPtr hModule ) => WindowsLoader . FreeLibrary ( hModule ) ;
152207 }
153208}
0 commit comments