@@ -3,7 +3,31 @@ use proc_macro2::{Span, TokenStream};
3
3
use pyo3:: { ffi, AsPyPointer , PyObject , PyResult , Python } ;
4
4
use std:: str:: FromStr ;
5
5
6
+ #[ cfg( unix) ]
7
+ fn ensure_libpython_symbols_loaded ( py : Python ) -> PyResult < ( ) > {
8
+ // On Unix, Rustc loads proc-macro crates with RTLD_LOCAL, which (at least
9
+ // on Linux) means all their dependencies (in our case: libpython) don't
10
+ // get their symbols made available globally either. This means that
11
+ // loading modules (e.g. `import math`) will fail, as those modules refer
12
+ // back to symbols of libpython.
13
+ //
14
+ // This function tries to (re)load the right version of libpython, but this
15
+ // time with RTLD_GLOBAL enabled.
16
+
17
+ let sysconfig = py. import ( "sysconfig" ) ?;
18
+ let libdir: String = sysconfig. call1 ( "get_config_var" , ( "LIBDIR" , ) ) ?. extract ( ) ?;
19
+ let so_name: String = sysconfig. call1 ( "get_config_var" , ( "INSTSONAME" , ) ) ?. extract ( ) ?;
20
+ let path = std:: ffi:: CString :: new ( format ! ( "{}/{}" , libdir, so_name) ) . unwrap ( ) ;
21
+ unsafe {
22
+ libc:: dlopen ( path. as_ptr ( ) , libc:: RTLD_NOW | libc:: RTLD_GLOBAL ) ;
23
+ }
24
+ Ok ( ( ) )
25
+ }
26
+
6
27
fn run_and_capture ( py : Python , code : PyObject ) -> PyResult < String > {
28
+ #[ cfg( unix) ]
29
+ let _ = ensure_libpython_symbols_loaded ( py) ;
30
+
7
31
let globals = py. import ( "__main__" ) ?. dict ( ) . copy ( ) ?;
8
32
9
33
let sys = py. import ( "sys" ) ?;
0 commit comments