我编写了一个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记录必须执行的操作的任何提示吗?
谢谢, 贾斯汀
答案 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开始提供。