Files
serein-flow/NodeFlow/Tool/NativeDllHelper.cs
fengjiayi 152077e9b5 1. 重新设计了Generate项目及相关特性的命名,避免与其他类型混淆。
2. 补充了部分注释。
3. 修改了删除容器节点时,容器内子节点未正确删除的问题。
2025-07-30 21:15:07 +08:00

189 lines
5.4 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using Serein.Library;
using Serein.Library.Utils;
using System;
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系统");
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;
}
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系统");
}
foreach (var dir in Directory.GetDirectories(path))
{
LoadAllDll(dir, true);
}
}
/// <summary>
/// 加载Windows类库
/// </summary>
/// <param name="file"></param>
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}");
return true;
}
else
{
SereinEnv.WriteLine(InfoType.INFO, $"Failed to load {file}: {Marshal.GetLastWin32Error()}");
return false;
}
}
catch (Exception ex)
{
SereinEnv.WriteLine(InfoType.ERROR, $"Error loading {file}: {ex.Message}");
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}");
return true;
// 可以调用共享库中的函数
// IntPtr procAddress = dlsym(handle, "my_function");
}
else
{
SereinEnv.WriteLine(InfoType.INFO, $"Failed to load {file}: {Marshal.GetLastWin32Error()}");
return false;
}
}
catch (Exception ex)
{
SereinEnv.WriteLine(InfoType.ERROR, $"Error loading {file}: {ex.Message}");
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();
}
}
}