pythonfmu3 0.3.3__py3-none-any.whl → 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pythonfmu3/_version.py +1 -1
- pythonfmu3/builder.py +96 -24
- pythonfmu3/fmi3slave.py +80 -40
- pythonfmu3/modelexchange.py +17 -2
- pythonfmu3/osutil.py +34 -9
- pythonfmu3/pythonfmu-export/CMakeLists.txt +36 -4
- pythonfmu3/pythonfmu-export/generate_shim.py +88 -0
- pythonfmu3/pythonfmu-export/src/CMakeLists.txt +41 -13
- pythonfmu3/pythonfmu-export/src/cppfmu/cppfmu_common.hpp +3 -0
- pythonfmu3/pythonfmu-export/src/cppfmu/cppfmu_cs.cpp +20 -10
- pythonfmu3/pythonfmu-export/src/cppfmu/cppfmu_cs.hpp +20 -10
- pythonfmu3/pythonfmu-export/src/cppfmu/fmi_functions.cpp +16 -14
- pythonfmu3/pythonfmu-export/src/pythonfmu/PySlaveInstance.cpp +570 -570
- pythonfmu3/pythonfmu-export/src/pythonfmu/PySlaveInstance.hpp +30 -17
- pythonfmu3/pythonfmu-export/src/shim/fmi3_forwarders.cpp +612 -0
- pythonfmu3/pythonfmu-export/src/shim/shim_loader.cpp +157 -0
- pythonfmu3/pythonfmu-export/src/shim/shim_loader.hpp +29 -0
- pythonfmu3/resources/binaries/x86_64-linux/libpythonfmu-backend.so +0 -0
- pythonfmu3/resources/binaries/x86_64-linux/libpythonfmu-export.so +0 -0
- pythonfmu3/resources/binaries/x86_64-windows/pythonfmu-export.dll +0 -0
- pythonfmu3/tests/data/fmi3_host.c +31 -0
- pythonfmu3/tests/fmi3_ctypes_driver.py +137 -0
- pythonfmu3/tests/slaves/pythonslave_arraytypes.py +80 -0
- pythonfmu3/tests/test_builder.py +48 -2
- pythonfmu3/tests/test_docs.py +70 -61
- pythonfmu3/tests/test_integration.py +106 -0
- pythonfmu3/tests/test_non_python_host.py +75 -0
- pythonfmu3/tests/test_osutil.py +23 -0
- pythonfmu3/tests/test_variables.py +1 -1
- pythonfmu3/tests/test_wrapper_ctypes.py +61 -0
- pythonfmu3/variables.py +72 -47
- {pythonfmu3-0.3.3.dist-info → pythonfmu3-1.0.0.dist-info}/METADATA +61 -25
- {pythonfmu3-0.3.3.dist-info → pythonfmu3-1.0.0.dist-info}/RECORD +37 -26
- {pythonfmu3-0.3.3.dist-info → pythonfmu3-1.0.0.dist-info}/WHEEL +1 -1
- {pythonfmu3-0.3.3.dist-info → pythonfmu3-1.0.0.dist-info}/entry_points.txt +0 -0
- {pythonfmu3-0.3.3.dist-info → pythonfmu3-1.0.0.dist-info}/licenses/LICENSE +0 -0
- {pythonfmu3-0.3.3.dist-info → pythonfmu3-1.0.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"""Generate src/shim/fmi3_forwarders.cpp from src/fmi/fmi3FunctionTypes.h.
|
|
2
|
+
|
|
3
|
+
The shim is the library the importer loads on Linux/macOS. It has no link-time
|
|
4
|
+
dependency on libpython: on instantiation it loads libpython (unless the host process
|
|
5
|
+
already provides it, e.g. when the importer is itself written in Python) and then the
|
|
6
|
+
real implementation (the "backend" library), and forwards every FMI call to it.
|
|
7
|
+
|
|
8
|
+
Re-run this script after updating the FMI headers:
|
|
9
|
+
python generate_shim.py
|
|
10
|
+
"""
|
|
11
|
+
import re
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
|
|
14
|
+
HERE = Path(__file__).parent
|
|
15
|
+
TYPES_HEADER = HERE / "src" / "fmi" / "fmi3FunctionTypes.h"
|
|
16
|
+
OUTPUT = HERE / "src" / "shim" / "fmi3_forwarders.cpp"
|
|
17
|
+
|
|
18
|
+
TYPEDEF_RE = re.compile(r"typedef\s+([\w\s\*]+?)\s*\b(fmi3\w+)TYPE\s*\((.*?)\)\s*;", re.S)
|
|
19
|
+
INSTANTIATE = {
|
|
20
|
+
"fmi3InstantiateModelExchange",
|
|
21
|
+
"fmi3InstantiateCoSimulation",
|
|
22
|
+
"fmi3InstantiateScheduledExecution",
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def param_names(params: str):
|
|
27
|
+
params = " ".join(params.split())
|
|
28
|
+
if params in ("", "void"):
|
|
29
|
+
return []
|
|
30
|
+
return [re.findall(r"\w+", p.replace("[]", ""))[-1] for p in params.split(",")]
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def main():
|
|
34
|
+
functions = [
|
|
35
|
+
(" ".join(ret.split()), name, " ".join(params.split()))
|
|
36
|
+
for ret, name, params in TYPEDEF_RE.findall(TYPES_HEADER.read_text())
|
|
37
|
+
]
|
|
38
|
+
forwarded = [f for f in functions if f[1] != "fmi3GetVersion"]
|
|
39
|
+
|
|
40
|
+
out = [
|
|
41
|
+
"// GENERATED by generate_shim.py from fmi/fmi3FunctionTypes.h - do not edit by hand.",
|
|
42
|
+
'#include "shim/shim_loader.hpp"',
|
|
43
|
+
"",
|
|
44
|
+
"namespace pythonfmu_shim",
|
|
45
|
+
"{",
|
|
46
|
+
"const char* const kFunctionNames[] = {",
|
|
47
|
+
*[f' "{name}",' for _, name, _ in forwarded],
|
|
48
|
+
"};",
|
|
49
|
+
f"const std::size_t kFunctionCount = {len(forwarded)};",
|
|
50
|
+
"} // namespace pythonfmu_shim",
|
|
51
|
+
"",
|
|
52
|
+
'extern "C" {',
|
|
53
|
+
"",
|
|
54
|
+
"FMI3_Export const char* fmi3GetVersion(void)",
|
|
55
|
+
"{",
|
|
56
|
+
" return fmi3Version;",
|
|
57
|
+
"}",
|
|
58
|
+
"",
|
|
59
|
+
]
|
|
60
|
+
for index, (ret, name, params) in enumerate(forwarded):
|
|
61
|
+
names = param_names(params)
|
|
62
|
+
args = ", ".join(names)
|
|
63
|
+
out.append(f"FMI3_Export {ret} {name}({params})")
|
|
64
|
+
out.append("{")
|
|
65
|
+
if name in INSTANTIATE:
|
|
66
|
+
out.append(
|
|
67
|
+
" if (!pythonfmu_shim::ensureBackendLoaded(resourcePath, instanceEnvironment, logMessage)) return nullptr;"
|
|
68
|
+
)
|
|
69
|
+
out.append(f" const auto fn = reinterpret_cast<{name}TYPE*>(pythonfmu_shim::function({index}));")
|
|
70
|
+
if ret == "void":
|
|
71
|
+
out.append(f" if (fn) fn({args});")
|
|
72
|
+
elif ret == "fmi3Status":
|
|
73
|
+
out.append(" if (!fn) return fmi3Error;")
|
|
74
|
+
out.append(f" return fn({args});")
|
|
75
|
+
else:
|
|
76
|
+
out.append(" if (!fn) return nullptr;")
|
|
77
|
+
out.append(f" return fn({args});")
|
|
78
|
+
out.append("}")
|
|
79
|
+
out.append("")
|
|
80
|
+
out.append('} // extern "C"')
|
|
81
|
+
out.append("")
|
|
82
|
+
OUTPUT.parent.mkdir(exist_ok=True)
|
|
83
|
+
OUTPUT.write_text("\n".join(out))
|
|
84
|
+
print(f"wrote {OUTPUT.relative_to(HERE)} ({len(functions)} functions)")
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
if __name__ == "__main__":
|
|
88
|
+
main()
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
|
|
2
1
|
set(headers
|
|
3
2
|
cppfmu/cppfmu_cs.hpp
|
|
4
3
|
cppfmu/cppfmu_common.hpp
|
|
@@ -17,29 +16,58 @@ set(sources
|
|
|
17
16
|
pythonfmu/PySlaveInstance.cpp
|
|
18
17
|
)
|
|
19
18
|
|
|
20
|
-
|
|
21
|
-
target_compile_features(pythonfmu-export PUBLIC "cxx_std_17")
|
|
19
|
+
set(BINARY_OUTPUT_DIR "${CMAKE_SOURCE_DIR}/../resources/binaries/${TARGET_PLATFORM}")
|
|
22
20
|
|
|
23
|
-
|
|
21
|
+
if (WIN32)
|
|
22
|
+
# Windows: a single library, linked against the version-independent python3.dll.
|
|
23
|
+
set(PYTHONFMU_IMPL_TARGET pythonfmu-export)
|
|
24
|
+
else ()
|
|
25
|
+
# Linux/macOS: the Python-dependent implementation lives in a "backend" library
|
|
26
|
+
# (FMI functions renamed with a prefix). The FMU library itself (pythonfmu-export,
|
|
27
|
+
# renamed to <modelIdentifier> by the builder) is a small shim with no link-time
|
|
28
|
+
# dependency on libpython, so non-Python importers can load it. See shim/shim_loader.cpp.
|
|
29
|
+
set(PYTHONFMU_IMPL_TARGET pythonfmu-backend)
|
|
30
|
+
endif ()
|
|
31
|
+
|
|
32
|
+
add_library(${PYTHONFMU_IMPL_TARGET} ${sources} ${headers})
|
|
33
|
+
target_compile_features(${PYTHONFMU_IMPL_TARGET} PUBLIC "cxx_std_17")
|
|
34
|
+
target_include_directories(${PYTHONFMU_IMPL_TARGET}
|
|
24
35
|
PRIVATE
|
|
25
36
|
"${Python3_INCLUDE_DIRS}"
|
|
26
37
|
"${CMAKE_CURRENT_SOURCE_DIR}"
|
|
27
38
|
)
|
|
28
39
|
|
|
29
40
|
if (WIN32)
|
|
30
|
-
target_link_libraries(
|
|
31
|
-
|
|
32
|
-
set_target_properties(pythonfmu-export PROPERTIES LINK_FLAGS "-undefined dynamic_lookup")
|
|
33
|
-
endif ()
|
|
34
|
-
|
|
35
|
-
if (WIN32)
|
|
36
|
-
set_target_properties(pythonfmu-export
|
|
41
|
+
target_link_libraries(${PYTHONFMU_IMPL_TARGET} PRIVATE ${Python3_LIBRARIES})
|
|
42
|
+
set_target_properties(${PYTHONFMU_IMPL_TARGET}
|
|
37
43
|
PROPERTIES
|
|
38
|
-
RUNTIME_OUTPUT_DIRECTORY_RELEASE "${
|
|
44
|
+
RUNTIME_OUTPUT_DIRECTORY_RELEASE "${BINARY_OUTPUT_DIR}"
|
|
39
45
|
)
|
|
40
46
|
else ()
|
|
47
|
+
# Python symbols are resolved at load time against the process (the host Python, or
|
|
48
|
+
# the libpython the shim opened with RTLD_GLOBAL).
|
|
49
|
+
target_compile_definitions(${PYTHONFMU_IMPL_TARGET} PRIVATE FMI3_FUNCTION_PREFIX=pythonfmu_backend_)
|
|
50
|
+
if (APPLE)
|
|
51
|
+
set_target_properties(${PYTHONFMU_IMPL_TARGET} PROPERTIES LINK_FLAGS "-undefined dynamic_lookup")
|
|
52
|
+
endif ()
|
|
53
|
+
set_target_properties(${PYTHONFMU_IMPL_TARGET}
|
|
54
|
+
PROPERTIES
|
|
55
|
+
LIBRARY_OUTPUT_DIRECTORY "${BINARY_OUTPUT_DIR}"
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
add_library(pythonfmu-export
|
|
59
|
+
shim/shim_loader.cpp
|
|
60
|
+
shim/shim_loader.hpp
|
|
61
|
+
shim/fmi3_forwarders.cpp
|
|
62
|
+
)
|
|
63
|
+
target_compile_features(pythonfmu-export PUBLIC "cxx_std_17")
|
|
64
|
+
target_include_directories(pythonfmu-export PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}")
|
|
65
|
+
target_link_libraries(pythonfmu-export PRIVATE ${CMAKE_DL_LIBS})
|
|
41
66
|
set_target_properties(pythonfmu-export
|
|
42
67
|
PROPERTIES
|
|
43
|
-
LIBRARY_OUTPUT_DIRECTORY "${
|
|
68
|
+
LIBRARY_OUTPUT_DIRECTORY "${BINARY_OUTPUT_DIR}"
|
|
69
|
+
# Only the FMI functions (marked FMI3_Export) are exported
|
|
70
|
+
CXX_VISIBILITY_PRESET hidden
|
|
71
|
+
VISIBILITY_INLINES_HIDDEN ON
|
|
44
72
|
)
|
|
45
73
|
endif ()
|
|
@@ -121,6 +121,9 @@ public:
|
|
|
121
121
|
FMIString message,
|
|
122
122
|
Args&&... args) CPPFMU_NOEXCEPT
|
|
123
123
|
{
|
|
124
|
+
if (m_fmiLogger == nullptr) {
|
|
125
|
+
return; // FMI 3.0 allows instantiating without a logger callback
|
|
126
|
+
}
|
|
124
127
|
if (m_settings->loggedCategories.empty() ||
|
|
125
128
|
detail::CanFind(m_settings->loggedCategories, category)) {
|
|
126
129
|
m_fmiLogger(
|
|
@@ -66,7 +66,8 @@ void SlaveInstance::SetFloat64(
|
|
|
66
66
|
void SlaveInstance::SetInt32(
|
|
67
67
|
const FMIValueReference /*vr*/[],
|
|
68
68
|
std::size_t nvr,
|
|
69
|
-
const FMIInt32 /*value*/[]
|
|
69
|
+
const FMIInt32 /*value*/[],
|
|
70
|
+
std::size_t nValues)
|
|
70
71
|
{
|
|
71
72
|
if (nvr != 0) {
|
|
72
73
|
throw std::logic_error("Attempted to set nonexistent variable");
|
|
@@ -76,7 +77,8 @@ void SlaveInstance::SetInt32(
|
|
|
76
77
|
void SlaveInstance::SetInt64(
|
|
77
78
|
const FMIValueReference /*vr*/[],
|
|
78
79
|
std::size_t nvr,
|
|
79
|
-
const FMIInt64 /*value*/[]
|
|
80
|
+
const FMIInt64 /*value*/[],
|
|
81
|
+
std::size_t nValues)
|
|
80
82
|
{
|
|
81
83
|
if (nvr != 0) {
|
|
82
84
|
throw std::logic_error("Attempted to set nonexistent variable");
|
|
@@ -86,7 +88,8 @@ void SlaveInstance::SetInt64(
|
|
|
86
88
|
void SlaveInstance::SetUInt64(
|
|
87
89
|
const FMIValueReference /*vr*/[],
|
|
88
90
|
std::size_t nvr,
|
|
89
|
-
const FMIUInt64 /*value*/[]
|
|
91
|
+
const FMIUInt64 /*value*/[],
|
|
92
|
+
std::size_t nValues)
|
|
90
93
|
{
|
|
91
94
|
if (nvr != 0) {
|
|
92
95
|
throw std::logic_error("Attempted to set nonexistent variable");
|
|
@@ -97,7 +100,8 @@ void SlaveInstance::SetUInt64(
|
|
|
97
100
|
void SlaveInstance::SetBoolean(
|
|
98
101
|
const FMIValueReference /*vr*/[],
|
|
99
102
|
std::size_t nvr,
|
|
100
|
-
const FMIBoolean /*value*/[]
|
|
103
|
+
const FMIBoolean /*value*/[],
|
|
104
|
+
std::size_t nValues)
|
|
101
105
|
{
|
|
102
106
|
if (nvr != 0) {
|
|
103
107
|
throw std::logic_error("Attempted to set nonexistent variable");
|
|
@@ -108,7 +112,8 @@ void SlaveInstance::SetBoolean(
|
|
|
108
112
|
void SlaveInstance::SetString(
|
|
109
113
|
const FMIValueReference /*vr*/[],
|
|
110
114
|
std::size_t nvr,
|
|
111
|
-
const FMIString /*value*/[]
|
|
115
|
+
const FMIString /*value*/[],
|
|
116
|
+
std::size_t nValues)
|
|
112
117
|
{
|
|
113
118
|
if (nvr != 0) {
|
|
114
119
|
throw std::logic_error("Attempted to set nonexistent variable");
|
|
@@ -131,7 +136,8 @@ void SlaveInstance::GetFloat64(
|
|
|
131
136
|
void SlaveInstance::GetInt32(
|
|
132
137
|
const FMIValueReference /*vr*/[],
|
|
133
138
|
std::size_t nvr,
|
|
134
|
-
FMIInt32 /*value*/[]
|
|
139
|
+
FMIInt32 /*value*/[],
|
|
140
|
+
std::size_t nValues) const
|
|
135
141
|
{
|
|
136
142
|
if (nvr != 0) {
|
|
137
143
|
throw std::logic_error("Attempted to get nonexistent variable");
|
|
@@ -142,7 +148,8 @@ void SlaveInstance::GetInt32(
|
|
|
142
148
|
void SlaveInstance::GetInt64(
|
|
143
149
|
const FMIValueReference /*vr*/[],
|
|
144
150
|
std::size_t nvr,
|
|
145
|
-
FMIInt64 /*value*/[]
|
|
151
|
+
FMIInt64 /*value*/[],
|
|
152
|
+
std::size_t nValues) const
|
|
146
153
|
{
|
|
147
154
|
if (nvr != 0) {
|
|
148
155
|
throw std::logic_error("Attempted to get nonexistent variable");
|
|
@@ -153,7 +160,8 @@ void SlaveInstance::GetInt64(
|
|
|
153
160
|
void SlaveInstance::GetUInt64(
|
|
154
161
|
const FMIValueReference /*vr*/[],
|
|
155
162
|
std::size_t nvr,
|
|
156
|
-
FMIUInt64 /*value*/[]
|
|
163
|
+
FMIUInt64 /*value*/[],
|
|
164
|
+
std::size_t nValues) const
|
|
157
165
|
{
|
|
158
166
|
if (nvr != 0) {
|
|
159
167
|
throw std::logic_error("Attempted to get nonexistent variable");
|
|
@@ -164,7 +172,8 @@ void SlaveInstance::GetUInt64(
|
|
|
164
172
|
void SlaveInstance::GetBoolean(
|
|
165
173
|
const FMIValueReference /*vr*/[],
|
|
166
174
|
std::size_t nvr,
|
|
167
|
-
FMIBoolean /*value*/[]
|
|
175
|
+
FMIBoolean /*value*/[],
|
|
176
|
+
std::size_t nValues) const
|
|
168
177
|
{
|
|
169
178
|
if (nvr != 0) {
|
|
170
179
|
throw std::logic_error("Attempted to set nonexistent variable");
|
|
@@ -175,7 +184,8 @@ void SlaveInstance::GetBoolean(
|
|
|
175
184
|
void SlaveInstance::GetString(
|
|
176
185
|
const FMIValueReference /*vr*/[],
|
|
177
186
|
std::size_t nvr,
|
|
178
|
-
FMIString /*value*/[]
|
|
187
|
+
FMIString /*value*/[],
|
|
188
|
+
std::size_t nValues) const
|
|
179
189
|
{
|
|
180
190
|
if (nvr != 0) {
|
|
181
191
|
throw std::logic_error("Attempted to set nonexistent variable");
|
|
@@ -76,23 +76,28 @@ public:
|
|
|
76
76
|
virtual void SetInt32(
|
|
77
77
|
const FMIValueReference vr[],
|
|
78
78
|
std::size_t nvr,
|
|
79
|
-
const FMIInt32 value[]
|
|
79
|
+
const FMIInt32 value[],
|
|
80
|
+
std::size_t nValues);
|
|
80
81
|
virtual void SetInt64(
|
|
81
82
|
const FMIValueReference vr[],
|
|
82
83
|
std::size_t nvr,
|
|
83
|
-
const FMIInt64 value[]
|
|
84
|
+
const FMIInt64 value[],
|
|
85
|
+
std::size_t nValues);
|
|
84
86
|
virtual void SetUInt64(
|
|
85
87
|
const FMIValueReference vr[],
|
|
86
88
|
std::size_t nvr,
|
|
87
|
-
const FMIUInt64 value[]
|
|
89
|
+
const FMIUInt64 value[],
|
|
90
|
+
std::size_t nValues);
|
|
88
91
|
virtual void SetBoolean(
|
|
89
92
|
const FMIValueReference vr[],
|
|
90
93
|
std::size_t nvr,
|
|
91
|
-
const FMIBoolean value[]
|
|
94
|
+
const FMIBoolean value[],
|
|
95
|
+
std::size_t nValues);
|
|
92
96
|
virtual void SetString(
|
|
93
97
|
const FMIValueReference vr[],
|
|
94
98
|
std::size_t nvr,
|
|
95
|
-
const FMIString value[]
|
|
99
|
+
const FMIString value[],
|
|
100
|
+
std::size_t nValues);
|
|
96
101
|
|
|
97
102
|
/* Called from fmi3GetXxx()/fmiGetXxx().
|
|
98
103
|
* Throws std::logic_error by default.
|
|
@@ -105,23 +110,28 @@ public:
|
|
|
105
110
|
virtual void GetInt32(
|
|
106
111
|
const FMIValueReference vr[],
|
|
107
112
|
std::size_t nvr,
|
|
108
|
-
FMIInt32 value[]
|
|
113
|
+
FMIInt32 value[],
|
|
114
|
+
std::size_t nValues) const;
|
|
109
115
|
virtual void GetInt64(
|
|
110
116
|
const FMIValueReference vr[],
|
|
111
117
|
std::size_t nvr,
|
|
112
|
-
FMIInt64 value[]
|
|
118
|
+
FMIInt64 value[],
|
|
119
|
+
std::size_t nValues) const;
|
|
113
120
|
virtual void GetUInt64(
|
|
114
121
|
const FMIValueReference vr[],
|
|
115
122
|
std::size_t nvr,
|
|
116
|
-
FMIUInt64 value[]
|
|
123
|
+
FMIUInt64 value[],
|
|
124
|
+
std::size_t nValues) const;
|
|
117
125
|
virtual void GetBoolean(
|
|
118
126
|
const FMIValueReference vr[],
|
|
119
127
|
std::size_t nvr,
|
|
120
|
-
FMIBoolean value[]
|
|
128
|
+
FMIBoolean value[],
|
|
129
|
+
std::size_t nValues) const;
|
|
121
130
|
virtual void GetString(
|
|
122
131
|
const FMIValueReference vr[],
|
|
123
132
|
std::size_t nvr,
|
|
124
|
-
FMIString value[]
|
|
133
|
+
FMIString value[],
|
|
134
|
+
std::size_t nValues) const;
|
|
125
135
|
|
|
126
136
|
// Called from fmi3DoStep()/fmiDoStep(). Must be implemented in model code.
|
|
127
137
|
virtual FMIStatus DoStep(
|
|
@@ -95,7 +95,8 @@ fmi3Instance fmi3InstantiateCoSimulation(
|
|
|
95
95
|
fmi3IntermediateUpdateCallback intermediateUpdate )
|
|
96
96
|
{
|
|
97
97
|
try {
|
|
98
|
-
|
|
98
|
+
// Owned until fully constructed, so a failing instantiation does not leak it.
|
|
99
|
+
auto component = std::make_unique<Component>(
|
|
99
100
|
environment,
|
|
100
101
|
logMessage,
|
|
101
102
|
loggingOn);
|
|
@@ -108,7 +109,7 @@ fmi3Instance fmi3InstantiateCoSimulation(
|
|
|
108
109
|
visible,
|
|
109
110
|
cppfmu::FMIFalse,
|
|
110
111
|
component->logger);
|
|
111
|
-
return component;
|
|
112
|
+
return component.release();
|
|
112
113
|
} catch (const cppfmu::FatalError& e) {
|
|
113
114
|
if (logMessage)
|
|
114
115
|
{
|
|
@@ -134,7 +135,8 @@ fmi3Instance fmi3InstantiateModelExchange(
|
|
|
134
135
|
fmi3LogMessageCallback logMessage)
|
|
135
136
|
{
|
|
136
137
|
try {
|
|
137
|
-
|
|
138
|
+
// Owned until fully constructed, so a failing instantiation does not leak it.
|
|
139
|
+
auto component = std::make_unique<Component>(
|
|
138
140
|
environment,
|
|
139
141
|
logMessage,
|
|
140
142
|
loggingOn);
|
|
@@ -147,7 +149,7 @@ fmi3Instance fmi3InstantiateModelExchange(
|
|
|
147
149
|
visible,
|
|
148
150
|
cppfmu::FMIFalse,
|
|
149
151
|
component->logger);
|
|
150
|
-
return component;
|
|
152
|
+
return component.release();
|
|
151
153
|
} catch (const cppfmu::FatalError& e) {
|
|
152
154
|
if (logMessage)
|
|
153
155
|
{
|
|
@@ -334,7 +336,7 @@ fmi3Status fmi3GetInt32(
|
|
|
334
336
|
{
|
|
335
337
|
const auto component = reinterpret_cast<Component*>(c);
|
|
336
338
|
try {
|
|
337
|
-
component->slave->GetInt32(vr, nvr, values);
|
|
339
|
+
component->slave->GetInt32(vr, nvr, values, nValues);
|
|
338
340
|
return fmi3OK;
|
|
339
341
|
} catch (const cppfmu::FatalError& e) {
|
|
340
342
|
component->logger.Log(fmi3Fatal, "", e.what());
|
|
@@ -354,7 +356,7 @@ fmi3Status fmi3GetInt64(
|
|
|
354
356
|
{
|
|
355
357
|
const auto component = reinterpret_cast<Component*>(c);
|
|
356
358
|
try {
|
|
357
|
-
component->slave->GetInt64(vr, nvr, values);
|
|
359
|
+
component->slave->GetInt64(vr, nvr, values, nValues);
|
|
358
360
|
return fmi3OK;
|
|
359
361
|
} catch (const cppfmu::FatalError& e) {
|
|
360
362
|
component->logger.Log(fmi3Fatal, "", e.what());
|
|
@@ -374,7 +376,7 @@ fmi3Status fmi3GetUInt64(
|
|
|
374
376
|
{
|
|
375
377
|
const auto component = reinterpret_cast<Component*>(c);
|
|
376
378
|
try {
|
|
377
|
-
component->slave->GetUInt64(vr, nvr, values);
|
|
379
|
+
component->slave->GetUInt64(vr, nvr, values, nValues);
|
|
378
380
|
return fmi3OK;
|
|
379
381
|
} catch (const cppfmu::FatalError& e) {
|
|
380
382
|
component->logger.Log(fmi3Fatal, "", e.what());
|
|
@@ -394,7 +396,7 @@ fmi3Status fmi3GetBoolean(
|
|
|
394
396
|
{
|
|
395
397
|
const auto component = reinterpret_cast<Component*>(c);
|
|
396
398
|
try {
|
|
397
|
-
component->slave->GetBoolean(vr, nvr, values);
|
|
399
|
+
component->slave->GetBoolean(vr, nvr, values, nValues);
|
|
398
400
|
return fmi3OK;
|
|
399
401
|
} catch (const cppfmu::FatalError& e) {
|
|
400
402
|
component->logger.Log(fmi3Fatal, "", e.what());
|
|
@@ -414,7 +416,7 @@ fmi3Status fmi3GetString(
|
|
|
414
416
|
{
|
|
415
417
|
const auto component = reinterpret_cast<Component*>(c);
|
|
416
418
|
try {
|
|
417
|
-
component->slave->GetString(vr, nvr, values);
|
|
419
|
+
component->slave->GetString(vr, nvr, values, nValues);
|
|
418
420
|
return fmi3OK;
|
|
419
421
|
} catch (const cppfmu::FatalError& e) {
|
|
420
422
|
component->logger.Log(fmi3Fatal, "", e.what());
|
|
@@ -455,7 +457,7 @@ fmi3Status fmi3SetInt32(
|
|
|
455
457
|
{
|
|
456
458
|
const auto component = reinterpret_cast<Component*>(c);
|
|
457
459
|
try {
|
|
458
|
-
component->slave->SetInt32(vr, nvr, values);
|
|
460
|
+
component->slave->SetInt32(vr, nvr, values, nValues);
|
|
459
461
|
return fmi3OK;
|
|
460
462
|
} catch (const cppfmu::FatalError& e) {
|
|
461
463
|
component->logger.Log(fmi3Fatal, "", e.what());
|
|
@@ -475,7 +477,7 @@ fmi3Status fmi3SetInt64(
|
|
|
475
477
|
{
|
|
476
478
|
const auto component = reinterpret_cast<Component*>(c);
|
|
477
479
|
try {
|
|
478
|
-
component->slave->SetInt64(vr, nvr, values);
|
|
480
|
+
component->slave->SetInt64(vr, nvr, values, nValues);
|
|
479
481
|
return fmi3OK;
|
|
480
482
|
} catch (const cppfmu::FatalError& e) {
|
|
481
483
|
component->logger.Log(fmi3Fatal, "", e.what());
|
|
@@ -495,7 +497,7 @@ fmi3Status fmi3SetUInt64(
|
|
|
495
497
|
{
|
|
496
498
|
const auto component = reinterpret_cast<Component*>(c);
|
|
497
499
|
try {
|
|
498
|
-
component->slave->SetUInt64(vr, nvr, values);
|
|
500
|
+
component->slave->SetUInt64(vr, nvr, values, nValues);
|
|
499
501
|
return fmi3OK;
|
|
500
502
|
} catch (const cppfmu::FatalError& e) {
|
|
501
503
|
component->logger.Log(fmi3Fatal, "", e.what());
|
|
@@ -515,7 +517,7 @@ fmi3Status fmi3SetBoolean(
|
|
|
515
517
|
{
|
|
516
518
|
const auto component = reinterpret_cast<Component*>(c);
|
|
517
519
|
try {
|
|
518
|
-
component->slave->SetBoolean(vr, nvr, values);
|
|
520
|
+
component->slave->SetBoolean(vr, nvr, values, nValues);
|
|
519
521
|
return fmi3OK;
|
|
520
522
|
} catch (const cppfmu::FatalError& e) {
|
|
521
523
|
component->logger.Log(fmi3Fatal, "", e.what());
|
|
@@ -535,7 +537,7 @@ fmi3Status fmi3SetString(
|
|
|
535
537
|
{
|
|
536
538
|
const auto component = reinterpret_cast<Component*>(c);
|
|
537
539
|
try {
|
|
538
|
-
component->slave->SetString(vr, nvr, values);
|
|
540
|
+
component->slave->SetString(vr, nvr, values, nValues);
|
|
539
541
|
return fmi3OK;
|
|
540
542
|
} catch (const cppfmu::FatalError& e) {
|
|
541
543
|
component->logger.Log(fmi3Fatal, "", e.what());
|