0

This question is similar to this one : Is it possible to return multiple values from an external file to Dymola? but somehow, it could not help me.

I have the following C structure:

typedef struct ModelicaExport
{
    double* foo;
    double* bar;
} ModelicaExport;

and the following test function in C.

void testExport(double a, double b, void * modelicaExport)
{

    ModelicaExport* output = modelicaExport;

    double* foo = output->foo;
    double* bar = output->bar; 

    foo[0] = a;
    foo[1] = b;

    bar[0] = a - b;
    bar[1] = a + b;
}

The structure and function behaves normally in C, no issues here. I can export the function as a static library using Visual Studio Build Tools 2019. No issues here either.

The problem arises when I call this function is Dymola. I recreated the "structure" in Dymola as a record ( as indicated here https://mbe.modelica.university/behavior/functions/external/ )

record recordTest
  Real foo[3];
  Real bar[3];
end recordTest;

Then I created the function is dymola to call my external C function:

function testExportC "test calculation through external C code"
  extends Modelica.Icons.Function;
    input Real a;
    input Real b;

    output recordTest cc;

    external "C"  testExport(a, b, cc)
    annotation(Include="#include \"myheader.h\"",Library="mylib");
end testExportC;

I am confident the annotation with the header and library is correct since I tried it on even simpler function and everything works well. However testExportC does not work. It compiles fine, I get a message from dymola saying compilation is successful but then it "stopped without error indication" according to Dymola. What could I be missing ? I am using Dymola 2023x with Visual Studio Build Tools 2019 also.

MrBellamy
  • 29
  • 5
  • 1
    The page you link to indicates that an array of type `T[d1]` is mapped to a pair `T' *` and `size_t`, where `T'` is the type mapped to by `T`. Presumably the first member of the pair is a pointer to the first element of the array, and the second member is the number of elements. So a record containing `Real foo[3]; Real bar[3];` does not correspond to a structure with `double *foo; double *bar;`. It needs `double *foo; size_t fooSize; double *bar; size_t barSize;`. – Eric Postpischil Apr 01 '23 at 22:51
  • @EricPostpischil I tried to modify the C struct as ```struct ModelicaExport { double* foo; size_t fooSize; double* bar; size_t BarSize; }``` as you suggested but to no avail. I get the same error. If I follow the link, shouldn't it be actually ```double **foo, size_t fooSize, etc.``` ? I tried like that also, but it did not work either. – MrBellamy Apr 02 '23 at 20:10

1 Answers1

1

The external C interface in Modelica is intended for returning "values", and only scalars in records can be handled - specifically arrays as in modelicaExport are not supported, https://specification.modelica.org/master/functions.html#records

This is a recent change and the old link you use hasn't been updated.

The reason for forbidding arrays is that in practice arrays are often variable-length and that would create a mess. In particular in C the following structs:

typedef struct ModelicaExport
{
    double* foo;
    double* bar;
} ModelicaExport;

struct ModelicaExport2 {
  double foo[3];
  double bar[3];
}

are completely different, and not compatible.

You will either have to re-think the original issue (it might be a X-Y problem), or write a C-wrapper for testExport.

Hans Olsson
  • 11,123
  • 15
  • 38
  • In "12.9.1.2 Arrays", it says arrays are mapped like in my original link for "argument type mapping" which is my case since ModelicaExport is passed as an argument and NOT a return type. Am I getting this right ? – MrBellamy Apr 03 '23 at 19:13
  • No, 12.9.1.2 is for array arguments, e.g., passing cc.foo directly to the C-function. – Hans Olsson Apr 04 '23 at 05:58