-
Notifications
You must be signed in to change notification settings - Fork 63
BMI C
For C models, the model must be packaged as a pre-compiled shared library. A CMake cache variables can be configured for controlling whether the framework functionality for working with BMI C libraries is activated. This is found in, or must be added to, the CMakeCache.txt file in the build system directory:
-
BMI_C_LIB_ACTIVE
- type:
BOOL
- must be set to
ON
(or equivalent in CMake) for BMI C shared library functionality to be compiled and active
- type:
The CMake build system may need to be regenerated after changing these settings.
See the CMake documentation on the set function or variables for more information on working with CMake variables.
When CMake is able to find the library for the given name, it will automatically set up the dependent, internal, static library to dynamically link to the external shared library at runtime.
Additionally, as noted above, the path to the shared library must be provided in the configuration. This is because C libraries must be loaded dynamically within the execution of the NextGen framework, or else certain limitations of C would prevent using more than one such external C BMI model library at a time.
An example implementation for an appropriate BMI model as a C shared library is provided in the project here.
BMI C functionality will not work (i.e., will not be compiled or executable) unless set to be active in the CMake build. This requires setting the BMI_C_LIB_ACTIVE
CMake cache variable to ON
or TRUE
(or equivalent).
Conversely, built executables (and perhaps certain build targets) may not function as expected if BMI_C_LIB_ACTIVE
is ON
but the configured shared library is not available.
BMI models written in C should implement an extra "registration" function in order to be compatible with NextGen. By default, this registration function is expected to be:
Bmi* register_bmi(Bmi *model);
It is possible to configure a different name for the function within the NGen realization config, but the return type and parameter list must be as noted here.
The implemented function must set the member pointers of the passed Bmi
struct to the appropriate analogous functions inside the model. E.g., the initialize
member of the struct:
int (*initialize)(struct Bmi *self, const char *bmi_init_config)
needs to be set to the module's function the performs the BMI initialization. This will probably be something like:
static int Initialize (Bmi *self, const char *file)
So the registration function may look something like:
Bmi* register_bmi_cfe(Bmi *model) {
if (model) {
...
model->initialize = Initialize;
...
Full examples for how to write this registration function can be found in the local CFE BMI implementation, specifically in extern/cfe/src/bmi_cfe.c, or in the official CSDMS bmi-example-c repo near the bottom of the bmi-heat.c file.
This is needed both due to the design of the C language variant of BMI, and the limitations of C regarding duplication of function names. The latter becomes significant when more than one BMI C library is used at once. Even if that is actively the case, NextGen is designed to accomodate that case, so this requirement is in place.
Future versions of NextGen will provide alternative ways to declaratively configure function names from a BMI C library so they can individually be dynamically loaded.
Tutorial
Getting Started
Configuration
Technical References