【问题标题】:Error Returning Modelica Record from External C Function从外部 C 函数返回 Modelica 记录时出错
【发布时间】:2016-07-12 03:30:58
【问题描述】:

我编写了一个 C dll 函数,我想从 Modelica 调用它,并希望它返回一个 Modelica 记录。

基于“Modelica by Example”一书中描述的data mapping,我在我的 C 头文件中定义了一个结构,我的函数返回一个指向该结构的指针。您可以在下面看到标题内容:

#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 并返回“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 函数返回,使其直接返回结构而不是指向结构的指针,但我收到了类似的错误消息:

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

关于从外部 C 函数返回 Modelica 记录必须做什么的任何提示?

谢谢, 贾斯汀

【问题讨论】:

    标签: c modelica dymola


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

      作为我的解决方法,我能够通过更改外部函数来解决问题。不是在映射到记录的结构中返回数组(感谢 Shaga 指出这不受 modelica 规范的支持),而是将该函数更改为返回具有四个输出数组的 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;
      

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

      谢谢, 贾斯汀

      【讨论】:

        【解决方案3】:

        您可以通过在外部函数调用中使用分层名称来向 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 Revision 1 中添加的新功能,https://trac.modelica.org/Modelica/ticket/351 并且应该从 Dymola 2015 开始提供。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-11-18
          • 2021-09-16
          • 1970-01-01
          • 1970-01-01
          • 2015-11-21
          • 2023-01-21
          • 2017-05-31
          • 1970-01-01
          相关资源
          最近更新 更多