从外部 C 函数返回 Modelica 记录时出错

Error Returning Modelica Record from External C Function

我已经编写了一个 C dll 函数,我想从 Modelica 调用它,并希望它成为 return Modelica 记录。

根据 "Modelica by Example" 书中描述的 data mapping,我在我的 C header 中定义了一个结构,我的函数 return 是一个指向该结构的指针。您可以在下面看到header内容:

#ifdef NZ1MAP_EXPORTS
#define NZ1MAP_API __declspec(dllexport)
#else
#define NZ1MAP_API __declspec(dllimport)
#endif

#ifdef __cplusplus
    extern "C" {
#endif

    // Define struct to match the SpeedlineVectors record in Modelica.
    typedef struct
    {
        double Mach;
        double PRVposition;
        double DiffuserGap;
        double Theta[24];
        double Omega[24];
        double MapEfficiency[24];
        double OmegaStall[24];
    } SpeedlineVectors;


    NZ1MAP_API SpeedlineVectors* GetNZ1SpeedlineVectors_External(double Mach, double DiffuserGapFraction);

#ifdef __cplusplus
    }
#endif

在 Dymola 中,我创建了以下记录:

record SpeedlineVectors 
  "Mach, PRV position, Diffuser Gap, and Vectors of Theta, Omega, Map Efficiency, Omega Stall"

  Real Mach "impeller machine Mach";
  Real PRVposition "PRV position, 0 = fully closed, 1 = fully open";
  Real DiffuserGap 
    "Diffuser gap, 0 = fully closed, 1 = fully open, typical minimum = 0.05";

  Real Theta[24] "vector of non-dimensional flow coefficients along speed line";
  Real Omega[24] "vector of non-dimensional head coefficients along speed line";
  Real MapEfficiency[24] 
    "vector of isentropic efficiency normalized to tip Reynolds number of 1E6 along speed line";
  Real OmegaStall[24] 
    "vector of non-dimensional head where stall is expected to begin along speed line";

end SpeedlineVectors;

并且我创建了应该调用外部 C dll 和 return 一条 "SpeedlineVectors" 记录的函数:

function GetNZ1SpeedlineVectors_External 
  "Get NZ1 speedline array from external C function"

  input Real operatingMach "Machine Mach number";
  input Real diffuserGapFraction "Diffuser gap open fraction, 0 to 1";
  output SpeedlineVectors speedlineVectors "speedlineVectors record";

  external "C" speedlineVectors = GetNZ1SpeedlineVectors_External(operatingMach, diffuserGapFraction);
  annotation(Include="#include <NZ1Map.h>", Library="NZ1Map");

end GetNZ1SpeedlineVectors_External;

我建立了下面的简单测试模型:

model GetNZ1SpeedlineVectors_Tester
  Real mach = 1.32;
  Real diffuserGapFraction = 0.50;
  SpeedlineVectors myVectors;

equation 
  myVectors = GetNZ1SpeedlineVectors_External(mach, diffuserGapFraction);

  annotation (Icon(coordinateSystem(preserveAspectRatio=false)), Diagram(
        coordinateSystem(preserveAspectRatio=false)));
end GetNZ1SpeedlineVectors_Tester;

当我尝试 运行 测试模型时,我从 Dymola 收到以下错误消息:

Compiling and linking the model (Visual C++). 

dsmodel.c
dsmodel.c(74) : error C2440: '=' : cannot convert from 'SpeedlineVectors *' to 'DymStruc0'

Error generating Dymosim. 

我也尝试调整 C 函数 return 以便它直接 return 结构而不是指向结构的指针,但我收到类似的错误消息:

dsmodel.c(74) : error C2440: '=' : cannot convert from 'SpeedlineVectors' to 'DymStruc0'

关于必须对来自外部 C 函数的 Modelica 记录执行哪些操作的任何提示?

谢谢, 贾斯汀

根据 Modelica 规范第 12.9.1.3 节,当从外部函数返回时,无法映射记录中的数组。您也可以尝试使用外部对象:https://build.openmodelica.org/Documentation/ModelicaReference.Classes.ExternalObject.html

作为我的案例的解决方法,我能够通过更改外部函数来解决问题。而不是 returning 映射到记录的结构中的数组(感谢 Shaga 指出根据 modelica 规范不支持),函数更改为 return void 有四个输出数组。

C 头文件中的新函数定义是:

NZ1MAP_API void GetNZ1SpeedlineVectors_External(double Mach, double DiffuserGapFraction, double ThetaVector[], size_t SizeOfThetaVector, double OmegaVector[], size_t SizeOfOmegaVector, double MapEfficiencyVector[], size_t SizeOfMapEfficiencyVector, double OmegaStallVector[], size_t SizeOfOmegaStallVector);

C文件中的C函数定义为:

NZ1MAP_API void GetNZ1SpeedlineVectors_External(double Mach, double DiffuserGapFraction,
    double thetaVector[], size_t thetaVectorSize, // thetaVector[] is equivalent to double* thetaVector
    double omegaVector[], size_t omegaVectorSize,
    double efficiencyVector[], size_t efficiencyVectorSize,
    double omegaStallVector[], size_t omegaStallVectorSize)

modelica函数如下图:

function GetNZ1SpeedlineVectors_External 
  "Get NZ1 speedline array from external C function"

  input Real operatingMach "Machine Mach number";
  input Real diffuserGapFraction "Diffuser gap open fraction, 0 to 1";
  output Real ThetaVector[24] 
    "vector of non-dimensional flow coefficients along speedline";
  output Real OmegaVector[24] 
    "vector of non-dimensional head coefficients along speedline";
  output Real MapEfficiencyVector[24] 
    "vector of non-dimensional map efficiency along speedline";
  output Real OmegaStallVector[24] "vector of omega stall along speedline";

  external "C" GetNZ1SpeedlineVectors_External(operatingMach, diffuserGapFraction, ThetaVector, size(ThetaVector,1), OmegaVector, size(OmegaVector,1), MapEfficiencyVector, size(MapEfficiencyVector,1), OmegaStallVector, size(OmegaStallVector, 1));
  annotation(Include = "#include <NZ1Map.h>", Library="NZ1Map");

end GetNZ1SpeedlineVectors_External;

调用modelica函数的测试模型为:

model NZ1_External "NZ1 External Dll"
  extends SpeedlineVectorsBase;

  parameter Real inputMach = 1.4;
  parameter Real inputDiffuserGapFraction = 1;

equation 
  Mach = inputMach;
  PRVposition = 1;
  DiffuserGapFraction = inputDiffuserGapFraction;

  (ThetaVector, OmegaVector, MapEfficiencyVector, OmegaStallVector) =
    GetNZ1SpeedlineVectors_External(Mach, DiffuserGapFraction);
end NZ1_External;

我希望这可以帮助其他人了解他们如何 return 从外部函数到 modelica 的多个数组,因为 modelica 不会将数组 return 映射为结构的一部分。

谢谢, 贾斯汀

您可以通过在外部函数调用中使用分层名称来向 Modelica 函数的用户隐藏多个数组。

function GetNZ1SpeedlineVectors_External 
  input Real operatingMach "Machine Mach number";
  input Real diffuserGapFraction "Diffuser gap open fraction, 0 to 1";
  output SpeedlineVectors speedlineVectors "speedlineVectors record";
  external "C" GetNZ1SpeedlineVectors_External(operatingMach,diffuserGapFraction, speedLineVectors.ThetaVector, size(speedLineVectors.ThetaVector,1), ...);
 annotation(Include="#include <NZ1Map.h>", Library="NZ1Map");
end GetNZ1SpeedlineVectors_External;

这是 Modelica 3.3 修订版 1 中添加的新功能,https://trac.modelica.org/Modelica/ticket/351 并且应该从 Dymola 2015 开始可用。