]> gerrit.simantics Code Review - simantics/fmil.git/blob - org.simantics.fmil.core/native/FMILibrary/src/Import/src/FMI1/fmi1_import_capi.c
Add FMILibrary-2.0.3 to org.simantics.fmil.core\native.
[simantics/fmil.git] / org.simantics.fmil.core / native / FMILibrary / src / Import / src / FMI1 / fmi1_import_capi.c
1 /*
2     Copyright (C) 2012 Modelon AB
3
4     This program is free software: you can redistribute it and/or modify
5     it under the terms of the BSD style license.
6
7      This program is distributed in the hope that it will be useful,
8     but WITHOUT ANY WARRANTY; without even the implied warranty of
9     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10     FMILIB_License.txt file for more details.
11
12     You should have received a copy of the FMILIB_License.txt file
13     along with this program. If not, contact Modelon AB <http://www.modelon.com>.
14 */
15
16 #ifdef __cplusplus
17 extern "C" {
18 #endif
19
20 #include <stdio.h>
21 #include <errno.h>
22 #include <FMI1/fmi1_types.h>
23 #include <FMI1/fmi1_functions.h>
24 #include <FMI1/fmi1_enums.h>\r
25 #include <FMI1/fmi1_capi.h>
26 #include <FMI/fmi_util.h>
27 #include "fmi1_import_impl.h"
28
29 static const char * module = "FMILIB";
30
31 /* Load and destroy functions */
32 jm_status_enu_t fmi1_import_create_dllfmu(fmi1_import_t* fmu, fmi1_callback_functions_t callBackFunctions, int registerGlobally) {
33
34         char curDir[FILENAME_MAX + 2];
35         char* dllDirPath = 0;
36         char* dllFileName = 0;
37         const char* modelIdentifier;
38         fmi1_fmu_kind_enu_t standard;
39
40         if (fmu == NULL) {
41                 assert(0);
42                 return jm_status_error;
43         }
44
45         if(fmu -> capi) {
46                 jm_log_warning(fmu->callbacks, module, "FMU binary is already loaded"); 
47                 return jm_status_success;
48         }
49
50         standard = fmi1_import_get_fmu_kind(fmu);
51
52         modelIdentifier = fmi1_import_get_model_identifier(fmu);
53         if (modelIdentifier == NULL) {
54                 return jm_status_error;
55         }
56
57         if( jm_portability_get_current_working_directory(curDir, FILENAME_MAX+1) != jm_status_success) {
58                 jm_log_warning(fmu->callbacks, module, "Could not get current working directory (%s)", strerror(errno));
59                 curDir[0] = 0;
60         };
61
62         dllDirPath = fmi_construct_dll_dir_name(fmu->callbacks, fmu->dirPath);
63         dllFileName = fmi_construct_dll_file_name(fmu->callbacks, dllDirPath, modelIdentifier);
64
65         if (!dllDirPath ||!dllFileName) {
66                 fmu->callbacks->free(dllDirPath);
67                 return jm_status_error;
68         }
69
70         if(jm_portability_set_current_working_directory(dllDirPath) != jm_status_success) {
71                 jm_log_fatal(fmu->callbacks, module, "Could not change to the DLL directory %s", dllDirPath);
72                 if(ENOENT == errno)
73                         jm_log_fatal(fmu->callbacks, module, "The FMU contains no binary for this platform.");
74                 else
75                         jm_log_fatal(fmu->callbacks, module, "System error: %s", strerror(errno));
76         }
77         else {
78                 /* Allocate memory for the C-API struct */
79                 fmu -> capi = fmi1_capi_create_dllfmu(fmu->callbacks, dllFileName, modelIdentifier, callBackFunctions, standard);
80         }
81
82
83         /* Load the DLL handle */
84         if (fmu -> capi) {
85                 jm_log_info(fmu->callbacks, module, \r
86                         "Loading '" FMI_PLATFORM "' binary with '%s' platform types", fmi1_get_platform() );\r
87
88                 if(fmi1_capi_load_dll(fmu -> capi) == jm_status_error) {                
89                         fmi1_capi_destroy_dllfmu(fmu -> capi);
90                         fmu -> capi = NULL;
91                 }
92         }
93
94         if(curDir[0] && (jm_portability_set_current_working_directory(curDir) != jm_status_success)) {
95                 jm_log_error(fmu->callbacks, module, "Could not restore current working directory (%s)", strerror(errno));
96         }
97
98         fmu->callbacks->free((jm_voidp)dllDirPath);
99         fmu->callbacks->free((jm_voidp)dllFileName);
100
101         if (fmu -> capi == NULL) {
102                 return jm_status_error;
103         }
104
105
106         /* Load the DLL functions */
107         if (fmi1_capi_load_fcn(fmu -> capi) == jm_status_error) {
108                 fmi1_capi_free_dll(fmu -> capi);                        
109                 fmi1_capi_destroy_dllfmu(fmu -> capi);
110                 fmu -> capi = NULL;
111                 return jm_status_error;
112         }
113         jm_log_verbose(fmu->callbacks, module, "Successfully loaded all the interface functions"); 
114
115         if (registerGlobally) {
116                 fmu->registerGlobally = 1;
117                 if(!fmi1_import_active_fmu) {
118                         fmi1_import_active_fmu_store_callbacks = *fmu->callbacks;
119                         fmi1_import_active_fmu_store_callbacks.context = 0;
120                         jm_vector_init(jm_voidp)(&fmi1_import_active_fmu_store,0, &fmi1_import_active_fmu_store_callbacks);
121                         fmi1_import_active_fmu = &fmi1_import_active_fmu_store;
122                         jm_log_debug(fmu->callbacks, module, "Created an empty active fmu list");
123                 }
124                 jm_vector_push_back(jm_voidp)(fmi1_import_active_fmu, fmu);
125                 jm_log_debug(fmu->callbacks, module, "Registrered active fmu(%p)", fmu);
126         }
127
128         return jm_status_success;
129 }
130
131 void fmi1_import_set_debug_mode(fmi1_import_t* fmu, int mode) {
132         if (fmu == NULL) {
133                 return;
134         }
135         fmi1_capi_set_debug_mode(fmu->capi, mode);
136 }
137
138 void fmi1_import_destroy_dllfmu(fmi1_import_t* fmu) {
139         
140         if (fmu == NULL) {
141                 return;
142         }
143
144         
145         if(fmu -> capi) {
146                 jm_log_verbose(fmu->callbacks, module, "Releasing FMU CAPI interface"); 
147
148                 /* Free DLL handle */
149                 fmi1_capi_free_dll(fmu -> capi);
150
151                 /* Destroy the C-API struct */
152                 fmi1_capi_destroy_dllfmu(fmu -> capi);
153
154                 if(fmu->registerGlobally && fmi1_import_active_fmu) {
155                         size_t index;
156                         size_t nFmu;
157
158                         index = jm_vector_find_index(jm_voidp)(fmi1_import_active_fmu, (void**)&fmu, jm_compare_voidp);
159                         nFmu = jm_vector_get_size(jm_voidp)(fmi1_import_active_fmu);
160                         if(index < nFmu) {
161                                 jm_vector_remove_item(jm_voidp)(fmi1_import_active_fmu,index);
162                                 jm_log_debug(fmu->callbacks, module, "Unregistrered active fmu(%p)", fmu);
163                                 if(nFmu == 1) {
164                                         jm_vector_free_data(jm_voidp)(fmi1_import_active_fmu);
165                                         fmi1_import_active_fmu = 0;
166                                         jm_log_debug(fmu->callbacks, module, "Freed active fmu list");
167                                 }
168                         }
169                         fmu->registerGlobally = 0;
170                 }
171
172                 fmu -> capi = NULL;
173         }
174         else {
175                 assert(fmu->registerGlobally == 0);
176         }
177 }
178
179 /* FMI 1.0 Common functions */
180 const char* fmi1_import_get_version(fmi1_import_t* fmu) {
181         if(!fmu->capi) {
182                 jm_log_error(fmu->callbacks, module,"FMU CAPI is not loaded");
183                 return 0;
184         }
185         return fmi1_capi_get_version(fmu -> capi);
186 }
187
188 fmi1_status_t fmi1_import_set_debug_logging(fmi1_import_t* fmu, fmi1_boolean_t loggingOn) {
189         if(!fmu->capi) {
190                 jm_log_error(fmu->callbacks, module,"FMU CAPI is not loaded");
191                 return fmi1_status_fatal;
192         }
193         return fmi1_capi_set_debug_logging(fmu -> capi, loggingOn);
194 }
195
196 fmi1_status_t fmi1_import_set_real(fmi1_import_t* fmu, const fmi1_value_reference_t vr[], size_t nvr, const fmi1_real_t    value[]) {
197         return fmi1_capi_set_real(fmu -> capi, vr, nvr, value);
198 }
199
200 fmi1_status_t fmi1_import_set_integer(fmi1_import_t* fmu, const fmi1_value_reference_t vr[], size_t nvr, const fmi1_integer_t value[]) {
201         return fmi1_capi_set_integer(fmu -> capi, vr, nvr, value);
202 }
203
204 fmi1_status_t fmi1_import_set_boolean(fmi1_import_t* fmu, const fmi1_value_reference_t vr[], size_t nvr, const fmi1_boolean_t value[]) {
205         return fmi1_capi_set_boolean(fmu -> capi, vr, nvr, value);
206 }
207
208 fmi1_status_t fmi1_import_set_string(fmi1_import_t* fmu, const fmi1_value_reference_t vr[], size_t nvr, const fmi1_string_t  value[]) {
209         return fmi1_capi_set_string(fmu -> capi, vr, nvr, value);
210 }
211
212 fmi1_status_t fmi1_import_get_real(fmi1_import_t* fmu, const fmi1_value_reference_t vr[], size_t nvr, fmi1_real_t    value[]) {
213         return fmi1_capi_get_real(fmu -> capi, vr, nvr, value);
214 }
215
216 fmi1_status_t fmi1_import_get_integer(fmi1_import_t* fmu, const fmi1_value_reference_t vr[], size_t nvr, fmi1_integer_t value[]) {
217         return fmi1_capi_get_integer(fmu -> capi, vr, nvr, value);
218 }
219
220 fmi1_status_t fmi1_import_get_boolean(fmi1_import_t* fmu, const fmi1_value_reference_t vr[], size_t nvr, fmi1_boolean_t value[]) {
221         return fmi1_capi_get_boolean(fmu -> capi, vr, nvr, value);
222 }
223
224 fmi1_status_t fmi1_import_get_string(fmi1_import_t* fmu, const fmi1_value_reference_t vr[], size_t nvr, fmi1_string_t  value[]) {
225         return fmi1_capi_get_string(fmu -> capi, vr, nvr, value);
226 }
227
228
229 /* FMI 1.0 ME functions */
230 const char* fmi1_import_get_model_types_platform(fmi1_import_t* fmu) {
231         return fmi1_capi_get_model_types_platform(fmu -> capi);
232 }
233
234 jm_status_enu_t fmi1_import_instantiate_model(fmi1_import_t* fmu, fmi1_string_t instanceName) {
235         fmi1_string_t GUID = fmi1_import_get_GUID(fmu);
236         fmi1_boolean_t loggingOn = (fmu->callbacks->log_level > jm_log_level_nothing);
237         fmi1_component_t c = fmi1_capi_instantiate_model(fmu -> capi, instanceName, GUID, loggingOn);
238         if (c == NULL) {
239                 return jm_status_error;
240         } else {
241                 return jm_status_success;
242         }
243 }
244
245 void fmi1_import_free_model_instance(fmi1_import_t* fmu) {
246         fmi1_capi_free_model_instance(fmu -> capi);
247 }
248
249 fmi1_status_t fmi1_import_set_time(fmi1_import_t* fmu, fmi1_real_t time) {
250         return fmi1_capi_set_time(fmu -> capi, time);
251 }
252
253 fmi1_status_t fmi1_import_set_continuous_states(fmi1_import_t* fmu, const fmi1_real_t x[], size_t nx) {
254         return fmi1_capi_set_continuous_states(fmu -> capi, x, nx);
255 }
256
257 fmi1_status_t fmi1_import_completed_integrator_step(fmi1_import_t* fmu, fmi1_boolean_t* callEventUpdate) {
258         return fmi1_capi_completed_integrator_step(fmu -> capi, callEventUpdate);
259 }
260
261 fmi1_status_t fmi1_import_initialize(fmi1_import_t* fmu, fmi1_boolean_t toleranceControlled, fmi1_real_t relativeTolerance, fmi1_event_info_t* eventInfo) {
262         return fmi1_capi_initialize(fmu -> capi, toleranceControlled, relativeTolerance, eventInfo);
263 }
264
265 fmi1_status_t fmi1_import_get_derivatives(fmi1_import_t* fmu, fmi1_real_t derivatives[], size_t nx) {
266         return fmi1_capi_get_derivatives(fmu -> capi, derivatives, nx);
267 }
268
269 fmi1_status_t fmi1_import_get_event_indicators(fmi1_import_t* fmu, fmi1_real_t eventIndicators[], size_t ni) {
270         return fmi1_capi_get_event_indicators(fmu -> capi, eventIndicators, ni);
271 }
272
273 fmi1_status_t fmi1_import_eventUpdate(fmi1_import_t* fmu, fmi1_boolean_t intermediateResults, fmi1_event_info_t* eventInfo) {
274         return fmi1_capi_eventUpdate(fmu -> capi, intermediateResults, eventInfo);
275 }
276
277 fmi1_status_t fmi1_import_get_continuous_states(fmi1_import_t* fmu, fmi1_real_t states[], size_t nx) {
278         return fmi1_capi_get_continuous_states(fmu -> capi, states, nx);
279 }
280
281 fmi1_status_t fmi1_import_get_nominal_continuous_states(fmi1_import_t* fmu, fmi1_real_t x_nominal[], size_t nx) {
282         return fmi1_capi_get_nominal_continuous_states(fmu -> capi, x_nominal, nx);
283 }
284
285 fmi1_status_t fmi1_import_get_state_value_references(fmi1_import_t* fmu, fmi1_value_reference_t vrx[], size_t nx) {
286         return fmi1_capi_get_state_value_references(fmu -> capi, vrx, nx);
287 }
288
289 fmi1_status_t fmi1_import_terminate(fmi1_import_t* fmu) {
290         return fmi1_capi_terminate(fmu -> capi);
291 }
292
293
294 /* FMI 1.0 CS functions */
295 const char* fmi1_import_get_types_platform(fmi1_import_t* fmu) {
296         return fmi1_capi_get_types_platform(fmu -> capi);
297 }
298
299 jm_status_enu_t fmi1_import_instantiate_slave(fmi1_import_t* fmu, fmi1_string_t instanceName, fmi1_string_t fmuLocation, fmi1_string_t mimeType,
300                                                                                                                                  fmi1_real_t timeout, fmi1_boolean_t visible, fmi1_boolean_t interactive) {
301         fmi1_string_t fmuGUID = fmi1_import_get_GUID(fmu);
302         fmi1_boolean_t loggingOn = (fmu->callbacks->log_level > jm_log_level_nothing);
303         fmi1_component_t c;
304         if(!mimeType) mimeType = "application/x-fmu-sharedlibrary";
305         if(!fmuLocation) fmuLocation = fmu->location;
306         jm_log_verbose(fmu->callbacks, module, "Instantiating the slave with \n"\r
307                                         "\tFMU location ='%s'\n\tMIME type = '%s'", fmuLocation, mimeType);\r
308
309         c = fmi1_capi_instantiate_slave(fmu -> capi, instanceName, fmuGUID, fmuLocation, mimeType, timeout, visible, interactive, loggingOn);
310         if (c == NULL) {
311                 return jm_status_error;
312         } else {
313                 return jm_status_success;
314         }
315 }
316
317 fmi1_status_t fmi1_import_initialize_slave(fmi1_import_t* fmu, fmi1_real_t tStart, fmi1_boolean_t StopTimeDefined, fmi1_real_t tStop) {
318         return fmi1_capi_initialize_slave(fmu -> capi, tStart, StopTimeDefined, tStop);
319 }
320
321 fmi1_status_t fmi1_import_terminate_slave(fmi1_import_t* fmu) {
322         return fmi1_capi_terminate_slave(fmu -> capi);
323 }
324
325 fmi1_status_t fmi1_import_reset_slave(fmi1_import_t* fmu) {
326         return fmi1_capi_reset_slave(fmu -> capi);
327 }
328
329 void fmi1_import_free_slave_instance(fmi1_import_t* fmu) {
330         fmi1_capi_free_slave_instance(fmu -> capi);
331 }
332
333 fmi1_status_t fmi1_import_set_real_input_derivatives(fmi1_import_t* fmu, const fmi1_value_reference_t vr[], size_t nvr, const fmi1_integer_t order[], const  fmi1_real_t value[]) {
334         return fmi1_capi_set_real_input_derivatives(fmu -> capi, vr, nvr, order, value);
335 }
336                                                   
337 fmi1_status_t fmi1_import_get_real_output_derivatives(fmi1_import_t* fmu, const fmi1_value_reference_t vr[], size_t nvr, const fmi1_integer_t order[], fmi1_real_t value[]) {
338         return fmi1_capi_get_real_output_derivatives(fmu -> capi, vr, nvr, order, value);
339 }
340                                               
341 fmi1_status_t fmi1_import_cancel_step(fmi1_import_t* fmu) {
342         return fmi1_capi_cancel_step(fmu -> capi);
343 }
344
345 fmi1_status_t fmi1_import_do_step(fmi1_import_t* fmu, fmi1_real_t currentCommunicationPoint, fmi1_real_t communicationStepSize, fmi1_boolean_t newStep) {
346         return fmi1_capi_do_step(fmu -> capi, currentCommunicationPoint, communicationStepSize, newStep);
347 }
348
349 fmi1_status_t fmi1_import_get_status(fmi1_import_t* fmu, const fmi1_status_kind_t s, fmi1_status_t*  value) {
350         return fmi1_capi_get_status(fmu -> capi, s, value);
351 }
352
353 fmi1_status_t fmi1_import_get_real_status(fmi1_import_t* fmu, const fmi1_status_kind_t s, fmi1_real_t*    value) {
354         return fmi1_capi_get_real_status(fmu -> capi, s, value);
355 }
356
357 fmi1_status_t fmi1_import_get_integer_status(fmi1_import_t* fmu, const fmi1_status_kind_t s, fmi1_integer_t* value) {
358         return fmi1_capi_get_integer_status(fmu -> capi, s, value);
359 }
360
361 fmi1_status_t fmi1_import_get_boolean_status(fmi1_import_t* fmu, const fmi1_status_kind_t s, fmi1_boolean_t* value) {
362         return fmi1_capi_get_boolean_status(fmu -> capi, s, value);
363 }
364
365 fmi1_status_t fmi1_import_get_string_status(fmi1_import_t* fmu, const fmi1_status_kind_t s, fmi1_string_t*  value) {
366         return fmi1_capi_get_string_status(fmu -> capi, s, value);
367 }
368
369 #ifdef __cplusplus
370 }
371 #endif