]> gerrit.simantics Code Review - simantics/fmil.git/commitdiff
Reduced logging level in FMIL to warning 61/2061/1
authorMarko Luukkainen <marko.luukkainen@semantum.fi>
Thu, 30 Aug 2018 12:41:41 +0000 (15:41 +0300)
committerMarko Luukkainen <marko.luukkainen@semantum.fi>
Thu, 30 Aug 2018 12:41:41 +0000 (15:41 +0300)
Fixed compilation issues with VS2017

gitlab #2
gitlab #3

Change-Id: I1caf4a7ed7fe3443a3180b857a87ae0d487b84b2

16 files changed:
org.simantics.fmil.core/native/FMUSimulator/fmi_util.c.txt
org.simantics.fmil.core/native/FMUSimulator/fmilib_shared32.lib
org.simantics.fmil.core/native/FMUSimulator/fmilib_shared64.lib
org.simantics.fmil.core/native/FMUSimulator/src/sim_support.c
org.simantics.fmil.win32/libraries/FMUSimulator.dll
org.simantics.fmil.win32/libraries/fmilib_shared.dll
org.simantics.fmil.win32/libraries/fmu1_dll_cs.dll
org.simantics.fmil.win32/libraries/fmu1_dll_me.dll
org.simantics.fmil.win32/libraries/fmu2_dll_cs.dll
org.simantics.fmil.win32/libraries/fmu2_dll_me.dll
org.simantics.fmil.win64/libraries/FMUSimulator.dll
org.simantics.fmil.win64/libraries/fmilib_shared.dll
org.simantics.fmil.win64/libraries/fmu1_dll_cs.dll
org.simantics.fmil.win64/libraries/fmu1_dll_me.dll
org.simantics.fmil.win64/libraries/fmu2_dll_cs.dll
org.simantics.fmil.win64/libraries/fmu2_dll_me.dll

index bfd6e203a552bb8144e48862945e32b5e3ce9180..450910cad7820976fc8435cfeec039214e4fa252 100644 (file)
@@ -180,7 +180,11 @@ int FMI_CS_LOAD(const char *zipFilePath, const char *unzipFolder, void **fmuPoin
     callbacks->realloc = realloc;
     callbacks->free = free;
     callbacks->logger = importlogger;
+#ifdef _DEBUG
     callbacks->log_level = jm_log_level_debug;
+#else
+       callbacks->log_level = jm_log_level_warning;
+#endif
     callbacks->context = 0;
 
        context = fmi_import_allocate_context(callbacks);
index 205ff49e963bde8ed55f6090749b98d602c67cbe..2951ee8e2bb882fe93154d2fd76d2aa867c3244f 100644 (file)
Binary files a/org.simantics.fmil.core/native/FMUSimulator/fmilib_shared32.lib and b/org.simantics.fmil.core/native/FMUSimulator/fmilib_shared32.lib differ
index d181250813e2e877a6367e1e16e569ffa7ccf802..fec3a347084542b384967fcb40ca39f063217ed0 100644 (file)
Binary files a/org.simantics.fmil.core/native/FMUSimulator/fmilib_shared64.lib and b/org.simantics.fmil.core/native/FMUSimulator/fmilib_shared64.lib differ
index 71915f02785ee474d3226183615fcf627f7d7bb9..5725147ad04c49315437a748e695fd285573564a 100644 (file)
-/* ------------------------------------------------------------------------- \r
- * sim_support.c\r
- * Functions used by both FMU simulators fmusim_me and fmusim_cs\r
- * to parse command-line arguments, to unzip and load an fmu, \r
- * to write CSV file, and more.\r
- * Copyright 2011 QTronic GmbH. All rights reserved. \r
- * -------------------------------------------------------------------------*/ \r
-\r
-#include <stdio.h>\r
-#include <stdlib.h>\r
-#include <string.h>\r
-#include <assert.h>\r
-#include <time.h>\r
-#include <stdarg.h>\r
-\r
-#ifdef FMI_COSIMULATION\r
-#include "fmi_cs.h"\r
-#else\r
-#include "fmi_me.h"\r
-#endif\r
-\r
-// linux/unix DSO loading\r
-#ifndef _MSC_VER\r
-#include <dlfcn.h>\r
-#endif\r
-\r
-#include "sim_support.h"\r
-//#include "fmuExtract.h"\r
-\r
-#define MAX_PATH_SIZE 4096\r
-\r
-#ifdef _MSC_VER\r
-// fileName is an absolute path, e.g. C:\test\a.fmu\r
-// or relative to the current dir, e.g. ..\test\a.fmu\r
-// Does not check for existence of the file\r
-static char* getFmuPath(const char* fileName){\r
-    char pathName[MAX_PATH_SIZE];\r
-    int n = GetFullPathName(fileName, MAX_PATH, pathName, NULL);\r
-    return n ? strdup(pathName) : NULL;\r
-}\r
-\r
-int tmpPathRequests = 0;\r
-static char* getTmpPath() {\r
-    char tmpPath[BUFSIZE];\r
-    if(! GetTempPath(BUFSIZE, tmpPath)) {\r
-        printf ("error: Could not find temporary disk space\n");\r
-        return NULL;\r
-    }\r
-       if(tmpPathRequests % 2 == 0) {\r
-               strcat(tmpPath, "fmu\\");\r
-               tmpPathRequests++;\r
-       } else {\r
-               strcat(tmpPath, "fmu2\\");\r
-               tmpPathRequests = 0;\r
-       }\r
-\r
-       makedir(tmpPath);\r
-\r
-    return strdup(tmpPath);\r
-}\r
-#endif\r
-\r
-static void* getAdr(int* s, FMU *fmu, const char* functionName){\r
-    char name[BUFSIZE];\r
-    void* fp;\r
-    sprintf(name, "%s_%s", getModelIdentifier(fmu->modelDescription), functionName);\r
-#ifdef _MSC_VER\r
-    fp = GetProcAddress(fmu->dllHandle, name);\r
-#else\r
-    fp = dlsym(fmu->dllHandle, name);\r
-#endif\r
-    if (!fp) {\r
-        printf ("warning: Function %s not found in dll\n", name);\r
-        *s = 0; // mark dll load as 'failed'        \r
-    }\r
-    return fp;\r
-}\r
-\r
-// Load the given dll and set function pointers in fmu\r
-// Return 0 to indicate failure\r
-static int loadDll(const char* dllPath, FMU *fmu) {\r
-    int s = 1;\r
-#ifdef _MSC_VER\r
-    HANDLE h = LoadLibraryEx(dllPath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);\r
-    if (!h) {\r
-        int error = GetLastError();\r
-        printf("error %d: Could not load %s\n", error, dllPath);\r
-        return 0; // failure\r
-    }\r
-    fmu->dllHandle = h;\r
-#else\r
-    void* h = dlopen(dllPath, RTLD_LAZY);\r
-    if (!h) {\r
-        char* error = dlerror();\r
-        printf("error %s: Could not load %s\n", error, dllPath);\r
-        return 0; // failure\r
-    }\r
-    fmu->dllHandle = h;\r
-#endif\r
-\r
-#ifdef FMI_COSIMULATION   \r
-    fmu->getTypesPlatform        = (fGetTypesPlatform)   getAdr(&s, fmu, "fmiGetTypesPlatform");\r
-    if (s==0) { \r
-        s = 1; // work around bug for FMUs exported using Dymola 2012 and SimulationX 3.x\r
-        fmu->getTypesPlatform    = (fGetTypesPlatform)   getAdr(&s, fmu, "fmiGetModelTypesPlatform");\r
-        if (s==1) printf("  using fmiGetModelTypesPlatform instead\n", dllPath);\r
-    }\r
-    fmu->instantiateSlave        = (fInstantiateSlave)   getAdr(&s, fmu, "fmiInstantiateSlave");\r
-    fmu->initializeSlave         = (fInitializeSlave)    getAdr(&s, fmu, "fmiInitializeSlave");    \r
-    fmu->terminateSlave          = (fTerminateSlave)     getAdr(&s, fmu, "fmiTerminateSlave");\r
-    fmu->resetSlave              = (fResetSlave)         getAdr(&s, fmu, "fmiResetSlave");\r
-    fmu->freeSlaveInstance       = (fFreeSlaveInstance)  getAdr(&s, fmu, "fmiFreeSlaveInstance");\r
-    fmu->setRealInputDerivatives = (fSetRealInputDerivatives) getAdr(&s, fmu, "fmiSetRealInputDerivatives");\r
-    fmu->getRealOutputDerivatives = (fGetRealOutputDerivatives) getAdr(&s, fmu, "fmiGetRealOutputDerivatives");\r
-    fmu->cancelStep              = (fCancelStep)         getAdr(&s, fmu, "fmiCancelStep");\r
-    fmu->doStep                  = (fDoStep)             getAdr(&s, fmu, "fmiDoStep");\r
-    // SimulationX 3.4 and 3.5 do not yet export getStatus and getXStatus: do not count this as failure here\r
-    fmu->getStatus               = (fGetStatus)          getAdr(&x, fmu, "fmiGetStatus");\r
-    fmu->getRealStatus           = (fGetRealStatus)      getAdr(&x, fmu, "fmiGetRealStatus");\r
-    fmu->getIntegerStatus        = (fGetIntegerStatus)   getAdr(&x, fmu, "fmiGetIntegerStatus");\r
-    fmu->getBooleanStatus        = (fGetBooleanStatus)   getAdr(&x, fmu, "fmiGetBooleanStatus");\r
-    fmu->getStringStatus         = (fGetStringStatus)    getAdr(&x, fmu, "fmiGetStringStatus");    \r
-\r
-#else // FMI for Model Exchange 1.0\r
-    fmu->getModelTypesPlatform   = (fGetModelTypesPlatform) getAdr(&s, fmu, "fmiGetModelTypesPlatform");\r
-    fmu->instantiateModel        = (fInstantiateModel)   getAdr(&s, fmu, "fmiInstantiateModel");\r
-    fmu->freeModelInstance       = (fFreeModelInstance)  getAdr(&s, fmu, "fmiFreeModelInstance");\r
-    fmu->setTime                 = (fSetTime)            getAdr(&s, fmu, "fmiSetTime");\r
-    fmu->setContinuousStates     = (fSetContinuousStates)getAdr(&s, fmu, "fmiSetContinuousStates");\r
-    fmu->completedIntegratorStep = (fCompletedIntegratorStep)getAdr(&s, fmu, "fmiCompletedIntegratorStep");\r
-    fmu->initialize              = (fInitialize)         getAdr(&s, fmu, "fmiInitialize");\r
-    fmu->getDerivatives          = (fGetDerivatives)     getAdr(&s, fmu, "fmiGetDerivatives");\r
-    fmu->getEventIndicators      = (fGetEventIndicators) getAdr(&s, fmu, "fmiGetEventIndicators");\r
-    fmu->eventUpdate             = (fEventUpdate)        getAdr(&s, fmu, "fmiEventUpdate");\r
-    fmu->getContinuousStates     = (fGetContinuousStates)getAdr(&s, fmu, "fmiGetContinuousStates");\r
-    fmu->getNominalContinuousStates = (fGetNominalContinuousStates)getAdr(&s, fmu, "fmiGetNominalContinuousStates");\r
-    fmu->getStateValueReferences = (fGetStateValueReferences)getAdr(&s, fmu, "fmiGetStateValueReferences");\r
-    fmu->terminate               = (fTerminate)          getAdr(&s, fmu, "fmiTerminate");\r
-#endif \r
-    fmu->getVersion              = (fGetVersion)         getAdr(&s, fmu, "fmiGetVersion");\r
-    fmu->setDebugLogging         = (fSetDebugLogging)    getAdr(&s, fmu, "fmiSetDebugLogging");\r
-    fmu->setReal                 = (fSetReal)            getAdr(&s, fmu, "fmiSetReal");\r
-    fmu->setInteger              = (fSetInteger)         getAdr(&s, fmu, "fmiSetInteger");\r
-    fmu->setBoolean              = (fSetBoolean)         getAdr(&s, fmu, "fmiSetBoolean");\r
-    fmu->setString               = (fSetString)          getAdr(&s, fmu, "fmiSetString");\r
-    fmu->getReal                 = (fGetReal)            getAdr(&s, fmu, "fmiGetReal");\r
-    fmu->getInteger              = (fGetInteger)         getAdr(&s, fmu, "fmiGetInteger");\r
-    fmu->getBoolean              = (fGetBoolean)         getAdr(&s, fmu, "fmiGetBoolean");\r
-    fmu->getString               = (fGetString)          getAdr(&s, fmu, "fmiGetString");\r
-    return s; \r
-}\r
-\r
-/*static void printModelDescription(ModelDescription* md){\r
-    Element* e = (Element*)md;  \r
-    int i;\r
-    printf("%s\n", elmNames[e->type]);\r
-    for (i=0; i<e->n; i+=2) \r
-        printf("  %s=%s\n", e->attributes[i], e->attributes[i+1]);\r
-#ifdef FMI_COSIMULATION   \r
-    if (!md->cosimulation) {\r
-        printf("error: No Implementation element found in model description. This FMU is not for Co-Simulation.\n");\r
-        exit(EXIT_FAILURE);\r
-    }\r
-    e = md->cosimulation->capabilities;\r
-    printf("%s\n", elmNames[e->type]);\r
-    for (i=0; i<e->n; i+=2) \r
-        printf("  %s=%s\n", e->attributes[i], e->attributes[i+1]);\r
-#endif // FMI_COSIMULATION  \r
-}\r
-*/\r
-\r
-/*\r
- * return: 1 for successful laod or number for error.\r
- * -1. FMU path not found\r
- * -2. Unzip failed\r
- * -3. Loading model description failed\r
- * -4. FMU dll load failed\r
- */\r
-/*\r
-int loadFMU(FMU *fmu, const char* fmuFileName, const char* tmpPath) {\r
-    char* fmuPath;\r
-    char* xmlPath;\r
-    char* dllPath;\r
-       unsigned old_clock = clock();\r
-       unsigned current_clock = 0;//will be assigned later\r
-    \r
-    // get absolute path to FMU, NULL if not found\r
-    fmuPath = getFmuPath(fmuFileName);\r
-    if (!fmuPath) return -1; // path not found\r
-\r
-    // unzip the FMU to the tmpPath directory\r
-    if (unzip(fmuPath, tmpPath)) return -2; // unzip failed\r
-\r
-    // parse tmpPath\modelDescription.xml\r
-    xmlPath = calloc(sizeof(char), strlen(tmpPath) + strlen(XML_FILE) + 1);\r
-    sprintf(xmlPath, "%s%s", tmpPath, XML_FILE);\r
-    fmu->modelDescription = parse(xmlPath);\r
-    free(xmlPath);\r
-    if (!fmu->modelDescription) return -3; // loading model description failed\r
-\r
-       // printModelDescription(fmu.modelDescription);\r
-       // fflush(stdout);\r
-\r
-    // load the FMU dll\r
-    dllPath = calloc(sizeof(char), strlen(tmpPath) + strlen(DLL_DIR) \r
-            + strlen( getModelIdentifier(fmu->modelDescription)) +  strlen(".dll") + 1);\r
-    sprintf(dllPath,"%s%s%s.dll", tmpPath, DLL_DIR, getModelIdentifier(fmu->modelDescription));\r
-    if (!loadDll(dllPath, fmu)) return -4; // loading dll failed\r
-\r
-    free(dllPath);\r
-    free(fmuPath);\r
-\r
-       return 1;\r
-}\r
-*/\r
-\r
-static void doubleToCommaString(char* buffer, double r){\r
-    char* comma;\r
-    sprintf(buffer, "%.16g", r);\r
-    comma = strchr(buffer, '.');\r
-    if (comma) *comma = ',';\r
-}\r
-\r
-// output time and all non-alias variables in CSV format\r
-// if separator is ',', columns are separated by ',' and '.' is used for floating-point numbers.\r
-// otherwise, the given separator (e.g. ';' or '\t') is to separate columns, and ',' is used \r
-// as decimal dot in floating-point numbers.\r
-/*\r
-void outputRow(FMU *fmu, fmiComponent c, double time, FILE* file, char separator, boolean header) {\r
-    int k;\r
-    fmiReal r;\r
-    fmiInteger i;\r
-    fmiBoolean b;\r
-    fmiString s;\r
-    fmiValueReference vr;\r
-    ScalarVariable** vars = fmu->modelDescription->modelVariables;\r
-    char buffer[32];\r
-    \r
-    // print first column\r
-    if (header) \r
-        fprintf(file, "time"); \r
-    else {\r
-        if (separator==',') \r
-            fprintf(file, "%.16g", time);\r
-        else {\r
-            // separator is e.g. ';' or '\t'\r
-            doubleToCommaString(buffer, time);\r
-            fprintf(file, "%s", buffer);       \r
-        }\r
-    }\r
-    \r
-    // print all other columns\r
-    for (k=0; vars[k]; k++) {\r
-        ScalarVariable* sv = vars[k];\r
-        if (getAlias(sv)!=enu_noAlias) continue;\r
-        if (header) {\r
-            // output names only\r
-            if (separator==',') {\r
-                // treat array element, e.g. print a[1, 2] as a[1.2]\r
-                char* s = getName(sv);\r
-                fprintf(file, "%c", separator);\r
-                while (*s) {\r
-                   if (*s!=' ') fprintf(file, "%c", *s==',' ? '.' : *s);\r
-                   s++;\r
-                }\r
-             }\r
-            else\r
-                fprintf(file, "%c%s", separator, getName(sv));\r
-        }\r
-        else {\r
-            // output values\r
-            vr = getValueReference(sv);\r
-            switch (sv->typeSpec->type){\r
-                case elm_Real:\r
-                    fmu->getReal(c, &vr, 1, &r);\r
-                    if (separator==',') \r
-                        fprintf(file, ",%.16g", r);\r
-                    else {\r
-                        // separator is e.g. ';' or '\t'\r
-                        doubleToCommaString(buffer, r);\r
-                        fprintf(file, "%c%s", separator, buffer);       \r
-                    }\r
-                    break;\r
-                case elm_Integer:\r
-                case elm_Enumeration:\r
-                    fmu->getInteger(c, &vr, 1, &i);\r
-                    fprintf(file, "%c%d", separator, i);\r
-                    break;\r
-                case elm_Boolean:\r
-                    fmu->getBoolean(c, &vr, 1, &b);\r
-                    fprintf(file, "%c%d", separator, b);\r
-                    break;\r
-                case elm_String:\r
-                    fmu->getString(c, &vr, 1, &s);\r
-                    fprintf(file, "%c%s", separator, s);\r
-                    break;\r
-                default: \r
-                    fprintf(file, "%cNoValueForType=%d", separator,sv->typeSpec->type);\r
-            }\r
-        }\r
-    } // for\r
-    \r
-    // terminate this row\r
-    fprintf(file, "\n"); \r
-}\r
-*/\r
-\r
-static const char* fmiStatusToString(fmiStatus status){\r
-    switch (status){\r
-        case fmiOK:      return "ok";\r
-        case fmiWarning: return "warning";\r
-        case fmiDiscard: return "discard";\r
-        case fmiError:   return "error";\r
-        case fmiFatal:   return "fatal";\r
-#ifdef FMI_COSIMULATION\r
-        case fmiPending: return "fmiPending";\r
-#endif\r
-        default:         return "?";\r
-    }\r
-}\r
-\r
-// search a fmu for the given variable\r
-// return NULL if not found or vr = fmiUndefinedValueReference\r
-static ScalarVariable* getSV(FMU* fmu, char type, fmiValueReference vr) {\r
-    int i;\r
-    Elm tp;\r
-    ScalarVariable** vars = fmu->modelDescription->modelVariables;\r
-    if (vr==fmiUndefinedValueReference) return NULL;\r
-    switch (type) {\r
-        case 'r': tp = elm_Real;    break;\r
-        case 'i': tp = elm_Integer; break;\r
-        case 'b': tp = elm_Boolean; break;\r
-        case 's': tp = elm_String;  break;                \r
-    }\r
-    for (i=0; vars[i]; i++) {\r
-        ScalarVariable* sv = vars[i];\r
-        if (vr==getValueReference(sv) && tp==sv->typeSpec->type) \r
-            return sv;\r
-    }\r
-    return NULL;\r
-}\r
-\r
-// replace e.g. #r1365# by variable name and ## by # in message\r
-// copies the result to buffer\r
-static void replaceRefsInMessage(const char* msg, char* buffer, int nBuffer, FMU* fmu){\r
-    int i=0; // position in msg\r
-    int k=0; // position in buffer\r
-    int n;\r
-    char c = msg[i];\r
-    while (c!='\0' && k < nBuffer) {\r
-        if (c!='#') {\r
-            buffer[k++]=c;\r
-            i++;\r
-            c = msg[i];\r
-        }\r
-        else {\r
-            char* end = strchr(const_cast<char*>(msg+i+1), '#');\r
-            if (!end) {\r
-                printf("unmatched '#' in '%s'\n", msg);\r
-                buffer[k++]='#';\r
-                break;\r
-            }\r
-            n = end - (msg+i);\r
-            if (n==1) {\r
-                // ## detected, output #\r
-                buffer[k++]='#';\r
-                i += 2;\r
-                c = msg[i];\r
-            }\r
-            else {\r
-                char type = msg[i+1]; // one of ribs\r
-                fmiValueReference vr;\r
-                int nvr = sscanf(msg+i+2, "%u", &vr);\r
-                if (nvr==1) {\r
-                    // vr of type detected, e.g. #r12#\r
-                    ScalarVariable* sv = getSV(fmu, type, vr);\r
-                    const char* name = sv ? getName(sv) : "?";\r
-                    sprintf(buffer+k, "%s", name);\r
-                    k += strlen(name);\r
-                    i += (n+1);\r
-                    c = msg[i]; \r
-                }\r
-                else {\r
-                    // could not parse the number\r
-                    printf("illegal value reference at position %d in '%s'\n", i+2, msg);\r
-                    buffer[k++]='#';\r
-                    break;\r
-                }\r
-            }\r
-        }\r
-    } // while\r
-    buffer[k] = '\0';\r
-}\r
-\r
-#define MAX_MSG_SIZE 1000\r
-void fmuLogger(FMU *fmu, fmiComponent c, fmiString instanceName, fmiStatus status,\r
-               fmiString category, fmiString message, ...) {\r
-    char msg[MAX_MSG_SIZE];\r
-//    char* copy;\r
-    va_list argp;\r
-\r
-    // replace C format strings\r
-    va_start(argp, message);\r
-    vsprintf(msg, message, argp);\r
-    va_end(argp);\r
-\r
-    // replace e.g. ## and #r12#  \r
-//    copy = strdup(msg);\r
-//    replaceRefsInMessage(copy, msg, MAX_MSG_SIZE, fmu);\r
-//    free(copy);\r
-    \r
-    // print the final message\r
-    if (!instanceName) instanceName = "?";\r
-    if (!category) category = "?";\r
-    //printf("%s %s (%s): %s\n", fmiStatusToString(status), instanceName, category, msg);\r
-       printf("%s\n", message);\r
-}\r
-\r
-int error(const char* message){\r
-    printf("%s\n", message);\r
-    return 0;\r
-}\r
-\r
-void parseArguments(int argc, char *argv[], char** fmuFileName, double* tEnd, double* h, int* loggingOn, char* csv_separator) {\r
-    // parse command line arguments\r
-    if (argc>1) {\r
-        *fmuFileName = argv[1];\r
-    }\r
-    else {\r
-        printf("error: no fmu file\n");\r
-        printHelp(argv[0]);\r
-        exit(EXIT_FAILURE);\r
-    }\r
-    if (argc>2) {\r
-        if (sscanf(argv[2],"%lf", tEnd) != 1) {\r
-            printf("error: The given end time (%s) is not a number\n", argv[2]);\r
-            exit(EXIT_FAILURE);\r
-        }\r
-    }\r
-    if (argc>3) {\r
-        if (sscanf(argv[3],"%lf", h) != 1) {\r
-            printf("error: The given stepsize (%s) is not a number\n", argv[3]);\r
-            exit(EXIT_FAILURE);\r
-        }\r
-    }\r
-    if (argc>4) {\r
-        if (sscanf(argv[4],"%d", loggingOn) != 1 || *loggingOn<0 || *loggingOn>1) {\r
-            printf("error: The given logging flag (%s) is not boolean\n", argv[4]);\r
-            exit(EXIT_FAILURE);\r
-        }\r
-    }\r
-    if (argc>5) {\r
-        if (strlen(argv[5]) != 1) {\r
-            printf("error: The given CSV separator char (%s) is not valid\n", argv[5]);\r
-            exit(EXIT_FAILURE);\r
-        }\r
-        switch (argv[5][0]) {\r
-            case 'c': *csv_separator = ','; break; // comma\r
-            case 's': *csv_separator = ';'; break; // semicolon\r
-            default:  *csv_separator = argv[5][0]; break; // any other char\r
-        }\r
-    }\r
-    if (argc>6) {\r
-        printf("warning: Ignoring %d additional arguments: %s ...\n", argc-6, argv[6]);\r
-        printHelp(argv[0]);\r
-    }\r
-}\r
-\r
-void printHelp(const char* fmusim) {\r
-    printf("command syntax: %s <model.fmu> <tEnd> <h> <loggingOn> <csv separator>\n", fmusim);\r
-    printf("   <model.fmu> .... path to FMU, relative to current dir or absolute, required\n");\r
-    printf("   <tEnd> ......... end  time of simulation, optional, defaults to 1.0 sec\n");\r
-    printf("   <h> ............ step size of simulation, optional, defaults to 0.1 sec\n");\r
-    printf("   <loggingOn> .... 1 to activate logging,   optional, defaults to 0\n");\r
-    printf("   <csv separator>. separator in csv file,   optional, c for ';', s for';', defaults to c\n");\r
-}\r
-\r
+/* ------------------------------------------------------------------------- 
+ * sim_support.c
+ * Functions used by both FMU simulators fmusim_me and fmusim_cs
+ * to parse command-line arguments, to unzip and load an fmu, 
+ * to write CSV file, and more.
+ * Copyright 2011 QTronic GmbH. All rights reserved. 
+ * -------------------------------------------------------------------------*/ 
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <time.h>
+#include <stdarg.h>
+
+#ifdef FMI_COSIMULATION
+#include "fmi_cs.h"
+#else
+#include "fmi_me.h"
+#endif
+
+// linux/unix DSO loading
+#ifndef _MSC_VER
+#include <dlfcn.h>
+#endif
+
+#include "sim_support.h"
+//#include "fmuExtract.h"
+
+#define MAX_PATH_SIZE 4096
+
+#ifdef _MSC_VER
+
+#include <windows.h>
+// fileName is an absolute path, e.g. C:\test\a.fmu
+// or relative to the current dir, e.g. ..\test\a.fmu
+// Does not check for existence of the file
+static char* getFmuPath(const char* fileName){
+    char pathName[MAX_PATH_SIZE];
+    int n = GetFullPathName(fileName, MAX_PATH_SIZE, pathName, NULL);
+    return n ? strdup(pathName) : NULL;
+}
+
+int tmpPathRequests = 0;
+static char* getTmpPath() {
+    char tmpPath[BUFSIZE];
+    if(! GetTempPath(BUFSIZE, tmpPath)) {
+        printf ("error: Could not find temporary disk space\n");
+        return NULL;
+    }
+       if(tmpPathRequests % 2 == 0) {
+               strcat(tmpPath, "fmu\\");
+               tmpPathRequests++;
+       } else {
+               strcat(tmpPath, "fmu2\\");
+               tmpPathRequests = 0;
+       }
+
+       makedir(tmpPath);
+
+    return strdup(tmpPath);
+}
+#endif
+
+static void* getAdr(int* s, FMU *fmu, const char* functionName){
+    char name[BUFSIZE];
+    void* fp;
+    sprintf(name, "%s_%s", getModelIdentifier(fmu->modelDescription), functionName);
+#ifdef _MSC_VER
+    fp = GetProcAddress(fmu->dllHandle, name);
+#else
+    fp = dlsym(fmu->dllHandle, name);
+#endif
+    if (!fp) {
+        printf ("warning: Function %s not found in dll\n", name);
+        *s = 0; // mark dll load as 'failed'        
+    }
+    return fp;
+}
+
+// Load the given dll and set function pointers in fmu
+// Return 0 to indicate failure
+static int loadDll(const char* dllPath, FMU *fmu) {
+    int s = 1;
+#ifdef _MSC_VER
+    HANDLE h = LoadLibraryEx(dllPath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
+    if (!h) {
+        int error = GetLastError();
+        printf("error %d: Could not load %s\n", error, dllPath);
+        return 0; // failure
+    }
+    fmu->dllHandle = h;
+#else
+    void* h = dlopen(dllPath, RTLD_LAZY);
+    if (!h) {
+        char* error = dlerror();
+        printf("error %s: Could not load %s\n", error, dllPath);
+        return 0; // failure
+    }
+    fmu->dllHandle = h;
+#endif
+
+#ifdef FMI_COSIMULATION   
+    fmu->getTypesPlatform        = (fGetTypesPlatform)   getAdr(&s, fmu, "fmiGetTypesPlatform");
+    if (s==0) { 
+        s = 1; // work around bug for FMUs exported using Dymola 2012 and SimulationX 3.x
+        fmu->getTypesPlatform    = (fGetTypesPlatform)   getAdr(&s, fmu, "fmiGetModelTypesPlatform");
+        if (s==1) printf("  using fmiGetModelTypesPlatform instead\n", dllPath);
+    }
+    fmu->instantiateSlave        = (fInstantiateSlave)   getAdr(&s, fmu, "fmiInstantiateSlave");
+    fmu->initializeSlave         = (fInitializeSlave)    getAdr(&s, fmu, "fmiInitializeSlave");    
+    fmu->terminateSlave          = (fTerminateSlave)     getAdr(&s, fmu, "fmiTerminateSlave");
+    fmu->resetSlave              = (fResetSlave)         getAdr(&s, fmu, "fmiResetSlave");
+    fmu->freeSlaveInstance       = (fFreeSlaveInstance)  getAdr(&s, fmu, "fmiFreeSlaveInstance");
+    fmu->setRealInputDerivatives = (fSetRealInputDerivatives) getAdr(&s, fmu, "fmiSetRealInputDerivatives");
+    fmu->getRealOutputDerivatives = (fGetRealOutputDerivatives) getAdr(&s, fmu, "fmiGetRealOutputDerivatives");
+    fmu->cancelStep              = (fCancelStep)         getAdr(&s, fmu, "fmiCancelStep");
+    fmu->doStep                  = (fDoStep)             getAdr(&s, fmu, "fmiDoStep");
+    // SimulationX 3.4 and 3.5 do not yet export getStatus and getXStatus: do not count this as failure here
+    fmu->getStatus               = (fGetStatus)          getAdr(&x, fmu, "fmiGetStatus");
+    fmu->getRealStatus           = (fGetRealStatus)      getAdr(&x, fmu, "fmiGetRealStatus");
+    fmu->getIntegerStatus        = (fGetIntegerStatus)   getAdr(&x, fmu, "fmiGetIntegerStatus");
+    fmu->getBooleanStatus        = (fGetBooleanStatus)   getAdr(&x, fmu, "fmiGetBooleanStatus");
+    fmu->getStringStatus         = (fGetStringStatus)    getAdr(&x, fmu, "fmiGetStringStatus");    
+
+#else // FMI for Model Exchange 1.0
+    fmu->getModelTypesPlatform   = (fGetModelTypesPlatform) getAdr(&s, fmu, "fmiGetModelTypesPlatform");
+    fmu->instantiateModel        = (fInstantiateModel)   getAdr(&s, fmu, "fmiInstantiateModel");
+    fmu->freeModelInstance       = (fFreeModelInstance)  getAdr(&s, fmu, "fmiFreeModelInstance");
+    fmu->setTime                 = (fSetTime)            getAdr(&s, fmu, "fmiSetTime");
+    fmu->setContinuousStates     = (fSetContinuousStates)getAdr(&s, fmu, "fmiSetContinuousStates");
+    fmu->completedIntegratorStep = (fCompletedIntegratorStep)getAdr(&s, fmu, "fmiCompletedIntegratorStep");
+    fmu->initialize              = (fInitialize)         getAdr(&s, fmu, "fmiInitialize");
+    fmu->getDerivatives          = (fGetDerivatives)     getAdr(&s, fmu, "fmiGetDerivatives");
+    fmu->getEventIndicators      = (fGetEventIndicators) getAdr(&s, fmu, "fmiGetEventIndicators");
+    fmu->eventUpdate             = (fEventUpdate)        getAdr(&s, fmu, "fmiEventUpdate");
+    fmu->getContinuousStates     = (fGetContinuousStates)getAdr(&s, fmu, "fmiGetContinuousStates");
+    fmu->getNominalContinuousStates = (fGetNominalContinuousStates)getAdr(&s, fmu, "fmiGetNominalContinuousStates");
+    fmu->getStateValueReferences = (fGetStateValueReferences)getAdr(&s, fmu, "fmiGetStateValueReferences");
+    fmu->terminate               = (fTerminate)          getAdr(&s, fmu, "fmiTerminate");
+#endif 
+    fmu->getVersion              = (fGetVersion)         getAdr(&s, fmu, "fmiGetVersion");
+    fmu->setDebugLogging         = (fSetDebugLogging)    getAdr(&s, fmu, "fmiSetDebugLogging");
+    fmu->setReal                 = (fSetReal)            getAdr(&s, fmu, "fmiSetReal");
+    fmu->setInteger              = (fSetInteger)         getAdr(&s, fmu, "fmiSetInteger");
+    fmu->setBoolean              = (fSetBoolean)         getAdr(&s, fmu, "fmiSetBoolean");
+    fmu->setString               = (fSetString)          getAdr(&s, fmu, "fmiSetString");
+    fmu->getReal                 = (fGetReal)            getAdr(&s, fmu, "fmiGetReal");
+    fmu->getInteger              = (fGetInteger)         getAdr(&s, fmu, "fmiGetInteger");
+    fmu->getBoolean              = (fGetBoolean)         getAdr(&s, fmu, "fmiGetBoolean");
+    fmu->getString               = (fGetString)          getAdr(&s, fmu, "fmiGetString");
+    return s; 
+}
+
+/*static void printModelDescription(ModelDescription* md){
+    Element* e = (Element*)md;  
+    int i;
+    printf("%s\n", elmNames[e->type]);
+    for (i=0; i<e->n; i+=2) 
+        printf("  %s=%s\n", e->attributes[i], e->attributes[i+1]);
+#ifdef FMI_COSIMULATION   
+    if (!md->cosimulation) {
+        printf("error: No Implementation element found in model description. This FMU is not for Co-Simulation.\n");
+        exit(EXIT_FAILURE);
+    }
+    e = md->cosimulation->capabilities;
+    printf("%s\n", elmNames[e->type]);
+    for (i=0; i<e->n; i+=2) 
+        printf("  %s=%s\n", e->attributes[i], e->attributes[i+1]);
+#endif // FMI_COSIMULATION  
+}
+*/
+
+/*
+ * return: 1 for successful laod or number for error.
+ * -1. FMU path not found
+ * -2. Unzip failed
+ * -3. Loading model description failed
+ * -4. FMU dll load failed
+ */
+/*
+int loadFMU(FMU *fmu, const char* fmuFileName, const char* tmpPath) {
+    char* fmuPath;
+    char* xmlPath;
+    char* dllPath;
+       unsigned old_clock = clock();
+       unsigned current_clock = 0;//will be assigned later
+    
+    // get absolute path to FMU, NULL if not found
+    fmuPath = getFmuPath(fmuFileName);
+    if (!fmuPath) return -1; // path not found
+
+    // unzip the FMU to the tmpPath directory
+    if (unzip(fmuPath, tmpPath)) return -2; // unzip failed
+
+    // parse tmpPath\modelDescription.xml
+    xmlPath = calloc(sizeof(char), strlen(tmpPath) + strlen(XML_FILE) + 1);
+    sprintf(xmlPath, "%s%s", tmpPath, XML_FILE);
+    fmu->modelDescription = parse(xmlPath);
+    free(xmlPath);
+    if (!fmu->modelDescription) return -3; // loading model description failed
+
+       // printModelDescription(fmu.modelDescription);
+       // fflush(stdout);
+
+    // load the FMU dll
+    dllPath = calloc(sizeof(char), strlen(tmpPath) + strlen(DLL_DIR) 
+            + strlen( getModelIdentifier(fmu->modelDescription)) +  strlen(".dll") + 1);
+    sprintf(dllPath,"%s%s%s.dll", tmpPath, DLL_DIR, getModelIdentifier(fmu->modelDescription));
+    if (!loadDll(dllPath, fmu)) return -4; // loading dll failed
+
+    free(dllPath);
+    free(fmuPath);
+
+       return 1;
+}
+*/
+
+static void doubleToCommaString(char* buffer, double r){
+    char* comma;
+    sprintf(buffer, "%.16g", r);
+    comma = strchr(buffer, '.');
+    if (comma) *comma = ',';
+}
+
+// output time and all non-alias variables in CSV format
+// if separator is ',', columns are separated by ',' and '.' is used for floating-point numbers.
+// otherwise, the given separator (e.g. ';' or '\t') is to separate columns, and ',' is used 
+// as decimal dot in floating-point numbers.
+/*
+void outputRow(FMU *fmu, fmiComponent c, double time, FILE* file, char separator, boolean header) {
+    int k;
+    fmiReal r;
+    fmiInteger i;
+    fmiBoolean b;
+    fmiString s;
+    fmiValueReference vr;
+    ScalarVariable** vars = fmu->modelDescription->modelVariables;
+    char buffer[32];
+    
+    // print first column
+    if (header) 
+        fprintf(file, "time"); 
+    else {
+        if (separator==',') 
+            fprintf(file, "%.16g", time);
+        else {
+            // separator is e.g. ';' or '\t'
+            doubleToCommaString(buffer, time);
+            fprintf(file, "%s", buffer);       
+        }
+    }
+    
+    // print all other columns
+    for (k=0; vars[k]; k++) {
+        ScalarVariable* sv = vars[k];
+        if (getAlias(sv)!=enu_noAlias) continue;
+        if (header) {
+            // output names only
+            if (separator==',') {
+                // treat array element, e.g. print a[1, 2] as a[1.2]
+                char* s = getName(sv);
+                fprintf(file, "%c", separator);
+                while (*s) {
+                   if (*s!=' ') fprintf(file, "%c", *s==',' ? '.' : *s);
+                   s++;
+                }
+             }
+            else
+                fprintf(file, "%c%s", separator, getName(sv));
+        }
+        else {
+            // output values
+            vr = getValueReference(sv);
+            switch (sv->typeSpec->type){
+                case elm_Real:
+                    fmu->getReal(c, &vr, 1, &r);
+                    if (separator==',') 
+                        fprintf(file, ",%.16g", r);
+                    else {
+                        // separator is e.g. ';' or '\t'
+                        doubleToCommaString(buffer, r);
+                        fprintf(file, "%c%s", separator, buffer);       
+                    }
+                    break;
+                case elm_Integer:
+                case elm_Enumeration:
+                    fmu->getInteger(c, &vr, 1, &i);
+                    fprintf(file, "%c%d", separator, i);
+                    break;
+                case elm_Boolean:
+                    fmu->getBoolean(c, &vr, 1, &b);
+                    fprintf(file, "%c%d", separator, b);
+                    break;
+                case elm_String:
+                    fmu->getString(c, &vr, 1, &s);
+                    fprintf(file, "%c%s", separator, s);
+                    break;
+                default: 
+                    fprintf(file, "%cNoValueForType=%d", separator,sv->typeSpec->type);
+            }
+        }
+    } // for
+    
+    // terminate this row
+    fprintf(file, "\n"); 
+}
+*/
+
+static const char* fmiStatusToString(fmiStatus status){
+    switch (status){
+        case fmiOK:      return "ok";
+        case fmiWarning: return "warning";
+        case fmiDiscard: return "discard";
+        case fmiError:   return "error";
+        case fmiFatal:   return "fatal";
+#ifdef FMI_COSIMULATION
+        case fmiPending: return "fmiPending";
+#endif
+        default:         return "?";
+    }
+}
+
+// search a fmu for the given variable
+// return NULL if not found or vr = fmiUndefinedValueReference
+static ScalarVariable* getSV(FMU* fmu, char type, fmiValueReference vr) {
+    int i;
+    Elm tp;
+    ScalarVariable** vars = fmu->modelDescription->modelVariables;
+    if (vr==fmiUndefinedValueReference) return NULL;
+    switch (type) {
+        case 'r': tp = elm_Real;    break;
+        case 'i': tp = elm_Integer; break;
+        case 'b': tp = elm_Boolean; break;
+        case 's': tp = elm_String;  break;                
+    }
+    for (i=0; vars[i]; i++) {
+        ScalarVariable* sv = vars[i];
+        if (vr==getValueReference(sv) && tp==sv->typeSpec->type) 
+            return sv;
+    }
+    return NULL;
+}
+
+// replace e.g. #r1365# by variable name and ## by # in message
+// copies the result to buffer
+static void replaceRefsInMessage(const char* msg, char* buffer, int nBuffer, FMU* fmu){
+    int i=0; // position in msg
+    int k=0; // position in buffer
+    int n;
+    char c = msg[i];
+    while (c!='\0' && k < nBuffer) {
+        if (c!='#') {
+            buffer[k++]=c;
+            i++;
+            c = msg[i];
+        }
+        else {
+            char* end = strchr((char*)(msg+i+1), '#');
+            if (!end) {
+                printf("unmatched '#' in '%s'\n", msg);
+                buffer[k++]='#';
+                break;
+            }
+            n = end - (msg+i);
+            if (n==1) {
+                // ## detected, output #
+                buffer[k++]='#';
+                i += 2;
+                c = msg[i];
+            }
+            else {
+                char type = msg[i+1]; // one of ribs
+                fmiValueReference vr;
+                int nvr = sscanf(msg+i+2, "%u", &vr);
+                if (nvr==1) {
+                    // vr of type detected, e.g. #r12#
+                    ScalarVariable* sv = getSV(fmu, type, vr);
+                    const char* name = sv ? getName(sv) : "?";
+                    sprintf(buffer+k, "%s", name);
+                    k += strlen(name);
+                    i += (n+1);
+                    c = msg[i]; 
+                }
+                else {
+                    // could not parse the number
+                    printf("illegal value reference at position %d in '%s'\n", i+2, msg);
+                    buffer[k++]='#';
+                    break;
+                }
+            }
+        }
+    } // while
+    buffer[k] = '\0';
+}
+
+#define MAX_MSG_SIZE 1000
+void fmuLogger(FMU *fmu, fmiComponent c, fmiString instanceName, fmiStatus status,
+               fmiString category, fmiString message, ...) {
+    char msg[MAX_MSG_SIZE];
+//    char* copy;
+    va_list argp;
+
+    // replace C format strings
+    va_start(argp, message);
+    vsprintf(msg, message, argp);
+    va_end(argp);
+
+    // replace e.g. ## and #r12#  
+//    copy = strdup(msg);
+//    replaceRefsInMessage(copy, msg, MAX_MSG_SIZE, fmu);
+//    free(copy);
+    
+    // print the final message
+    if (!instanceName) instanceName = "?";
+    if (!category) category = "?";
+    //printf("%s %s (%s): %s\n", fmiStatusToString(status), instanceName, category, msg);
+       printf("%s\n", message);
+}
+
+int error(const char* message){
+    printf("%s\n", message);
+    return 0;
+}
+
+void parseArguments(int argc, char *argv[], char** fmuFileName, double* tEnd, double* h, int* loggingOn, char* csv_separator) {
+    // parse command line arguments
+    if (argc>1) {
+        *fmuFileName = argv[1];
+    }
+    else {
+        printf("error: no fmu file\n");
+        printHelp(argv[0]);
+        exit(EXIT_FAILURE);
+    }
+    if (argc>2) {
+        if (sscanf(argv[2],"%lf", tEnd) != 1) {
+            printf("error: The given end time (%s) is not a number\n", argv[2]);
+            exit(EXIT_FAILURE);
+        }
+    }
+    if (argc>3) {
+        if (sscanf(argv[3],"%lf", h) != 1) {
+            printf("error: The given stepsize (%s) is not a number\n", argv[3]);
+            exit(EXIT_FAILURE);
+        }
+    }
+    if (argc>4) {
+        if (sscanf(argv[4],"%d", loggingOn) != 1 || *loggingOn<0 || *loggingOn>1) {
+            printf("error: The given logging flag (%s) is not boolean\n", argv[4]);
+            exit(EXIT_FAILURE);
+        }
+    }
+    if (argc>5) {
+        if (strlen(argv[5]) != 1) {
+            printf("error: The given CSV separator char (%s) is not valid\n", argv[5]);
+            exit(EXIT_FAILURE);
+        }
+        switch (argv[5][0]) {
+            case 'c': *csv_separator = ','; break; // comma
+            case 's': *csv_separator = ';'; break; // semicolon
+            default:  *csv_separator = argv[5][0]; break; // any other char
+        }
+    }
+    if (argc>6) {
+        printf("warning: Ignoring %d additional arguments: %s ...\n", argc-6, argv[6]);
+        printHelp(argv[0]);
+    }
+}
+
+void printHelp(const char* fmusim) {
+    printf("command syntax: %s <model.fmu> <tEnd> <h> <loggingOn> <csv separator>\n", fmusim);
+    printf("   <model.fmu> .... path to FMU, relative to current dir or absolute, required\n");
+    printf("   <tEnd> ......... end  time of simulation, optional, defaults to 1.0 sec\n");
+    printf("   <h> ............ step size of simulation, optional, defaults to 0.1 sec\n");
+    printf("   <loggingOn> .... 1 to activate logging,   optional, defaults to 0\n");
+    printf("   <csv separator>. separator in csv file,   optional, c for ';', s for';', defaults to c\n");
+}
+
index fd14ee682242200c9f9e5e42cab3fb0a0aad96f9..f702ac6cb764940082d2d3efa6bcc6b7836d123a 100644 (file)
Binary files a/org.simantics.fmil.win32/libraries/FMUSimulator.dll and b/org.simantics.fmil.win32/libraries/FMUSimulator.dll differ
index fa599b6cd70bb5587650acb1f1ce6f90353e5735..7eb972d4319ac901a3f73da09669475959d941da 100644 (file)
Binary files a/org.simantics.fmil.win32/libraries/fmilib_shared.dll and b/org.simantics.fmil.win32/libraries/fmilib_shared.dll differ
index 6569466dae67c51590f6e893fc2d75892a615d25..edd1487426ac7cdce14972933663b3b122ba4c62 100644 (file)
Binary files a/org.simantics.fmil.win32/libraries/fmu1_dll_cs.dll and b/org.simantics.fmil.win32/libraries/fmu1_dll_cs.dll differ
index 1eb1f6978124c60e341922e33f54b660786fe3eb..2f80629ba5073848eebd72354daf756fdc6c12b1 100644 (file)
Binary files a/org.simantics.fmil.win32/libraries/fmu1_dll_me.dll and b/org.simantics.fmil.win32/libraries/fmu1_dll_me.dll differ
index 46fa6200b01af5749e9029df8676c00ec9ae11d6..eb847c62d197992dd620b67929328daffb939136 100644 (file)
Binary files a/org.simantics.fmil.win32/libraries/fmu2_dll_cs.dll and b/org.simantics.fmil.win32/libraries/fmu2_dll_cs.dll differ
index da76130fbd9a476711a356edd145ebf78f926cd0..7668516d03f44b49709dd6a53573a99696296a99 100644 (file)
Binary files a/org.simantics.fmil.win32/libraries/fmu2_dll_me.dll and b/org.simantics.fmil.win32/libraries/fmu2_dll_me.dll differ
index 53f0749f239569499f4685209b41b39b4fe42c5c..b4e27a91b30f054f9f14c10d3cfe924b4bd8d551 100644 (file)
Binary files a/org.simantics.fmil.win64/libraries/FMUSimulator.dll and b/org.simantics.fmil.win64/libraries/FMUSimulator.dll differ
index f33a53d677a2e233532045286dfc0a80b7be544e..5870f10b503b9d047131ec0d24986301766e85c0 100644 (file)
Binary files a/org.simantics.fmil.win64/libraries/fmilib_shared.dll and b/org.simantics.fmil.win64/libraries/fmilib_shared.dll differ
index ddfa7c36538138b482c89bc18bdc1e1a42185657..88ec2245c1a792aaf62a6e4aca1229b985809acf 100644 (file)
Binary files a/org.simantics.fmil.win64/libraries/fmu1_dll_cs.dll and b/org.simantics.fmil.win64/libraries/fmu1_dll_cs.dll differ
index 432673b2fb0c29938ca4f9d7aed7f9e0352426ca..bbdb6d9ba0a63192b1b0131cf82869d74826f14d 100644 (file)
Binary files a/org.simantics.fmil.win64/libraries/fmu1_dll_me.dll and b/org.simantics.fmil.win64/libraries/fmu1_dll_me.dll differ
index d8a75075cd0e53001433acd05f53285519b895f2..9f28b07677d02e145041bf81acddfe8b6c5fa9a7 100644 (file)
Binary files a/org.simantics.fmil.win64/libraries/fmu2_dll_cs.dll and b/org.simantics.fmil.win64/libraries/fmu2_dll_cs.dll differ
index f4225cf5661aee488a488f060f316b0ab00d3e2f..bd3b0e345c2ac91d45d41c1bc7672601aa8ce9a3 100644 (file)
Binary files a/org.simantics.fmil.win64/libraries/fmu2_dll_me.dll and b/org.simantics.fmil.win64/libraries/fmu2_dll_me.dll differ