Skip to content

Commit 1196691

Browse files
authored
Use libc iso libdl on newer glibc versions (#1612)
1 parent cc8d9f9 commit 1196691

File tree

1 file changed

+52
-12
lines changed

1 file changed

+52
-12
lines changed

Src/IronPython.Modules/_ctypes/NativeFunctions.cs

Lines changed: 52 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -58,32 +58,72 @@ public static void MemCopy(IntPtr destination, IntPtr source, IntPtr length) {
5858
}
5959

6060
// unix entry points, VM needs to map the filenames.
61-
[DllImport("libdl")]
61+
[DllImport("libc")]
6262
private static extern IntPtr dlopen(string filename, int flags);
6363

64-
[DllImport("libdl")]
64+
[DllImport("libdl", EntryPoint = "dlopen")]
65+
private static extern IntPtr dlopen_dl(string filename, int flags);
66+
67+
[DllImport("libc")]
6568
private static extern IntPtr dlsym(IntPtr handle, string symbol);
6669

70+
[DllImport("libdl", EntryPoint = "dlsym")]
71+
private static extern IntPtr dlsym_dl(IntPtr handle, string symbol);
72+
73+
[DllImport("libc")]
74+
private static extern IntPtr gnu_get_libc_version();
75+
76+
private static bool GetGNULibCVersion(out int major, out int minor) {
77+
major = minor = 0;
78+
try {
79+
string ver = Marshal.PtrToStringAnsi(gnu_get_libc_version());
80+
int dot = ver.IndexOf('.');
81+
if (dot < 0) dot = ver.Length;
82+
if (!int.TryParse(ver.Substring(0, dot), out major)) return false;
83+
if (dot + 1 < ver.Length) {
84+
if (!int.TryParse(ver.Substring(dot + 1), out minor)) return false;
85+
}
86+
} catch {
87+
return false;
88+
}
89+
return true;
90+
}
91+
6792
private const int RTLD_NOW = 2;
6893

94+
private static bool UseLibDL() {
95+
if (!_useLibDL.HasValue) {
96+
bool success = GetGNULibCVersion(out int major, out int minor);
97+
_useLibDL = !success || major < 2 || (major == 2 && minor < 34);
98+
}
99+
return _useLibDL.Value;
100+
}
101+
private static bool? _useLibDL;
102+
69103
public static IntPtr LoadDLL(string filename, int flags) {
70-
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ||
71-
RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) {
72-
if (flags == 0)
73-
flags = RTLD_NOW;
74-
return dlopen(filename, flags);
104+
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) {
105+
return LoadLibrary(filename);
106+
}
107+
108+
if (flags == 0) flags = RTLD_NOW;
109+
110+
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) && UseLibDL()) {
111+
return dlopen_dl(filename, flags);
75112
}
76113

77-
return LoadLibrary(filename);
114+
return dlopen(filename, flags);
78115
}
79116

80117
public static IntPtr LoadFunction(IntPtr module, string functionName) {
81-
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ||
82-
RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) {
83-
return dlsym(module, functionName);
118+
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) {
119+
return GetProcAddress(module, functionName);
120+
}
121+
122+
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) && UseLibDL()) {
123+
return dlsym_dl(module, functionName);
84124
}
85125

86-
return GetProcAddress(module, functionName);
126+
return dlsym(module, functionName);
87127
}
88128

89129
public static IntPtr LoadFunction(IntPtr module, IntPtr ordinal) {

0 commit comments

Comments
 (0)