Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Implement error handling, move using statements
  • Loading branch information
filmor committed Jun 26, 2019
commit 537ee5fae147c78d0221133f4db4de3371ebc319
115 changes: 85 additions & 30 deletions src/runtime/platform/LibraryLoader.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;

namespace Python.Runtime.Platform
Expand All @@ -9,7 +10,7 @@ interface ILibraryLoader

IntPtr GetFunction(IntPtr hModule, string procedureName);

bool Free(IntPtr hModule);
void Free(IntPtr hModule);
}

static class LibraryLoader
Expand All @@ -25,7 +26,7 @@ public static ILibraryLoader Get(OperatingSystemType os)
case OperatingSystemType.Linux:
return new LinuxLoader();
default:
throw new Exception($"This operating system ({os}) is not supported");
throw new PlatformNotSupportedException($"This operating system ({os}) is not supported");
}
}
}
Expand All @@ -37,15 +38,23 @@ class LinuxLoader : ILibraryLoader
private static IntPtr RTLD_DEFAULT = IntPtr.Zero;
private const string NativeDll = "libdl.so";

public IntPtr Load(string fileName)
public IntPtr Load(string dllToLoad)
{
return dlopen($"lib{fileName}.so", RTLD_NOW | RTLD_GLOBAL);
var filename = $"lib{dllToLoad}.so";
ClearError();
var res = dlopen(filename, RTLD_NOW | RTLD_GLOBAL);
if (res == IntPtr.Zero)
{
var err = GetError();
throw new DllNotFoundException($"Could not load {filename} with flags RTLD_NOW | RTLD_GLOBAL: {err}");
}

return res;
}

public bool Free(IntPtr handle)
public void Free(IntPtr handle)
{
dlclose(handle);
return true;
}

public IntPtr GetFunction(IntPtr dllHandle, string name)
Expand All @@ -56,22 +65,35 @@ public IntPtr GetFunction(IntPtr dllHandle, string name)
dllHandle = RTLD_DEFAULT;
}

// clear previous errors if any
dlerror();
ClearError();
IntPtr res = dlsym(dllHandle, name);
IntPtr errPtr = dlerror();
if (errPtr != IntPtr.Zero)
if (res == IntPtr.Zero)
{
throw new Exception("dlsym: " + Marshal.PtrToStringAnsi(errPtr));
var err = GetError();
throw new MissingMethodException($"Failed to load symbol {name}: {err}");
}
return res;
}

void ClearError()
{
dlerror();
}

string GetError()
{
var res = dlerror();
if (res != IntPtr.Zero)
return Marshal.PtrToStringAnsi(res);
else
return null;
}

[DllImport(NativeDll, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
public static extern IntPtr dlopen(String fileName, int flags);
public static extern IntPtr dlopen(string fileName, int flags);

[DllImport(NativeDll, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
private static extern IntPtr dlsym(IntPtr handle, String symbol);
private static extern IntPtr dlsym(IntPtr handle, string symbol);

[DllImport(NativeDll, CallingConvention = CallingConvention.Cdecl)]
private static extern int dlclose(IntPtr handle);
Expand All @@ -87,15 +109,23 @@ class DarwinLoader : ILibraryLoader
private const string NativeDll = "/usr/lib/libSystem.dylib";
private static IntPtr RTLD_DEFAULT = new IntPtr(-2);

public IntPtr Load(string fileName)
public IntPtr Load(string dllToLoad)
{
return dlopen($"lib{fileName}.dylib", RTLD_NOW | RTLD_GLOBAL);
var filename = $"lib{dllToLoad}.dylib";
ClearError();
var res = dlopen(filename, RTLD_NOW | RTLD_GLOBAL);
if (res == IntPtr.Zero)
{
var err = GetError();
throw new DllNotFoundException($"Could not load {filename} with flags RTLD_NOW | RTLD_GLOBAL: {err}");
}

return res;
}

public bool Free(IntPtr handle)
public void Free(IntPtr handle)
{
dlclose(handle);
return true;
}

public IntPtr GetFunction(IntPtr dllHandle, string name)
Expand All @@ -106,17 +136,30 @@ public IntPtr GetFunction(IntPtr dllHandle, string name)
dllHandle = RTLD_DEFAULT;
}

// clear previous errors if any
dlerror();
ClearError();
IntPtr res = dlsym(dllHandle, name);
IntPtr errPtr = dlerror();
if (errPtr != IntPtr.Zero)
if (res == IntPtr.Zero)
{
throw new Exception("dlsym: " + Marshal.PtrToStringAnsi(errPtr));
var err = GetError();
throw new MissingMethodException($"Failed to load symbol {name}: {err}");
}
return res;
}

void ClearError()
{
dlerror();
}

string GetError()
{
var res = dlerror();
if (res != IntPtr.Zero)
return Marshal.PtrToStringAnsi(res);
else
return null;
}

[DllImport(NativeDll, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
public static extern IntPtr dlopen(String fileName, int flags);

Expand All @@ -134,20 +177,32 @@ class WindowsLoader : ILibraryLoader
{
private const string NativeDll = "kernel32.dll";

[DllImport(NativeDll)]
static extern IntPtr LoadLibrary(string dllToLoad);

public IntPtr Load(string dllToLoad) => WindowsLoader.LoadLibrary(dllToLoad);
public IntPtr Load(string dllToLoad)
{
var res = WindowsLoader.LoadLibrary(dllToLoad);
if (res == IntPtr.Zero)
throw new DllNotFoundException($"Could not load {dllToLoad}", new Win32Exception());
return res;
}

public IntPtr GetFunction(IntPtr hModule, string procedureName)
{
var res = WindowsLoader.GetProcAddress(hModule, procedureName);
if (res == IntPtr.Zero)
throw new MissingMethodException($"Failed to load symbol {procedureName}", new Win32Exception());
return res;
}

[DllImport(NativeDll)]
static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);
public void Free(IntPtr hModule) => WindowsLoader.FreeLibrary(hModule);

public IntPtr GetFunction(IntPtr hModule, string procedureName) => WindowsLoader.GetProcAddress(hModule, procedureName);
[DllImport(NativeDll, SetLastError = true)]
static extern IntPtr LoadLibrary(string dllToLoad);

[DllImport(NativeDll, SetLastError = true)]
static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);

[DllImport(NativeDll)]
static extern bool FreeLibrary(IntPtr hModule);

public bool Free(IntPtr hModule) => WindowsLoader.FreeLibrary(hModule);
}
}
2 changes: 1 addition & 1 deletion src/runtime/runtime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
using System.Text;
using System.Threading;
using System.Collections.Generic;
using Python.Runtime.Platform;

namespace Python.Runtime
{
using Python.Runtime.Platform;

/// <summary>
/// Encapsulates the low-level Python C API. Note that it is
Expand Down
2 changes: 1 addition & 1 deletion src/runtime/typemanager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.InteropServices;
using Python.Runtime.Platform;

namespace Python.Runtime
{
using Python.Runtime.Platform;

/// <summary>
/// The TypeManager class is responsible for building binary-compatible
Expand Down