Sorry I wasn't clear. The code is not the same. The old code relied on a
`fmuTemplate.h`and a `fmuTemplate.c` that I am trying to port to Nim.
>From all the functions and data models that I have ported so far, in this
>example the problem is on the `fmi2Instantiate` function. If I use the .c
>version it works, while the .nim one fails.
The C version is:
fmi2Component fmi2Instantiate(fmi2String instanceName, fmi2Type fmuType,
fmi2String fmuGUID,
fmi2String fmuResourceLocation, const
fmi2CallbackFunctions *functions,
fmi2Boolean visible, fmi2Boolean loggingOn) {
// ignoring arguments: fmuResourceLocation, visible
ModelInstance *comp;
if (!functions->logger) {
return NULL;
}
if (!functions->allocateMemory || !functions->freeMemory) {
functions->logger(functions->componentEnvironment, instanceName,
fmi2Error, "error",
"fmi2Instantiate: Missing callback function.");
return NULL;
}
if (!instanceName || strlen(instanceName) == 0) {
functions->logger(functions->componentEnvironment, "?", fmi2Error,
"error",
"fmi2Instantiate: Missing instance name.");
return NULL;
}
if (!fmuGUID || strlen(fmuGUID) == 0) {
functions->logger(functions->componentEnvironment, instanceName,
fmi2Error, "error",
"fmi2Instantiate: Missing GUID.");
return NULL;
}
if (strcmp(fmuGUID, MODEL_GUID)) {
functions->logger(functions->componentEnvironment, instanceName,
fmi2Error, "error",
"fmi2Instantiate: Wrong GUID %s. Expected %s.", fmuGUID,
MODEL_GUID);
return NULL;
}
comp = (ModelInstance *)functions->allocateMemory(1,
sizeof(ModelInstance));
if (comp) {
int i;
comp->r = (fmi2Real *) functions->allocateMemory(NUMBER_OF_REALS,
sizeof(fmi2Real));
comp->i = (fmi2Integer
*)functions->allocateMemory(NUMBER_OF_INTEGERS, sizeof(fmi2Integer));
comp->b = (fmi2Boolean
*)functions->allocateMemory(NUMBER_OF_BOOLEANS, sizeof(fmi2Boolean));
comp->s = (fmi2String *)
functions->allocateMemory(NUMBER_OF_STRINGS, sizeof(fmi2String));
comp->isPositive = (fmi2Boolean
*)functions->allocateMemory(NUMBER_OF_EVENT_INDICATORS,
sizeof(fmi2Boolean));
comp->instanceName = (char *)functions->allocateMemory(1 +
strlen(instanceName), sizeof(char));
comp->GUID = (char *)functions->allocateMemory(1 + strlen(fmuGUID),
sizeof(char));
// set all categories to on or off. fmi2SetDebugLogging should be
called to choose specific categories.
for (i = 0; i < NUMBER_OF_CATEGORIES; i++) {
comp->logCategories[i] = loggingOn;
}
}
if (!comp || !comp->r || !comp->i || !comp->b || !comp->s ||
!comp->isPositive
|| !comp->instanceName || !comp->GUID) {
functions->logger(functions->componentEnvironment, instanceName,
fmi2Error, "error",
"fmi2Instantiate: Out of memory.");
return NULL;
}
comp->time = 0; // overwrite in fmi2SetupExperiment, fmi2SetTime
strcpy((char *)comp->instanceName, (char *)instanceName);
comp->type = fmuType;
strcpy((char *)comp->GUID, (char *)fmuGUID);
comp->functions = functions;
comp->componentEnvironment = functions->componentEnvironment;
comp->loggingOn = loggingOn;
comp->state = modelInstantiated;
setStartValues(comp); // to be implemented by the includer of this file
comp->isDirtyValues = fmi2True; // because we just called setStartValues
comp->isNewEventIteration = fmi2False;
comp->eventInfo.newDiscreteStatesNeeded = fmi2False;
comp->eventInfo.terminateSimulation = fmi2False;
comp->eventInfo.nominalsOfContinuousStatesChanged = fmi2False;
comp->eventInfo.valuesOfContinuousStatesChanged = fmi2False;
comp->eventInfo.nextEventTimeDefined = fmi2False;
comp->eventInfo.nextEventTime = 0;
FILTERED_LOG(comp, fmi2OK, LOG_FMI_CALL, "fmi2Instantiate: GUID=%s",
fmuGUID)
return comp;
}
Run
The Nim version is:
proc fmi2Instantiate*( instanceName: fmi2String;
fmuType: fmi2Type;
fmuGUID: fmi2String;
fmuResourceLocation: fmi2String;
functions: fmi2CallbackFunctions; # <--- I suspect
of this
visible: fmi2Boolean;
loggingOn: fmi2Boolean): ModelInstance =
var comp:ModelInstance
echo functions.logger.isNil
echo functions.allocateMemory.isNil
#echo functions.allocateMemory.isNil
#[
# ignoring arguments: fmuResourceLocation, visible
if f.logger.isNil:
return nil
if f.allocateMemory.isNil or f.freeMemory.isNil:
f.logger( functions.componentEnvironment, instanceName, fmi2Error,
"error".fmi2String,
"fmi2Instantiate: Missing callback function.".fmi2String)
return nil
if instanceName.isNil or instanceName.len == 0:
f.logger( functions.componentEnvironment, "?", fmi2Error, "error",
"fmi2Instantiate: Missing instance name.")
return nil
if fmuGUID.isNil or fmuGUID.len == 0:
f.logger( functions.componentEnvironment, instanceName, fmi2Error,
"error",
"fmi2Instantiate: Missing GUID.")
return nil
]#
#[
if not ($(fmuGUID) == MODEL_GUID): #strcmp(fmuGUID, MODEL_GUID)) {
f.logger( functions.componentEnvironment, instanceName, fmi2Error,
"error",
fmt"fmi2Instantiate: Wrong GUID {$(fmuGUID)}. Expected
{MODEL_GUID}.")
return nil
]#
#comp = (ModelInstance *)functions.allocateMemory(1,
sizeof(ModelInstance));
# var comp = ModelInstance( time:0,
# instanceName:instanceName,
# `type`:fmuType,
# GUID: fmuGUID )
comp.time = 0
comp.instanceName = instanceName
comp.`type` = fmuType
comp.GUID = fmuGUID
comp.r = cast[typeof(comp.r)](realloc(comp.r, NUMBER_OF_REALS *
sizeof(fmi2Real)))
comp.i = cast[typeof(comp.i)](realloc(comp.i, NUMBER_OF_INTEGERS *
sizeof(fmi2Integer)))
comp.b = cast[typeof(comp.b)](realloc(comp.b, NUMBER_OF_BOOLEANS *
sizeof(fmi2Boolean)))
comp.s = cast[typeof(comp.s)](realloc(comp.s, NUMBER_OF_STRINGS *
sizeof(fmi2String)))
comp.isPositive =
cast[typeof(comp.isPositive)](realloc(comp.isPositive,
NUMBER_OF_EVENT_INDICATORS * sizeof(fmi2Boolean)))
for i in 0 ..< NUMBER_OF_CATEGORIES:
comp.logCategories[i] = loggingOn
#[
if not comp.isNil:
#[
comp.r = cast[typeof(comp.r)](realloc(comp.r, NUMBER_OF_REALS *
sizeof(fmi2Real)))
comp.i = cast[typeof(comp.i)](realloc(comp.i, NUMBER_OF_INTEGERS *
sizeof(fmi2Integer)))
comp.b = cast[typeof(comp.b)](realloc(comp.b, NUMBER_OF_BOOLEANS *
sizeof(fmi2Boolean)))
comp.s = cast[typeof(comp.s)](realloc(comp.s, NUMBER_OF_STRINGS *
sizeof(fmi2String)))
comp.isPositive =
cast[typeof(comp.isPositive)](realloc(comp.isPositive,
NUMBER_OF_EVENT_INDICATORS * sizeof(fmi2Boolean)))
]#
#comp.instanceName = (char *)functions.allocateMemory(1 +
strlen(instanceName), sizeof(char));
#comp.GUID = (char *)functions.allocateMemory(1 + strlen(fmuGUID),
sizeof(char));
# set all categories to on or off. fmi2SetDebugLogging should be
called to choose specific categories.
for i in 0 ..< NUMBER_OF_CATEGORIES:
comp.logCategories[i] = loggingOn
]#
#[
if comp.isNil or comp.r.isNil or comp.i.isNil or comp.b.isNil or
comp.s.isNil or comp.isPositive.isNil or
comp.instanceName.isNil or comp.GUID.isNil:
functions.logger(functions.componentEnvironment, instanceName,
fmi2Error, "error",
"fmi2Instantiate: Out of memory.")
return nil
]#
comp.functions = functions
comp.componentEnvironment = functions.componentEnvironment
comp.loggingOn = loggingOn
comp.state = modelInstantiated # State changed
setStartValues( comp ) # <------ to be implemented by the includer
of this file
comp.isDirtyValues = fmi2True # because we just called setStartValues
comp.isNewEventIteration = fmi2False
comp.eventInfo.newDiscreteStatesNeeded = fmi2False
comp.eventInfo.terminateSimulation = fmi2False
comp.eventInfo.nominalsOfContinuousStatesChanged = fmi2False
comp.eventInfo.valuesOfContinuousStatesChanged = fmi2False
comp.eventInfo.nextEventTimeDefined = fmi2False
comp.eventInfo.nextEventTime = 0
filteredLog( comp, fmi2OK, LOG_FMI_CALL, fmt"fmi2Instantiate:
GUID={$fmuGUID}")
return comp
Run
I suspect about the `functions: fmi2CallbackFunctions; ` argument, because the
following shows: `false`
echo functions.logger.isNil
echo functions.allocateMemory.isNil
Run