627 lines
22 KiB
C#
627 lines
22 KiB
C#
using System.Runtime.InteropServices;
|
||
using FortranWebApi.Models;
|
||
using System.Text.Json;
|
||
using System.Runtime.InteropServices.Marshalling;
|
||
using System.IO;
|
||
|
||
namespace FortranWebApi.Services
|
||
{
|
||
public class FortranInteropService
|
||
{
|
||
// 静态构造函数设置DLL导入解析器
|
||
static FortranInteropService()
|
||
{
|
||
// 添加当前目录到库搜索路径
|
||
NativeLibrary.SetDllImportResolver(typeof(FortranInteropService).Assembly, (name, assembly, path) =>
|
||
{
|
||
if (name == "libMAIN_UFRN.so")
|
||
{
|
||
// 尝试从当前目录加载
|
||
string currentDir = Directory.GetCurrentDirectory();
|
||
string libraryPath = Path.Combine(currentDir, "libMAIN_UFRN.so");
|
||
|
||
if (File.Exists(libraryPath))
|
||
{
|
||
return NativeLibrary.Load(libraryPath);
|
||
}
|
||
}
|
||
|
||
// 回退到默认加载行为
|
||
return IntPtr.Zero;
|
||
});
|
||
}
|
||
|
||
// DllImport声明
|
||
[DllImport("libMAIN_UFRN.so", CallingConvention = CallingConvention.Cdecl, EntryPoint = "MAIN_UFRN")]
|
||
private static extern void MAIN_UFRN(
|
||
ref int nriver,
|
||
ref int nsect,
|
||
ref int krc,
|
||
ref int ndata,
|
||
int[] Ns,
|
||
int[] Pc,
|
||
int[] Nrc,
|
||
int[] Lc,
|
||
float[] Dric,
|
||
float[] XJ,
|
||
float[] Asave,
|
||
float[] ds,
|
||
float[] bd,
|
||
float[] zd,
|
||
float[] sm,
|
||
float[] rough,
|
||
ref float ZZ0,
|
||
ref float Zctr,
|
||
float[] Qp,
|
||
int[] UB1,
|
||
int[] UB2,
|
||
int[] DB1,
|
||
int[] DB2,
|
||
float[] UBV,
|
||
int[] NUB,
|
||
float[] DBV,
|
||
float[] Gate,
|
||
int[] NDB,
|
||
float[] Aphi,
|
||
ref float period,
|
||
ref float dt,
|
||
ref float sita,
|
||
ref float sorz,
|
||
ref float sorq,
|
||
ref float epsz,
|
||
ref float epsq,
|
||
ref float Bsor1,
|
||
ref float Bsor2,
|
||
float[] Z,
|
||
float[] Q
|
||
);
|
||
|
||
public string ProcessFortranRequest(string requestText)
|
||
{
|
||
try
|
||
{
|
||
// 解析请求
|
||
var options = new JsonSerializerOptions
|
||
{
|
||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
||
DictionaryKeyPolicy = JsonNamingPolicy.CamelCase,
|
||
PropertyNameCaseInsensitive = true,
|
||
WriteIndented = true
|
||
};
|
||
|
||
var request = JsonSerializer.Deserialize<FortranRequest>(requestText, options);
|
||
if (request == null)
|
||
{
|
||
throw new ArgumentException("无效的请求格式");
|
||
}
|
||
|
||
// 准备输入参数
|
||
var parameters = request.Parameters;
|
||
|
||
// 提取参数
|
||
int nriver = GetIntParameter(parameters, "nriver");
|
||
int nsect = GetIntParameter(parameters, "nsect");
|
||
int krc = GetIntParameter(parameters, "krc");
|
||
int ndata = GetIntParameter(parameters, "ndata");
|
||
int[] Ns = GetIntArrayParameter(parameters, "Ns");
|
||
int[] Pc = GetIntArrayParameter(parameters, "Pc");
|
||
int[] Nrc = GetIntArrayParameter(parameters, "Nrc");
|
||
int[] Lc = GetIntArrayParameter(parameters, "Lc");
|
||
float[] Dric = GetFloatArrayParameter(parameters, "Dric");
|
||
float[] XJ = GetFloatArrayParameter(parameters, "XJ");
|
||
float[] Asave = GetFloatArrayParameter(parameters, "Asave");
|
||
float[] ds = GetFloatArrayParameter(parameters, "ds");
|
||
float[] bd = GetFloatArrayParameter(parameters, "bd");
|
||
float[] zd = GetFloatArrayParameter(parameters, "zd");
|
||
float[] sm = GetFloatArrayParameter(parameters, "sm");
|
||
float[] rough = GetFloatArrayParameter(parameters, "rough");
|
||
float ZZ0 = GetFloatParameter(parameters, "ZZ0");
|
||
float Zctr = GetFloatParameter(parameters, "Zctr");
|
||
float[] Qp = GetFloatArrayParameter(parameters, "Qp");
|
||
int[] UB1 = GetIntArrayParameter(parameters, "UB1");
|
||
int[] UB2 = GetIntArrayParameter(parameters, "UB2");
|
||
int[] DB1 = GetIntArrayParameter(parameters, "DB1");
|
||
int[] DB2 = GetIntArrayParameter(parameters, "DB2");
|
||
float[] UBV = GetFloatArrayParameter(parameters, "UBV");
|
||
int[] NUB = GetIntArrayParameter(parameters, "NUB");
|
||
float[] DBV = GetFloatArrayParameter(parameters, "DBV");
|
||
float[] Gate = GetFloatArrayParameter(parameters, "Gate");
|
||
int[] NDB = GetIntArrayParameter(parameters, "NDB");
|
||
float[] Aphi = GetFloatArrayParameter(parameters, "Aphi");
|
||
float period = GetFloatParameter(parameters, "period");
|
||
float dt = GetFloatParameter(parameters, "dt");
|
||
float sita = GetFloatParameter(parameters, "sita");
|
||
float sorz = GetFloatParameter(parameters, "sorz");
|
||
float sorq = GetFloatParameter(parameters, "sorq");
|
||
float epsz = GetFloatParameter(parameters, "epsz");
|
||
float epsq = GetFloatParameter(parameters, "epsq");
|
||
float Bsor1 = GetFloatParameter(parameters, "Bsor1");
|
||
float Bsor2 = GetFloatParameter(parameters, "Bsor2");
|
||
|
||
|
||
// 准备数组参数
|
||
float[] Z = new float[10000]; // 输出数组,初始大小为10000
|
||
float[] Q = new float[10000]; // 输出数组,初始大小为10000
|
||
|
||
|
||
// 调用Fortran函数
|
||
MAIN_UFRN(
|
||
ref nriver,
|
||
ref nsect,
|
||
ref krc,
|
||
ref ndata,
|
||
Ns,
|
||
Pc,
|
||
Nrc,
|
||
Lc,
|
||
Dric,
|
||
XJ,
|
||
Asave,
|
||
ds,
|
||
bd,
|
||
zd,
|
||
sm,
|
||
rough,
|
||
ref ZZ0,
|
||
ref Zctr,
|
||
Qp,
|
||
UB1,
|
||
UB2,
|
||
DB1,
|
||
DB2,
|
||
UBV,
|
||
NUB,
|
||
DBV,
|
||
Gate,
|
||
NDB,
|
||
Aphi,
|
||
ref period,
|
||
ref dt,
|
||
ref sita,
|
||
ref sorz,
|
||
ref sorq,
|
||
ref epsz,
|
||
ref epsq,
|
||
ref Bsor1,
|
||
ref Bsor2,
|
||
Z,
|
||
Q
|
||
);
|
||
|
||
// 更新输出参数
|
||
UpdateParameter(parameters, "Z", Z);
|
||
UpdateParameter(parameters, "Q", Q);
|
||
|
||
|
||
// 处理输出数组
|
||
// 处理输出数组 Z
|
||
// 注意:没有找到明确的长度参数,使用非零元素数量
|
||
{
|
||
int nonZeroCount = 0;
|
||
for (int i = 0; i < Z.Length; i++)
|
||
{
|
||
if (Z[i] != 0) nonZeroCount = i + 1;
|
||
}
|
||
if (nonZeroCount > 0)
|
||
{
|
||
float[] resultArray = new float[nonZeroCount];
|
||
Array.Copy(Z, resultArray, nonZeroCount);
|
||
UpdateArrayParameter(parameters, "Z", resultArray);
|
||
}
|
||
}
|
||
// 处理输出数组 Q
|
||
// 注意:没有找到明确的长度参数,使用非零元素数量
|
||
{
|
||
int nonZeroCount = 0;
|
||
for (int i = 0; i < Q.Length; i++)
|
||
{
|
||
if (Q[i] != 0) nonZeroCount = i + 1;
|
||
}
|
||
if (nonZeroCount > 0)
|
||
{
|
||
float[] resultArray = new float[nonZeroCount];
|
||
Array.Copy(Q, resultArray, nonZeroCount);
|
||
UpdateArrayParameter(parameters, "Q", resultArray);
|
||
}
|
||
}
|
||
|
||
|
||
// 返回结果 - 只返回原始请求的结构,但包含更新后的参数
|
||
var result = new FortranRequest
|
||
{
|
||
FuncName = request.FuncName,
|
||
ClassName = request.ClassName,
|
||
Parameters = parameters
|
||
};
|
||
|
||
return JsonSerializer.Serialize(result, options);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
return JsonSerializer.Serialize(new { error = ex.Message });
|
||
}
|
||
}
|
||
|
||
private float GetFloatParameter(List<FortranParameter> parameters, string name)
|
||
{
|
||
var param = parameters.FirstOrDefault(p => p.Name == name);
|
||
if (param == null || param.Data == null)
|
||
{
|
||
return 0.0f;
|
||
}
|
||
|
||
if (param.Data is JsonElement element)
|
||
{
|
||
if (element.ValueKind == JsonValueKind.Number)
|
||
{
|
||
return element.GetSingle();
|
||
}
|
||
}
|
||
|
||
return Convert.ToSingle(param.Data);
|
||
}
|
||
private double GetDoubleParameter(List<FortranParameter> parameters, string name)
|
||
{
|
||
var param = parameters.FirstOrDefault(p => p.Name == name);
|
||
if (param == null || param.Data == null)
|
||
{
|
||
return 0.0;
|
||
}
|
||
|
||
if (param.Data is JsonElement element)
|
||
{
|
||
if (element.ValueKind == JsonValueKind.Number)
|
||
{
|
||
return element.GetSingle();
|
||
}
|
||
}
|
||
|
||
return Convert.ToDouble(param.Data);
|
||
}
|
||
private int GetIntParameter(List<FortranParameter> parameters, string name)
|
||
{
|
||
var param = parameters.FirstOrDefault(p => p.Name == name);
|
||
if (param == null || param.Data == null)
|
||
{
|
||
return 0;
|
||
}
|
||
|
||
if (param.Data is JsonElement element)
|
||
{
|
||
if (element.ValueKind == JsonValueKind.Number)
|
||
{
|
||
return element.GetInt32();
|
||
}
|
||
}
|
||
|
||
return Convert.ToInt32(param.Data);
|
||
}
|
||
private int[] GetIntArrayParameter(List<FortranParameter> parameters, string name)
|
||
{
|
||
var param = parameters.FirstOrDefault(p => p.Name == name);
|
||
if (param == null || param.Data == null)
|
||
{
|
||
return Array.Empty<int>();
|
||
}
|
||
|
||
if (param.Data is JsonElement element && element.ValueKind == JsonValueKind.Array)
|
||
{
|
||
var array = new List<int>();
|
||
foreach (var item in element.EnumerateArray())
|
||
{
|
||
if (item.ValueKind == JsonValueKind.Number)
|
||
{
|
||
array.Add(item.GetInt32());
|
||
}
|
||
}
|
||
return array.ToArray();
|
||
}
|
||
|
||
if (param.Data is System.Collections.IEnumerable enumerable && !(param.Data is string))
|
||
{
|
||
var array = new List<int>();
|
||
foreach (var item in enumerable)
|
||
{
|
||
array.Add(Convert.ToInt32(item));
|
||
}
|
||
return array.ToArray();
|
||
}
|
||
|
||
return Array.Empty<int>();
|
||
}
|
||
private float[] GetFloatArrayParameter(List<FortranParameter> parameters, string name)
|
||
{
|
||
var param = parameters.FirstOrDefault(p => p.Name == name);
|
||
if (param == null || param.Data == null)
|
||
{
|
||
return Array.Empty<float>();
|
||
}
|
||
|
||
if (param.Data is JsonElement element && element.ValueKind == JsonValueKind.Array)
|
||
{
|
||
var array = new List<float>();
|
||
foreach (var item in element.EnumerateArray())
|
||
{
|
||
if (item.ValueKind == JsonValueKind.Number)
|
||
{
|
||
array.Add(item.GetSingle());
|
||
}
|
||
}
|
||
return array.ToArray();
|
||
}
|
||
|
||
if (param.Data is System.Collections.IEnumerable enumerable && !(param.Data is string))
|
||
{
|
||
var array = new List<float>();
|
||
foreach (var item in enumerable)
|
||
{
|
||
array.Add(Convert.ToSingle(item));
|
||
}
|
||
return array.ToArray();
|
||
}
|
||
|
||
return Array.Empty<float>();
|
||
}
|
||
private double[] GetDoubleArrayParameter(List<FortranParameter> parameters, string name)
|
||
{
|
||
var param = parameters.FirstOrDefault(p => p.Name == name);
|
||
if (param == null || param.Data == null)
|
||
{
|
||
return Array.Empty<double>();
|
||
}
|
||
|
||
if (param.Data is JsonElement element && element.ValueKind == JsonValueKind.Array)
|
||
{
|
||
var array = new List<double>();
|
||
foreach (var item in element.EnumerateArray())
|
||
{
|
||
if (item.ValueKind == JsonValueKind.Number)
|
||
{
|
||
array.Add(item.GetSingle());
|
||
}
|
||
}
|
||
return array.ToArray();
|
||
}
|
||
|
||
if (param.Data is System.Collections.IEnumerable enumerable && !(param.Data is string))
|
||
{
|
||
var array = new List<double>();
|
||
foreach (var item in enumerable)
|
||
{
|
||
array.Add(Convert.ToSingle(item));
|
||
}
|
||
return array.ToArray();
|
||
}
|
||
|
||
return Array.Empty<double>();
|
||
}
|
||
private void UpdateParameter(List<FortranParameter> parameters, string name, object value)
|
||
{
|
||
var param = parameters.FirstOrDefault(p => p.Name == name);
|
||
if (param != null)
|
||
{
|
||
param.Data = value;
|
||
}
|
||
}
|
||
|
||
private void UpdateArrayParameter(List<FortranParameter> parameters, string name, float[] value)
|
||
{
|
||
var param = parameters.FirstOrDefault(p => p.Name == name);
|
||
if (param != null)
|
||
{
|
||
param.Data = value;
|
||
}
|
||
}
|
||
private void UpdateDoubleArrayParameter(List<FortranParameter> parameters, string name, double[] value)
|
||
{
|
||
var param = parameters.FirstOrDefault(p => p.Name == name);
|
||
if (param != null)
|
||
{
|
||
param.Data = value;
|
||
}
|
||
}
|
||
private void UpdateIntArrayParameter(List<FortranParameter> parameters, string name, int[] value)
|
||
{
|
||
var param = parameters.FirstOrDefault(p => p.Name == name);
|
||
if (param != null)
|
||
{
|
||
param.Data = value;
|
||
}
|
||
}
|
||
// 添加新的辅助方法来处理二维数组
|
||
private double[,] GetDouble2DArrayParameter(List<FortranParameter> parameters, string name, int rows, int cols)
|
||
{
|
||
var param = parameters.FirstOrDefault(p => p.Name == name);
|
||
if (param == null || param.Data == null)
|
||
{
|
||
return new double[rows, cols];
|
||
}
|
||
|
||
double[,] result = new double[rows, cols];
|
||
|
||
if (param.Data is JsonElement element && element.ValueKind == JsonValueKind.Array)
|
||
{
|
||
int index = 0;
|
||
foreach (var item in element.EnumerateArray())
|
||
{
|
||
if (item.ValueKind == JsonValueKind.Number)
|
||
{
|
||
int row = index / cols;
|
||
int col = index % cols;
|
||
if (row < rows && col < cols)
|
||
{
|
||
result[row, col] = item.GetDouble();
|
||
}
|
||
index++;
|
||
}
|
||
}
|
||
}
|
||
else if (param.Data is System.Collections.IEnumerable enumerable && !(param.Data is string))
|
||
{
|
||
int index = 0;
|
||
foreach (var item in enumerable)
|
||
{
|
||
int row = index / cols;
|
||
int col = index % cols;
|
||
if (row < rows && col < cols)
|
||
{
|
||
result[row, col] = Convert.ToDouble(item);
|
||
}
|
||
index++;
|
||
}
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
// 添加更新二维数组参数的方法
|
||
private void UpdateDouble2DArrayParameter(List<FortranParameter> parameters, string name, double[,] value)
|
||
{
|
||
var param = parameters.FirstOrDefault(p => p.Name == name);
|
||
if (param != null)
|
||
{
|
||
// 将二维数组转换为一维数组以便于JSON序列化
|
||
int rows = value.GetLength(0);
|
||
int cols = value.GetLength(1);
|
||
double[] flatArray = new double[rows * cols];
|
||
for (int i = 0; i < rows; i++)
|
||
{
|
||
for (int j = 0; j < cols; j++)
|
||
{
|
||
flatArray[i * cols + j] = value[i, j];
|
||
}
|
||
}
|
||
param.Data = flatArray;
|
||
}
|
||
}
|
||
// float版本
|
||
private float[,] GetFloat2DArrayParameter(List<FortranParameter> parameters, string name, int rows, int cols)
|
||
{
|
||
var param = parameters.FirstOrDefault(p => p.Name == name);
|
||
if (param == null || param.Data == null)
|
||
{
|
||
return new float[rows, cols];
|
||
}
|
||
|
||
float[,] result = new float[rows, cols];
|
||
|
||
if (param.Data is JsonElement element && element.ValueKind == JsonValueKind.Array)
|
||
{
|
||
int index = 0;
|
||
foreach (var item in element.EnumerateArray())
|
||
{
|
||
if (item.ValueKind == JsonValueKind.Number)
|
||
{
|
||
int row = index / cols;
|
||
int col = index % cols;
|
||
if (row < rows && col < cols)
|
||
{
|
||
result[row, col] = item.GetSingle();
|
||
}
|
||
index++;
|
||
}
|
||
}
|
||
}
|
||
else if (param.Data is System.Collections.IEnumerable enumerable && !(param.Data is string))
|
||
{
|
||
int index = 0;
|
||
foreach (var item in enumerable)
|
||
{
|
||
int row = index / cols;
|
||
int col = index % cols;
|
||
if (row < rows && col < cols)
|
||
{
|
||
result[row, col] = Convert.ToSingle(item);
|
||
}
|
||
index++;
|
||
}
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
private void UpdateFloat2DArrayParameter(List<FortranParameter> parameters, string name, float[,] value)
|
||
{
|
||
var param = parameters.FirstOrDefault(p => p.Name == name);
|
||
if (param != null)
|
||
{
|
||
int rows = value.GetLength(0);
|
||
int cols = value.GetLength(1);
|
||
float[] flatArray = new float[rows * cols];
|
||
for (int i = 0; i < rows; i++)
|
||
{
|
||
for (int j = 0; j < cols; j++)
|
||
{
|
||
flatArray[i * cols + j] = value[i, j];
|
||
}
|
||
}
|
||
param.Data = flatArray;
|
||
}
|
||
}
|
||
|
||
// int版本
|
||
private int[,] GetInt2DArrayParameter(List<FortranParameter> parameters, string name, int rows, int cols)
|
||
{
|
||
var param = parameters.FirstOrDefault(p => p.Name == name);
|
||
if (param == null || param.Data == null)
|
||
{
|
||
return new int[rows, cols];
|
||
}
|
||
|
||
int[,] result = new int[rows, cols];
|
||
|
||
if (param.Data is JsonElement element && element.ValueKind == JsonValueKind.Array)
|
||
{
|
||
int index = 0;
|
||
foreach (var item in element.EnumerateArray())
|
||
{
|
||
if (item.ValueKind == JsonValueKind.Number)
|
||
{
|
||
int row = index / cols;
|
||
int col = index % cols;
|
||
if (row < rows && col < cols)
|
||
{
|
||
result[row, col] = item.GetInt32();
|
||
}
|
||
index++;
|
||
}
|
||
}
|
||
}
|
||
else if (param.Data is System.Collections.IEnumerable enumerable && !(param.Data is string))
|
||
{
|
||
int index = 0;
|
||
foreach (var item in enumerable)
|
||
{
|
||
int row = index / cols;
|
||
int col = index % cols;
|
||
if (row < rows && col < cols)
|
||
{
|
||
result[row, col] = Convert.ToInt32(item);
|
||
}
|
||
index++;
|
||
}
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
private void UpdateInt2DArrayParameter(List<FortranParameter> parameters, string name, int[,] value)
|
||
{
|
||
var param = parameters.FirstOrDefault(p => p.Name == name);
|
||
if (param != null)
|
||
{
|
||
int rows = value.GetLength(0);
|
||
int cols = value.GetLength(1);
|
||
int[] flatArray = new int[rows * cols];
|
||
for (int i = 0; i < rows; i++)
|
||
{
|
||
for (int j = 0; j < cols; j++)
|
||
{
|
||
flatArray[i * cols + j] = value[i, j];
|
||
}
|
||
}
|
||
param.Data = flatArray;
|
||
}
|
||
}
|
||
}
|
||
} |