Search code examples
cmodelicadymola

Error Returning Modelica Record from External C Function


I have written a C dll function that I want to call from Modelica, and want it to return a Modelica record.

Based upon the data mapping described in the "Modelica by Example" book, I defined a structure in my C header and my function returns a pointer to the structure. You can see the header contents below:

#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

In Dymola, I created the record below:

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;

And I created the function that should call the external C dll and return a "SpeedlineVectors" record:

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;

I built the simple test model below:

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;

When I try to run the test model, I receive the following error messages from Dymola:

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

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

Error generating Dymosim. 

I also tried adjusting the C function return so that it returns the struct directly rather than a pointer to the struct, but I receive a similar error message:

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

Any tips on what must be done to return a Modelica record from an external C function?

Thanks, Justin


Solution

  • According to the Modelica specification section 12.9.1.3 arrays in a record cannot be mapped when returned from an external function. You could also try using the ExternalObject: https://build.openmodelica.org/Documentation/ModelicaReference.Classes.ExternalObject.html