From 87e38f0f731bf5bf4ab1ce63ecdc8f2996d0e5e0 Mon Sep 17 00:00:00 2001 From: tp <1799149022@qq.com> Date: Tue, 3 Jun 2025 16:20:31 +0800 Subject: [PATCH] 1 --- Controllers/FortranController.cs | 74 +++++ Dockerfile | 88 +++++ Fortran/1.json | 97 ++++++ Fortran/1.xlsx | Bin 0 -> 12233 bytes Fortran/MASIJINGGEN.f90 | 50 +++ FortranWebApi.csproj | 27 ++ HttpRequests/fortranwebapi.http | 20 ++ Models/ApiResponse.cs | 31 ++ Models/FortranParameter.cs | 22 ++ Models/FortranRequest.cs | 13 + Models/FortranRequestWrapper.cs | 7 + Program.cs | 80 +++++ Properties/launchSettings.json | 14 + Services/FortranInteropService.cs | 527 ++++++++++++++++++++++++++++++ appsettings.json | 16 + 15 files changed, 1066 insertions(+) create mode 100644 Controllers/FortranController.cs create mode 100644 Dockerfile create mode 100644 Fortran/1.json create mode 100644 Fortran/1.xlsx create mode 100644 Fortran/MASIJINGGEN.f90 create mode 100644 FortranWebApi.csproj create mode 100644 HttpRequests/fortranwebapi.http create mode 100644 Models/ApiResponse.cs create mode 100644 Models/FortranParameter.cs create mode 100644 Models/FortranRequest.cs create mode 100644 Models/FortranRequestWrapper.cs create mode 100644 Program.cs create mode 100644 Properties/launchSettings.json create mode 100644 Services/FortranInteropService.cs create mode 100644 appsettings.json diff --git a/Controllers/FortranController.cs b/Controllers/FortranController.cs new file mode 100644 index 0000000..46a63e2 --- /dev/null +++ b/Controllers/FortranController.cs @@ -0,0 +1,74 @@ +using Microsoft.AspNetCore.Mvc; +using FortranWebApi.Models; +using FortranWebApi.Services; +using System.Text.Json; + +namespace FortranWebApi.Controllers +{ + [ApiController] + [Route("[controller]")] + public class FortranCalculateController : ControllerBase + { + private readonly FortranInteropService _fortranService; + private readonly ILogger<FortranCalculateController> _logger; + + public FortranCalculateController(FortranInteropService fortranService, ILogger<FortranCalculateController> logger) + { + _fortranService = fortranService; + _logger = logger; + } + + [HttpPost] + public IActionResult Post([FromBody] FortranRequestWrapper wrapper) + { + try + { + if (string.IsNullOrEmpty(wrapper.Text)) + { + return BadRequest(new + { + message = "请求文本不能为空", + success = false, + data = (object)null + }); + } + + string result = _fortranService.ProcessFortranRequest(wrapper.Text); + + // 使用驼峰命名法解析结果 + var options = new JsonSerializerOptions + { + PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + DictionaryKeyPolicy = JsonNamingPolicy.CamelCase, + PropertyNameCaseInsensitive = true, + WriteIndented = true + }; + + var resultObj = JsonSerializer.Deserialize<FortranRequest>(result, options); + + // 返回新的格式 + var response = new ApiResponse<FortranRequest> + { + Message = "Success", + Success = true, + Data = new ApiResponseData<FortranRequest> + { + Value = resultObj + } + }; + + return Ok(response); + } + catch (Exception ex) + { + _logger.LogError(ex, "处理Fortran请求时发生错误"); + return StatusCode(500, new + { + message = ex.Message, + success = false, + data = (object)null + }); + } + } + } +} \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..a35f0ef --- /dev/null +++ b/Dockerfile @@ -0,0 +1,88 @@ +# ===== 第一阶段:构建阶段 ===== +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build + +# 配置 NuGet 使用国内镜像源 +RUN dotnet nuget add source https://mirrors.cloud.tencent.com/nuget/ \ + && dotnet nuget disable source nuget.org + +# 配置 apt-get 使用 apt-cacher-ng 作为代理 +RUN echo 'Acquire::http::Proxy "http://192.168.1.140:3142";' > /etc/apt/apt.conf.d/01proxy + +# 创建并配置 Debian 镜像源 +RUN echo "deb https://mirrors.ustc.edu.cn/debian/ bookworm main contrib non-free non-free-firmware" > /etc/apt/sources.list && \ + echo "deb https://mirrors.ustc.edu.cn/debian/ bookworm-updates main contrib non-free non-free-firmware" >> /etc/apt/sources.list && \ + echo "deb https://mirrors.ustc.edu.cn/debian-security bookworm-security main contrib non-free non-free-firmware" >> /etc/apt/sources.list + +# 允许使用不安全的软件源 +RUN echo 'Acquire::AllowInsecureRepositories "true";' > /etc/apt/apt.conf.d/99allow-insecure && \ + echo 'Acquire::AllowDowngradeToInsecureRepositories "true";' >> /etc/apt/apt.conf.d/99allow-insecure + +WORKDIR /src + +# 安装 Fortran 编译器 +RUN apt-get update && apt-get install -y --no-install-recommends \ + gfortran \ + && rm -rf /var/lib/apt/lists/* + +# 复制 Fortran 源文件并编译 +COPY Fortran/*.f90 /src/Fortran/ +WORKDIR /src/Fortran + +# 编译所有 .f90 文件为 .o 文件 +RUN for file in *.f90; do gfortran -fPIC -c "$file" -o "${file%.f90}.o"; done + +# 链接所有 .o 文件为共享库 +RUN gfortran -shared *.o -o libMASIJINGGEN.so + +# 回到主工作目录 +WORKDIR /src + +# 只复制项目文件 +COPY ["FortranWebApi.csproj", "./"] +RUN dotnet restore + +# 复制源代码 +COPY . . + +# 合并 build 和 publish 命令 +RUN dotnet publish -c Release -o /app/publish + +# 复制编译好的 .so 文件到发布目录 +RUN mkdir -p /app/publish && \ + cp /src/Fortran/libMASIJINGGEN.so /app/publish/ + +# ===== 第二阶段:运行阶段 ===== +FROM mcr.microsoft.com/dotnet/aspnet:8.0 + +# 配置 apt-get 使用 apt-cacher-ng 作为代理 +RUN echo 'Acquire::http::Proxy "http://192.168.1.140:3142";' > /etc/apt/apt.conf.d/01proxy + +# 创建并配置 Debian 镜像源 +RUN echo "deb https://mirrors.ustc.edu.cn/debian/ bookworm main contrib non-free non-free-firmware" > /etc/apt/sources.list && \ + echo "deb https://mirrors.ustc.edu.cn/debian/ bookworm-updates main contrib non-free non-free-firmware" >> /etc/apt/sources.list && \ + echo "deb https://mirrors.ustc.edu.cn/debian-security bookworm-security main contrib non-free non-free-firmware" >> /etc/apt/sources.list + +# 允许使用不安全的软件源 +RUN echo 'Acquire::AllowInsecureRepositories "true";' > /etc/apt/apt.conf.d/99allow-insecure && \ + echo 'Acquire::AllowDowngradeToInsecureRepositories "true";' >> /etc/apt/apt.conf.d/99allow-insecure + +# 安装运行时依赖 +RUN apt-get update && apt-get install -y --no-install-recommends \ + libc6-dev \ + libgfortran5 \ + && rm -rf /var/lib/apt/lists/* + +WORKDIR /app +COPY --from=build /app/publish . + +# 确保 .so 文件的权限正确 +RUN chmod 755 /app/libMASIJINGGEN.so + +# 设置 LD_LIBRARY_PATH +ENV LD_LIBRARY_PATH=/app + +# 设置端口和监听地址 +ENV ASPNETCORE_URLS=http://+:5000 +EXPOSE 5000 + +ENTRYPOINT ["dotnet", "FortranWebApi.dll"] \ No newline at end of file diff --git a/Fortran/1.json b/Fortran/1.json new file mode 100644 index 0000000..207f24b --- /dev/null +++ b/Fortran/1.json @@ -0,0 +1,97 @@ +{ + "fortranSourceFile": "D:\\\u5DE5\u4F5C2025\\\u7B97\u6CD5\u5E73\u53F0\\dll\\\u9A6C\u65AF\u4EAC\u6839\u6A21\u578B\\MASIJINGGEN\\MASIJINGGEN\\MASIJINGGEN - \u526F\u672C.f90", + "fortranFunctionName": "MASIJINGGEN", + "projectName": "FortranWebApi", + "outputDirectory": "D:\\\u5DE5\u4F5C2025\\\u7B97\u6CD5\u5E73\u53F0\\\u8F93\u51FA\u5E93\\\u9A6C\u65AF\u4EAC\u6839\u6A21\u578B", + "cmbLanguage": "Fortran", + "parameters": [ + { + "name": "NFILENAME", + "dataType": "Integer", + "arrayType": "Scalar", + "direction": "Input", + "description": "", + "isSelected": true + }, + { + "name": "N", + "dataType": "Integer", + "arrayType": "Scalar", + "direction": "Input", + "description": "", + "isSelected": true + }, + { + "name": "Q1", + "dataType": "Float", + "arrayType": "OneDimensional", + "direction": "Input", + "description": "", + "isSelected": true + }, + { + "name": "Q20", + "dataType": "Float", + "arrayType": "Scalar", + "direction": "Input", + "description": "", + "isSelected": true + }, + { + "name": "X", + "dataType": "Float", + "arrayType": "Scalar", + "direction": "Input", + "description": "", + "isSelected": true + }, + { + "name": "K", + "dataType": "Float", + "arrayType": "Scalar", + "direction": "Input", + "description": "", + "isSelected": true + }, + { + "name": "DETAT", + "dataType": "Float", + "arrayType": "Scalar", + "direction": "Input", + "description": "", + "isSelected": true + }, + { + "name": "C0", + "dataType": "Float", + "arrayType": "Scalar", + "direction": "Output", + "description": "", + "isSelected": true + }, + { + "name": "C1", + "dataType": "Float", + "arrayType": "Scalar", + "direction": "Output", + "description": "", + "isSelected": true + }, + { + "name": "C2", + "dataType": "Float", + "arrayType": "Scalar", + "direction": "Output", + "description": "", + "isSelected": true + }, + { + "name": "Q2", + "dataType": "Float", + "arrayType": "OneDimensional", + "direction": "Output", + "description": "", + "isSelected": true + } + ] +} \ No newline at end of file diff --git a/Fortran/1.xlsx b/Fortran/1.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..bdf9fb4828cc9fd8a6116d6df6be3d80fb935a18 GIT binary patch literal 12233 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 WCMOB`^OHvdK?9KndNZMU(ffb6On}`0 literal 0 HcmV?d00001 diff --git a/Fortran/MASIJINGGEN.f90 b/Fortran/MASIJINGGEN.f90 new file mode 100644 index 0000000..9265bbd --- /dev/null +++ b/Fortran/MASIJINGGEN.f90 @@ -0,0 +1,50 @@ +subroutine MASIJINGGEN( NFILENAME ,& ! �ļ����ֳ��� ���� //������� + N ,& ! �����������ݵ���� ���� //������� + Q1 ,& ! �������� ������ //������� + Q20 ,& ! ����������ʼֵ ������ //���� + X ,& ! ������������ ������ //������� + K ,& ! ����ģ�� ������ //������� + DETAT ,& ! ʱ�䲽�� ��Сʱ�� ������ //������� + C0 ,& ! ϵ�� ������ //������� + C1 ,& ! ������ //������� + C2 ,& ! ������ //������� + Q2 )& ! �������� ������ //��� + BIND(C, NAME="MASIJINGGEN") + + !DEC$ ATTRIBUTES DLLEXPORT::MASIJINGGEN + INTEGER::NFILENAME + CHARACTER(LEN = NFILENAME)::FILENAME + + INTEGER::N + REAL::Q1(1000) + REAL::Q20 + REAL::Q2(1000) + REAL::I1 + REAL::I2 + REAL::C0 + REAL::C1 + REAL::C2 + + REAL::X + REAL::K + REAL::DETAT + + INTEGER::I + + C0 = (0.5*DETAT - K*X)/(0.5*DETAT + K - K*X) + C1 = (0.5*DETAT + K*X)/(0.5*DETAT + K - K*X) + C2 = (-0.5*DETAT +K - K*X)/(0.5*DETAT + K - K*X) + + Q2(1) =Q20 + + DO I = 2,N + + I2 = Q1(I) + + I1 = Q1(I-1) + + Q2(I) = C0*I2 + C1*I1 + C2*Q2(I-1) + + END DO + +end subroutine MASIJINGGEN diff --git a/FortranWebApi.csproj b/FortranWebApi.csproj new file mode 100644 index 0000000..6a4d551 --- /dev/null +++ b/FortranWebApi.csproj @@ -0,0 +1,27 @@ +<Project Sdk="Microsoft.NET.Sdk.Web"> + + <PropertyGroup> + <TargetFramework>net8.0</TargetFramework> + <Nullable>enable</Nullable> + <ImplicitUsings>enable</ImplicitUsings> + <InvariantGlobalization>true</InvariantGlobalization> + </PropertyGroup> + + <ItemGroup> + <PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.0" /> + <PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" /> + <PackageReference Include="Serilog" Version="4.2.0" /> + <PackageReference Include="Serilog.AspNetCore" Version="8.0.1" /> + <PackageReference Include="Serilog.Extensions.Logging" Version="8.0.0" /> + <PackageReference Include="Serilog.Sinks.Console" Version="5.0.1" /> + <PackageReference Include="Serilog.Sinks.File" Version="5.0.0" /> + <PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0" /> + </ItemGroup> + + <ItemGroup> + <None Update="lib{{FortranFunctionName}}.so"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </None> + </ItemGroup> + +</Project> \ No newline at end of file diff --git a/HttpRequests/fortranwebapi.http b/HttpRequests/fortranwebapi.http new file mode 100644 index 0000000..83ee6c0 --- /dev/null +++ b/HttpRequests/fortranwebapi.http @@ -0,0 +1,20 @@ +@FortranWebApi_HostAddress = http://localhost:5000 + +### 测试Fortran请求 + +POST {{FortranWebApi_HostAddress}}/FortranCalculate +Content-Type: application/json + +{ + "text": "{\"FuncName\":\"calculate_main\",\"ClassName\":\"\",\"Par\":[ {"Name":"NFILENAME","DataType":"0","ArrayType":"0","IsOut":"2","Data":0}, + {"Name":"N","DataType":"0","ArrayType":"0","IsOut":"2","Data":0}, + {"Name":"Q1","DataType":"1","ArrayType":"1","IsOut":"2","Data":[]}, + {"Name":"Q20","DataType":"1","ArrayType":"0","IsOut":"2","Data":0}, + {"Name":"X","DataType":"1","ArrayType":"0","IsOut":"2","Data":0}, + {"Name":"K","DataType":"1","ArrayType":"0","IsOut":"2","Data":0}, + {"Name":"DETAT","DataType":"1","ArrayType":"0","IsOut":"2","Data":0}, + {"Name":"C0","DataType":"1","ArrayType":"0","IsOut":"1","Data":0}, + {"Name":"C1","DataType":"1","ArrayType":"0","IsOut":"1","Data":0}, + {"Name":"C2","DataType":"1","ArrayType":"0","IsOut":"1","Data":0}, + {"Name":"Q2","DataType":"1","ArrayType":"1","IsOut":"1","Data":[]}]}" +} \ No newline at end of file diff --git a/Models/ApiResponse.cs b/Models/ApiResponse.cs new file mode 100644 index 0000000..3845aa5 --- /dev/null +++ b/Models/ApiResponse.cs @@ -0,0 +1,31 @@ +using System.Text.Json.Serialization; + +namespace FortranWebApi.Models +{ + public class ApiResponse<T> + { + [JsonPropertyName("message")] + public string Message { get; set; } = "Success"; + + [JsonPropertyName("success")] + public bool Success { get; set; } = true; + + [JsonPropertyName("data")] + public ApiResponseData<T>? Data { get; set; } + } + + public class ApiResponseData<T> + { + [JsonPropertyName("contentType")] + public string? ContentType { get; set; } + + [JsonPropertyName("serializerSettings")] + public object? SerializerSettings { get; set; } + + [JsonPropertyName("statusCode")] + public int? StatusCode { get; set; } + + [JsonPropertyName("value")] + public T? Value { get; set; } + } +} \ No newline at end of file diff --git a/Models/FortranParameter.cs b/Models/FortranParameter.cs new file mode 100644 index 0000000..78d68f0 --- /dev/null +++ b/Models/FortranParameter.cs @@ -0,0 +1,22 @@ +using System.Text.Json.Serialization; + +namespace FortranWebApi.Models +{ + public class FortranParameter + { + [JsonPropertyName("name")] + public string Name { get; set; } = string.Empty; + + [JsonPropertyName("dataType")] + public string DataType { get; set; } = "0"; + + [JsonPropertyName("arrayType")] + public string ArrayType { get; set; } = "0"; + + [JsonPropertyName("isOut")] + public string IsOut { get; set; } = "2"; + + [JsonPropertyName("data")] + public object? Data { get; set; } + } +} \ No newline at end of file diff --git a/Models/FortranRequest.cs b/Models/FortranRequest.cs new file mode 100644 index 0000000..e17fc88 --- /dev/null +++ b/Models/FortranRequest.cs @@ -0,0 +1,13 @@ +using System.Text.Json.Serialization; + +namespace FortranWebApi.Models +{ + public class FortranRequest + { + public string FuncName { get; set; } = string.Empty; + public string ClassName { get; set; } = string.Empty; + + [JsonPropertyName("par")] + public List<FortranParameter> Parameters { get; set; } = new List<FortranParameter>(); + } +} \ No newline at end of file diff --git a/Models/FortranRequestWrapper.cs b/Models/FortranRequestWrapper.cs new file mode 100644 index 0000000..49c36c2 --- /dev/null +++ b/Models/FortranRequestWrapper.cs @@ -0,0 +1,7 @@ +namespace FortranWebApi.Models +{ + public class FortranRequestWrapper + { + public string Text { get; set; } = string.Empty; + } +} \ No newline at end of file diff --git a/Program.cs b/Program.cs new file mode 100644 index 0000000..ac334f1 --- /dev/null +++ b/Program.cs @@ -0,0 +1,80 @@ +using Serilog; +using FortranWebApi.Services; +using System.IO; +using System.Text.Json; +using System.Text.Json.Serialization; + +// 设置库搜索路径 +string currentDir = Directory.GetCurrentDirectory(); +Environment.SetEnvironmentVariable("LD_LIBRARY_PATH", + $"{Environment.GetEnvironmentVariable("LD_LIBRARY_PATH")}:{currentDir}"); + +var builder = WebApplication.CreateBuilder(args); + +// 添加健康检查服务 +builder.Services.AddHealthChecks(); + +// 配置Serilog +Log.Logger = new LoggerConfiguration() + .WriteTo.Console(outputTemplate: + "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}") + .WriteTo.File("logs/log-.txt", + rollingInterval: RollingInterval.Day, + outputTemplate: + "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}") + .CreateLogger(); + +builder.Host.UseSerilog(); // 将Serilog添加到Host + +// 配置JSON序列化选项,使用驼峰命名法 +builder.Services.AddControllers().AddJsonOptions(options => +{ + options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; + options.JsonSerializerOptions.DictionaryKeyPolicy = JsonNamingPolicy.CamelCase; + options.JsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull; + options.JsonSerializerOptions.PropertyNameCaseInsensitive = true; +}); + +builder.Services.AddEndpointsApiExplorer(); +builder.Services.AddSwaggerGen(); +builder.Services.AddSingleton<FortranInteropService>(); + +// 配置CORS +builder.Services.AddCors(options => +{ + options.AddDefaultPolicy(policy => + { + policy.AllowAnyOrigin() + .AllowAnyMethod() + .AllowAnyHeader(); + }); +}); + +var app = builder.Build(); + +// Configure the HTTP request pipeline. +if (app.Environment.IsDevelopment()) +{ + app.UseSwagger(); + app.UseSwaggerUI(); +} + +app.UseCors(); +app.UseAuthorization(); +// 映射健康检查端点 +app.MapHealthChecks("/health"); +app.MapControllers(); + +try +{ + Log.Information("启动应用程序..."); + app.Run(); +} +catch (Exception ex) +{ + Log.Fatal(ex, "应用程序启动失败"); +} +finally +{ + Log.CloseAndFlush(); +} \ No newline at end of file diff --git a/Properties/launchSettings.json b/Properties/launchSettings.json new file mode 100644 index 0000000..295de27 --- /dev/null +++ b/Properties/launchSettings.json @@ -0,0 +1,14 @@ +{ + "profiles": { + "FortranWebApi": { + "commandName": "Project", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "dotnetRunMessages": true, + "applicationUrl": "http://0.0.0.0:5000" + } + } +} \ No newline at end of file diff --git a/Services/FortranInteropService.cs b/Services/FortranInteropService.cs new file mode 100644 index 0000000..07ec9f2 --- /dev/null +++ b/Services/FortranInteropService.cs @@ -0,0 +1,527 @@ +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 == "libMASIJINGGEN.so") + { + // 尝试从当前目录加载 + string currentDir = Directory.GetCurrentDirectory(); + string libraryPath = Path.Combine(currentDir, "libMASIJINGGEN.so"); + + if (File.Exists(libraryPath)) + { + return NativeLibrary.Load(libraryPath); + } + } + + // 回退到默认加载行为 + return IntPtr.Zero; + }); + } + + // DllImport声明 + [DllImport("libMASIJINGGEN.so", CallingConvention = CallingConvention.Cdecl, EntryPoint = "MASIJINGGEN")] + private static extern void MASIJINGGEN( + ref int NFILENAME, + ref int N, + float[] Q1, + ref float Q20, + ref float X, + ref float K, + ref float DETAT, + out float C0, + out float C1, + out float C2, + float[] Q2 + ); + + 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 NFILENAME = GetIntParameter(parameters, "NFILENAME"); + int N = GetIntParameter(parameters, "N"); + float[] Q1 = GetFloatArrayParameter(parameters, "Q1"); + float Q20 = GetFloatParameter(parameters, "Q20"); + float X = GetFloatParameter(parameters, "X"); + float K = GetFloatParameter(parameters, "K"); + float DETAT = GetFloatParameter(parameters, "DETAT"); + float C0; + float C1; + float C2; + + + // 准备数组参数 + float[] Q2 = new float[10000]; // 输出数组,初始大小为10000 + + + // 调用Fortran函数 + MASIJINGGEN( + ref NFILENAME, + ref N, + Q1, + ref Q20, + ref X, + ref K, + ref DETAT, + out C0, + out C1, + out C2, + Q2 + ); + + // 更新输出参数 + UpdateParameter(parameters, "C0", C0); + UpdateParameter(parameters, "C1", C1); + UpdateParameter(parameters, "C2", C2); + UpdateArrayParameter(parameters, "Q2", Q2); + + + // 处理输出数组 + // 处理输出数组 Q2 + // 注意:没有找到明确的长度参数,使用非零元素数量 + { + int nonZeroCount = 0; + for (int i = 0; i < Q2.Length; i++) + { + if (Q2[i] != 0) nonZeroCount = i + 1; + } + if (nonZeroCount > 0) + { + float[] resultArray = new float[nonZeroCount]; + Array.Copy(Q2, resultArray, nonZeroCount); + UpdateArrayParameter(parameters, "Q2", 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; + } + } + } +} \ No newline at end of file diff --git a/appsettings.json b/appsettings.json new file mode 100644 index 0000000..dcb0750 --- /dev/null +++ b/appsettings.json @@ -0,0 +1,16 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*", + "Kestrel": { + "Endpoints": { + "Http": { + "Url": "http://0.0.0.0:5000" + } + } + } +} \ No newline at end of file