Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Observe and manipulate boolean and string variables #257

Merged
merged 6 commits into from
Jun 7, 2019

Conversation

eidekrist
Copy link
Member

This PR fixes #253, observing boolean and string variables with cse::last_value_observer.

The C api has been updated with getters for boolean and string variables values. The solution for the latter won't win any beauty contests, please let me know if it can/should be done in a different way.

Additionally, methods for overriding and resetting boolean and string variables have been implemented in the C api, along with some minor changes to cse::override_manipulator. Most of the changes in cse.h are from moving code around, apologies to all.

For testing, you can download a distribution from the companion cse-server-go build on Jenkins. I recommend testing with identity.fmu as it has all the variable types we need.

Copy link
Member

@kyllingstad kyllingstad left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the most part, this looks very good! I mainly had some comments regarding the string handling, as you predicted. ;)

include/cse/manipulator.hpp Show resolved Hide resolved
include/cse.h Outdated
size_t nv,
bool values[]);

/// A struct used for retrieving string variable values with `cse_observer_slave_get_string()`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While I like the simplicity of this solution, I think it's too restrictive. It's very hard to determine what is a "good" size for the cse_string_value::value array. Make it too small, and you'll just get bogus data from some simulators; make it too big, and you're wasting memory. And the choice of SLAVE_NAME_MAX_SIZE seems somewhat arbitrary/unjustified.

Instead, I suggest we take our cue from FMI, in particular its fmi2GetString() function:

Let the user supply an array of const char* elements to cse_observer_slave_get_string(), which we fill with pointers to null-terminated strings. The memory for the string contents (to which the aforementioned pointers refer) is managed internally by CSE-core, typically in an internal vector of std::strings, and have a well-defined, documented lifetime. Depending on the implementation, in particular, where the strings are stored and when they get filled/overwritten, the returned pointers could be valid until:

  • the next cse_observer_slave_get_string() call for the given cse_observer
  • the next call to any CSE function
  • the next time step
  • ...and lots of other alternatives

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the suggestion! I agree, will implement.

src/c/cse.cpp Outdated
std::vector<std::string> s(nv);
obs->get_string(slave, gsl::make_span(variables, nv), gsl::span<std::string>(s));
for (size_t i = 0; i < nv; i++) {
strncpy(values[i].value, s[i].c_str(), SLAVE_NAME_MAX_SIZE);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

strncpy() is a treacherous function. If s[i].size() >= SLAVE_NAME_MAX_SIZE, the contents of values[i].value won't be null terminated. And a C string which is not null terminated is a buffer overrun just waiting to happen.

Therefore, you should always manually set the last element in the buffer to null when using it like this. That is, the next line should be

values[i].value[SLAVE_NAME_MAX_SIZE-1] = '\0';

(You may also want to use sizeof values[i].value instead of SLAVE_NAME_MAX_SIZE to be more robust against a future change of the array size in the header.)

Of course, none of this applies if you follow my suggestion and change the way the function works entirely, but it's still worth noting for future cases.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, wasn't aware you could do that. Will keep it in mind!

Copy link
Member

@kyllingstad kyllingstad left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great!

# Conflicts:
#	src/cpp/cse/observer/slave_value_provider.hpp
@eidekrist eidekrist merged commit 998eef3 into master Jun 7, 2019
@eidekrist eidekrist deleted the feature/253-observe-bool-and-string-variables branch June 7, 2019 09:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Observe string and boolean variables
3 participants