Files
serein-flow/NodeFlow/Tool/NativeDllHelper.cs

189 lines
5.4 KiB
C#
Raw Normal View History

using Serein.Library;
using Serein.Library.Utils;
using System;
2024-11-02 16:48:40 +08:00
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace Serein.NodeFlow.Tool
{
internal class NativeDllHelper
{
// 引入 Windows API 函数
[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr LoadLibrary(string lpFileName);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool FreeLibrary(IntPtr hModule);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
// 引入 Unix/Linux 的动态库加载函数
[DllImport("libdl.so.2", SetLastError = true)]
private static extern IntPtr dlopen(string filename, int flag);
[DllImport("libdl.so.2", SetLastError = true)]
private static extern IntPtr dlsym(IntPtr handle, string symbol);
[DllImport("libdl.so.2", SetLastError = true)]
private static extern int dlclose(IntPtr handle);
private const int RTLD_NOW = 2;
// bool LoadDll(string file)
// void LoadAllDll(string path, bool isRecurrence = true);
private static List<IntPtr> Nints = new List<nint>();
/// <summary>
/// 加载单个Dll
/// </summary>
/// <param name="file"></param>
public static bool LoadDll(string file)
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
return LoadWindowsLibrarie(file);
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
return LoadLinuxLibrarie(file);
}
else
{
SereinEnv.WriteLine(InfoType.ERROR, "非预期的OS系统");
2024-11-02 16:48:40 +08:00
return false;
}
}
public static void LoadAllDll(string path, bool isRecurrence = true)
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
if (!Directory.Exists(path))
{
SereinEnv.WriteLine(InfoType.ERROR, $"尝试加载Dll时失败路径不存在。{path}");
return;
}
2024-11-02 16:48:40 +08:00
foreach (var file in Directory.GetFiles(path, "*.dll"))
{
LoadWindowsLibrarie(file);
}
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
foreach (var file in Directory.GetFiles(path, "*.so"))
{
LoadLinuxLibrarie(file);
}
}
else
{
SereinEnv.WriteLine(InfoType.ERROR, "非预期的OS系统");
2024-11-02 16:48:40 +08:00
}
foreach (var dir in Directory.GetDirectories(path))
{
LoadAllDll(dir, true);
}
}
/// <summary>
/// 加载Windows类库
/// </summary>
/// <param name="file"></param>
2024-11-02 16:48:40 +08:00
private static bool LoadWindowsLibrarie(string file)
{
IntPtr hModule = IntPtr.Zero;
try
{
hModule = LoadLibrary(file);
// 加载 DLL
if (hModule != IntPtr.Zero)
{
Nints.Add(hModule);
SereinEnv.WriteLine(InfoType.INFO, $"Loaded: {file}");
2024-11-02 16:48:40 +08:00
return true;
}
else
{
SereinEnv.WriteLine(InfoType.INFO, $"Failed to load {file}: {Marshal.GetLastWin32Error()}");
2024-11-02 16:48:40 +08:00
return false;
}
}
catch (Exception ex)
{
SereinEnv.WriteLine(InfoType.ERROR, $"Error loading {file}: {ex.Message}");
2024-11-02 16:48:40 +08:00
return false;
}
}
/// <summary>
/// 加载Linux类库
/// </summary>
/// <param name="file"></param>
private static bool LoadLinuxLibrarie(string file)
{
IntPtr handle = IntPtr.Zero;
try
{
handle = dlopen(file, RTLD_NOW);
if (handle != IntPtr.Zero)
{
Nints.Add(handle);
SereinEnv.WriteLine(InfoType.INFO, $"Loaded: {file}");
2024-11-02 16:48:40 +08:00
return true;
// 可以调用共享库中的函数
// IntPtr procAddress = dlsym(handle, "my_function");
}
else
{
SereinEnv.WriteLine(InfoType.INFO, $"Failed to load {file}: {Marshal.GetLastWin32Error()}");
2024-11-02 16:48:40 +08:00
return false;
}
}
catch (Exception ex)
{
SereinEnv.WriteLine(InfoType.ERROR, $"Error loading {file}: {ex.Message}");
2024-11-02 16:48:40 +08:00
return false;
}
}
/// <summary>
/// 卸载所有已加载DLL
/// </summary>
public static void FreeLibrarys()
{
for (int i = 0; i < Nints.Count; i++)
{
IntPtr hModule = Nints[i];
FreeLibrary(hModule);
}
Nints.Clear();
}
}
}