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

时间:2016-07-12 03:30:59

标签: c modelica dymola

我编写了一个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记录必须执行的操作的任何提示吗?

谢谢, 贾斯汀

3 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分: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不会映射作为结构的一部分返回的数组。

谢谢, 贾斯汀

答案 2 :(得分:1)

您可以通过在外部函数调用中使用分层名称来隐藏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开始提供。