From e0105dcc43959291330dc9b11ff678e0419206ac Mon Sep 17 00:00:00 2001 From: Lars Ivar Hatledal Date: Mon, 28 Apr 2025 23:42:33 +0200 Subject: [PATCH 1/2] refactor how information is passed to instances using a struct is more future-proof --- README.md | 4 +- .../examples/BouncingBall/bouncing_ball.cpp | 4 +- export/examples/Resource/resource.cpp | 8 +- .../SimplePendulum/simple_pendulum.cpp | 4 +- export/include/fmu4cpp/fmu_base.hpp | 36 ++++----- export/src/fmu4cpp/fmi2.cpp | 80 ++++++++++--------- export/tests/array_test.cpp | 11 +-- export/tests/basic_test.cpp | 13 ++- export/tests/identity_test.cpp | 11 +-- export/tests/test_resource.cpp | 12 ++- src/model.cpp | 6 +- 11 files changed, 90 insertions(+), 99 deletions(-) diff --git a/README.md b/README.md index 95526e0..9999b09 100644 --- a/README.md +++ b/README.md @@ -25,8 +25,8 @@ using namespace fmu4cpp; class BouncingBall : public fmu_base { public: - BouncingBall(const std::string &instanceName, const std::string &resources) - : fmu_base(instanceName, resources) { + explicit BouncingBall(const fmu_data data) + : fmu_base(std::move(data)) { register_variable( real( diff --git a/export/examples/BouncingBall/bouncing_ball.cpp b/export/examples/BouncingBall/bouncing_ball.cpp index a5be334..1402484 100644 --- a/export/examples/BouncingBall/bouncing_ball.cpp +++ b/export/examples/BouncingBall/bouncing_ball.cpp @@ -7,8 +7,8 @@ using namespace fmu4cpp; class BouncingBall : public fmu_base { public: - BouncingBall(const std::string &instanceName, const std::filesystem::path &resources) - : fmu_base(instanceName, resources) { + explicit BouncingBall(const fmu_data &data) + : fmu_base(data) { register_variable( real( diff --git a/export/examples/Resource/resource.cpp b/export/examples/Resource/resource.cpp index e5f8210..7adbb4e 100644 --- a/export/examples/Resource/resource.cpp +++ b/export/examples/Resource/resource.cpp @@ -3,6 +3,7 @@ #include #include +#include using namespace fmu4cpp; @@ -10,10 +11,10 @@ using namespace fmu4cpp; class Resource : public fmu_base { public: - Resource(const std::string &instanceName, const std::filesystem::path &resources) - : fmu_base(instanceName, resources) { + explicit Resource(fmu_data data) + : fmu_base(std::move(data)) { - std::ifstream ifs(resources / "file.txt"); + std::ifstream ifs(resourceLocation() / "file.txt"); std::getline(ifs, content_); @@ -38,7 +39,6 @@ class Resource : public fmu_base { private: std::string content_; - }; model_info fmu4cpp::get_model_info() { diff --git a/export/examples/SimplePendulum/simple_pendulum.cpp b/export/examples/SimplePendulum/simple_pendulum.cpp index d9ee3e9..46693e1 100644 --- a/export/examples/SimplePendulum/simple_pendulum.cpp +++ b/export/examples/SimplePendulum/simple_pendulum.cpp @@ -9,8 +9,8 @@ constexpr double pi = 3.14159265358979323846; class SimplePendulum : public fmu_base { public: - SimplePendulum(const std::string &instanceName, const std::filesystem::path &resources) - : fmu_base(instanceName, resources) { + explicit SimplePendulum(const fmu_data &data) + : fmu_base(data) { register_variable(real("angle", &angle_) .setCausality(causality_t::OUTPUT) diff --git a/export/include/fmu4cpp/fmu_base.hpp b/export/include/fmu4cpp/fmu_base.hpp index 72cddd6..b92438b 100644 --- a/export/include/fmu4cpp/fmu_base.hpp +++ b/export/include/fmu4cpp/fmu_base.hpp @@ -16,29 +16,34 @@ #include -#define FMU4CPP_INSTANTIATE(MODELCLASS) \ - std::unique_ptr fmu4cpp::createInstance(const std::string &instanceName, \ - const std::filesystem::path &fmuResourceLocation) { \ - return std::make_unique(instanceName, fmuResourceLocation); \ +#define FMU4CPP_INSTANTIATE(MODELCLASS) \ + std::unique_ptr fmu4cpp::createInstance(const fmu4cpp::fmu_data &data) { \ + return std::make_unique(data); \ } namespace fmu4cpp { + struct fmu_data { + logger *logger; + std::string instance_name; + std::filesystem::path resourceLocation; + }; + class fmu_base { public: - fmu_base(std::string instance_name, std::filesystem::path resourceLocation) - : instanceName_(std::move(instance_name)), resourceLocation_(std::move(resourceLocation)) {} + explicit fmu_base(fmu_data data) + : data_(std::move(data)) {} fmu_base(const fmu_base &) = delete; fmu_base(const fmu_base &&) = delete; [[nodiscard]] std::string instanceName() const { - return instanceName_; + return data_.instance_name; } [[nodiscard]] const std::filesystem::path &resourceLocation() const { - return resourceLocation_; + return data_.resourceLocation; } [[nodiscard]] std::optional get_int_variable(const std::string &name) const { @@ -143,13 +148,9 @@ namespace fmu4cpp { [[nodiscard]] std::string make_description() const; - void __set_logger(logger *logger) { - logger_ = logger; - } - void log(const fmi2Status s, const std::string &message) { - if (logger_) { - logger_->log(s, message); + if (data_.logger) { + data_.logger->log(s, message); } } @@ -199,12 +200,9 @@ namespace fmu4cpp { private: - logger *logger_ = nullptr; + fmu_data data_; size_t numVariables_{1}; - std::string instanceName_; - std::filesystem::path resourceLocation_; - std::vector integers_; std::vector reals_; std::vector booleans_; @@ -215,7 +213,7 @@ namespace fmu4cpp { model_info get_model_info(); - std::unique_ptr createInstance(const std::string &instanceName, const std::filesystem::path &fmuResourceLocation); + std::unique_ptr createInstance(const fmu_data &data); }// namespace fmu4cpp diff --git a/export/src/fmu4cpp/fmi2.cpp b/export/src/fmu4cpp/fmi2.cpp index 79f34ae..811c369 100644 --- a/export/src/fmu4cpp/fmi2.cpp +++ b/export/src/fmu4cpp/fmi2.cpp @@ -16,17 +16,14 @@ namespace { // A struct that holds all the data for one model instance. struct Component { - Component(std::unique_ptr slave, const fmi2CallbackFunctions &callbackFunctions) + Component(std::unique_ptr slave, std::unique_ptr logger) : lastSuccessfulTime{std::numeric_limits::quiet_NaN()}, slave(std::move(slave)), - logger(callbackFunctions, this->slave->instanceName()) { - - this->slave->__set_logger(&logger); - } + logger(std::move(logger)) {} double lastSuccessfulTime; std::unique_ptr slave; - fmu4cpp::logger logger; + std::unique_ptr logger; }; }// namespace @@ -42,7 +39,11 @@ const char *fmi2GetVersion(void) { } FMI2_Export void write_description(const char *location) { - const auto instance = fmu4cpp::createInstance("", ""); + const auto instance = fmu4cpp::createInstance({ + nullptr, + "", + "", + }); const auto xml = instance->make_description(); std::ofstream of(location); of << xml; @@ -79,17 +80,18 @@ fmi2Component fmi2Instantiate(fmi2String instanceName, resources.replace(0, 6 - magic, ""); } - auto slave = fmu4cpp::createInstance(instanceName, resources); + std::unique_ptr logger = std::make_unique(*functions, instanceName); + + auto slave = fmu4cpp::createInstance({logger.get(), instanceName, resources}); const auto guid = slave->guid(); if (guid != fmuGUID) { std::cerr << "[fmu4cpp] Error. Wrong guid!" << std::endl; - fmu4cpp::logger l(*functions, instanceName); - l.log(fmi2Fatal, "Error. Wrong guid!"); + logger->log(fmi2Fatal, "Error. Wrong guid!"); return nullptr; } - auto c = std::make_unique(std::move(slave), *functions); - c->logger.setDebugLogging(loggingOn); + auto c = std::make_unique(std::move(slave), std::move(logger)); + c->logger->setDebugLogging(loggingOn); return c.release(); } @@ -110,10 +112,10 @@ fmi2Status fmi2SetupExperiment(fmi2Component c, component->slave->setup_experiment(startTime, stop, tol); return fmi2OK; } catch (const fmu4cpp::fatal_error &ex) { - component->logger.log(fmi2Fatal, ex.what()); + component->logger->log(fmi2Fatal, ex.what()); return fmi2Fatal; } catch (const std::exception &ex) { - component->logger.log(fmi2Error, ex.what()); + component->logger->log(fmi2Error, ex.what()); return fmi2Error; } } @@ -125,10 +127,10 @@ fmi2Status fmi2EnterInitializationMode(fmi2Component c) { component->slave->enter_initialisation_mode(); return fmi2OK; } catch (const fmu4cpp::fatal_error &ex) { - component->logger.log(fmi2Fatal, ex.what()); + component->logger->log(fmi2Fatal, ex.what()); return fmi2Fatal; } catch (const std::exception &ex) { - component->logger.log(fmi2Error, ex.what()); + component->logger->log(fmi2Error, ex.what()); return fmi2Error; } } @@ -139,10 +141,10 @@ fmi2Status fmi2ExitInitializationMode(fmi2Component c) { component->slave->exit_initialisation_mode(); return fmi2OK; } catch (const fmu4cpp::fatal_error &ex) { - component->logger.log(fmi2Fatal, ex.what()); + component->logger->log(fmi2Fatal, ex.what()); return fmi2Fatal; } catch (const std::exception &ex) { - component->logger.log(fmi2Error, ex.what()); + component->logger->log(fmi2Error, ex.what()); return fmi2Error; } } @@ -153,10 +155,10 @@ fmi2Status fmi2Terminate(fmi2Component c) { component->slave->terminate(); return fmi2OK; } catch (const fmu4cpp::fatal_error &ex) { - component->logger.log(fmi2Fatal, ex.what()); + component->logger->log(fmi2Fatal, ex.what()); return fmi2Fatal; } catch (const std::exception &ex) { - component->logger.log(fmi2Error, ex.what()); + component->logger->log(fmi2Error, ex.what()); return fmi2Error; } } @@ -176,10 +178,10 @@ fmi2Status fmi2DoStep( return fmi2Discard; } catch (const fmu4cpp::fatal_error &ex) { - component->logger.log(fmi2Fatal, ex.what()); + component->logger->log(fmi2Fatal, ex.what()); return fmi2Fatal; } catch (const std::exception &ex) { - component->logger.log(fmi2Error, ex.what()); + component->logger->log(fmi2Error, ex.what()); return fmi2Error; } } @@ -205,10 +207,10 @@ fmi2Status fmi2GetInteger( component->slave->get_integer(vr, nvr, value); return fmi2OK; } catch (const fmu4cpp::fatal_error &ex) { - component->logger.log(fmi2Fatal, ex.what()); + component->logger->log(fmi2Fatal, ex.what()); return fmi2Fatal; } catch (const std::exception &ex) { - component->logger.log(fmi2Error, ex.what()); + component->logger->log(fmi2Error, ex.what()); return fmi2Error; } } @@ -224,10 +226,10 @@ fmi2Status fmi2GetReal( component->slave->get_real(vr, nvr, value); return fmi2OK; } catch (const fmu4cpp::fatal_error &ex) { - component->logger.log(fmi2Fatal, ex.what()); + component->logger->log(fmi2Fatal, ex.what()); return fmi2Fatal; } catch (const std::exception &ex) { - component->logger.log(fmi2Error, ex.what()); + component->logger->log(fmi2Error, ex.what()); return fmi2Error; } } @@ -243,10 +245,10 @@ fmi2Status fmi2GetBoolean( component->slave->get_boolean(vr, nvr, value); return fmi2OK; } catch (const fmu4cpp::fatal_error &ex) { - component->logger.log(fmi2Fatal, ex.what()); + component->logger->log(fmi2Fatal, ex.what()); return fmi2Fatal; } catch (const std::exception &ex) { - component->logger.log(fmi2Error, ex.what()); + component->logger->log(fmi2Error, ex.what()); return fmi2Error; } } @@ -262,10 +264,10 @@ fmi2Status fmi2GetString( component->slave->get_string(vr, nvr, value); return fmi2OK; } catch (const fmu4cpp::fatal_error &ex) { - component->logger.log(fmi2Fatal, ex.what()); + component->logger->log(fmi2Fatal, ex.what()); return fmi2Fatal; } catch (const std::exception &ex) { - component->logger.log(fmi2Error, ex.what()); + component->logger->log(fmi2Error, ex.what()); return fmi2Error; } } @@ -281,10 +283,10 @@ fmi2Status fmi2SetInteger( component->slave->set_integer(vr, nvr, value); return fmi2OK; } catch (const fmu4cpp::fatal_error &ex) { - component->logger.log(fmi2Fatal, ex.what()); + component->logger->log(fmi2Fatal, ex.what()); return fmi2Fatal; } catch (const std::exception &ex) { - component->logger.log(fmi2Error, ex.what()); + component->logger->log(fmi2Error, ex.what()); return fmi2Error; } } @@ -300,10 +302,10 @@ fmi2Status fmi2SetReal( component->slave->set_real(vr, nvr, value); return fmi2OK; } catch (const fmu4cpp::fatal_error &ex) { - component->logger.log(fmi2Fatal, ex.what()); + component->logger->log(fmi2Fatal, ex.what()); return fmi2Fatal; } catch (const std::exception &ex) { - component->logger.log(fmi2Error, ex.what()); + component->logger->log(fmi2Error, ex.what()); return fmi2Error; } } @@ -319,10 +321,10 @@ fmi2Status fmi2SetBoolean( component->slave->set_boolean(vr, nvr, value); return fmi2OK; } catch (const fmu4cpp::fatal_error &ex) { - component->logger.log(fmi2Fatal, ex.what()); + component->logger->log(fmi2Fatal, ex.what()); return fmi2Fatal; } catch (const std::exception &ex) { - component->logger.log(fmi2Error, ex.what()); + component->logger->log(fmi2Error, ex.what()); return fmi2Error; } } @@ -338,10 +340,10 @@ fmi2Status fmi2SetString( component->slave->set_string(vr, nvr, value); return fmi2OK; } catch (const fmu4cpp::fatal_error &ex) { - component->logger.log(fmi2Fatal, ex.what()); + component->logger->log(fmi2Fatal, ex.what()); return fmi2Fatal; } catch (const std::exception &ex) { - component->logger.log(fmi2Error, ex.what()); + component->logger->log(fmi2Error, ex.what()); return fmi2Error; } } @@ -397,7 +399,7 @@ fmi2Status fmi2SetDebugLogging(fmi2Component c, const fmi2String /*categories*/[]) { const auto component = static_cast(c); - component->logger.setDebugLogging(loggingOn); + component->logger->setDebugLogging(loggingOn); return fmi2OK; } diff --git a/export/tests/array_test.cpp b/export/tests/array_test.cpp index 73cb08f..0405342 100644 --- a/export/tests/array_test.cpp +++ b/export/tests/array_test.cpp @@ -13,8 +13,8 @@ class Model : public fmu4cpp::fmu_base { public: - Model(const std::string &instanceName, const std::filesystem::path &resources) - : fmu_base(instanceName, resources), reals_(4) { + explicit Model(const fmu4cpp::fmu_data &data) + : fmu_base(data), reals_(4) { for (int i = 0; i < reals_.size(); i++) { register_variable( @@ -44,10 +44,7 @@ fmu4cpp::model_info fmu4cpp::get_model_info() { return info; } -std::unique_ptr fmu4cpp::createInstance(const std::string &instanceName, - const std::filesystem::path &fmuResourceLocation) { - return std::make_unique(instanceName, fmuResourceLocation); -} +FMU4CPP_INSTANTIATE(Model); void fmilogger(fmi2Component, fmi2String instanceName, fmi2Status status, fmi2String category, fmi2String message, ...) { va_list args; @@ -60,7 +57,7 @@ void fmilogger(fmi2Component, fmi2String instanceName, fmi2Status status, fmi2St TEST_CASE("test_array") { - Model model("", ""); + Model model({}); const auto guid = model.guid(); fmi2CallbackFunctions callbackFunctions; diff --git a/export/tests/basic_test.cpp b/export/tests/basic_test.cpp index f0e074c..7a33bbb 100644 --- a/export/tests/basic_test.cpp +++ b/export/tests/basic_test.cpp @@ -1,14 +1,15 @@ -#include #include +#include #include +#include class Model : public fmu4cpp::fmu_base { public: - Model(const std::string &instanceName, const std::filesystem::path &resources) - : fmu_base(instanceName, resources) { + explicit Model(fmu4cpp::fmu_data data) + : fmu_base(std::move(data)) { register_variable(real("myReal", &real_) .setCausality(fmu4cpp::causality_t::OUTPUT)); @@ -50,13 +51,11 @@ fmu4cpp::model_info fmu4cpp::get_model_info() { return m; } -std::unique_ptr fmu4cpp::createInstance(const std::string &instanceName, const std::filesystem::path &fmuResourceLocation) { - return std::make_unique(instanceName, fmuResourceLocation); -} +FMU4CPP_INSTANTIATE(Model); TEST_CASE("basic_test") { - const auto instance = fmu4cpp::createInstance("", ""); + const auto instance = fmu4cpp::createInstance({}); double t = 0; const double dt = 0.1; diff --git a/export/tests/identity_test.cpp b/export/tests/identity_test.cpp index 8586f8e..7c128bc 100644 --- a/export/tests/identity_test.cpp +++ b/export/tests/identity_test.cpp @@ -12,8 +12,8 @@ class Model : public fmu4cpp::fmu_base { public: - Model(const std::string &instanceName, const std::filesystem::path &resources) - : fmu_base(instanceName, resources) { + explicit Model(const fmu4cpp::fmu_data &data) + : fmu_base(data) { register_variable(integer("integerIn", &integer_) .setCausality(fmu4cpp::causality_t::INPUT) @@ -85,10 +85,7 @@ fmu4cpp::model_info fmu4cpp::get_model_info() { return info; } -std::unique_ptr fmu4cpp::createInstance(const std::string &instanceName, - const std::filesystem::path &fmuResourceLocation) { - return std::make_unique(instanceName, fmuResourceLocation); -} +FMU4CPP_INSTANTIATE(Model); int readInt(fmi2Component c) { fmi2ValueReference ref = 1; @@ -169,7 +166,7 @@ void fmilogger(fmi2Component, fmi2String instanceName, fmi2Status status, fmi2St TEST_CASE("test_identity") { - Model model("", ""); + Model model({}); const auto guid = model.guid(); fmi2CallbackFunctions callbackFunctions; diff --git a/export/tests/test_resource.cpp b/export/tests/test_resource.cpp index be0103b..eb5e23d 100644 --- a/export/tests/test_resource.cpp +++ b/export/tests/test_resource.cpp @@ -7,10 +7,10 @@ class Model : public fmu4cpp::fmu_base { public: - Model(const std::string &instanceName, const std::filesystem::path &resources) - : fmu_base(instanceName, resources) { + explicit Model(fmu4cpp::fmu_data data) + : fmu_base(std::move(data)) { - std::ifstream file(resources.string() + "/data.txt"); + std::ifstream file(resourceLocation().string() + "/data.txt"); std::getline(file, data_); @@ -39,15 +39,13 @@ fmu4cpp::model_info fmu4cpp::get_model_info() { return m; } -std::unique_ptr fmu4cpp::createInstance(const std::string &instanceName, const std::filesystem::path &fmuResourceLocation) { - return std::make_unique(instanceName, fmuResourceLocation); -} +FMU4CPP_INSTANTIATE(Model); TEST_CASE("model with resource") { std::string expected{"Hello resource!"}; - const auto instance = fmu4cpp::createInstance("myInstance", TEST_CASE_RESOURCE_LOCATION); + const auto instance = fmu4cpp::createInstance({nullptr, "myInstance", TEST_CASE_RESOURCE_LOCATION}); auto strVar = instance->get_string_variable("data"); REQUIRE(strVar); diff --git a/src/model.cpp b/src/model.cpp index ea5d8f6..30cb20d 100644 --- a/src/model.cpp +++ b/src/model.cpp @@ -11,8 +11,8 @@ using namespace fmu4cpp; class Model : public fmu_base { public: - Model(const std::string &instanceName, const std::filesystem::path &resources) - : fmu_base(instanceName, resources) { + explicit Model(const fmu_data &data) + : fmu_base(data) { register_variable(integer( "integerIn", &integer_) @@ -88,4 +88,4 @@ model_info fmu4cpp::get_model_info() { return info; } -FMU4CPP_INSTANTIATE(Model); // Entry point for FMI instantiate function. +FMU4CPP_INSTANTIATE(Model);// Entry point for FMI instantiate function. From cdea55f74bcdc40889808aca78122aec925ab166 Mon Sep 17 00:00:00 2001 From: Lars Ivar Hatledal Date: Mon, 28 Apr 2025 23:44:15 +0200 Subject: [PATCH 2/2] rename logger variable --- export/include/fmu4cpp/fmu_base.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/export/include/fmu4cpp/fmu_base.hpp b/export/include/fmu4cpp/fmu_base.hpp index b92438b..31d64ed 100644 --- a/export/include/fmu4cpp/fmu_base.hpp +++ b/export/include/fmu4cpp/fmu_base.hpp @@ -24,7 +24,7 @@ namespace fmu4cpp { struct fmu_data { - logger *logger; + logger *fmiLogger; std::string instance_name; std::filesystem::path resourceLocation; }; @@ -149,8 +149,8 @@ namespace fmu4cpp { [[nodiscard]] std::string make_description() const; void log(const fmi2Status s, const std::string &message) { - if (data_.logger) { - data_.logger->log(s, message); + if (data_.fmiLogger) { + data_.fmiLogger->log(s, message); } }