Using RoadRunner from C++

Despite RoadRunner’s user interface being primarily in Python, RoadRunner is first and foremost a C++ library. It is therefore is possible to link roadrunner into an executable or library.

Note

You will need to have already installed RoadRunner into a directory on your system. See Installing RoadRunner section.

Note

You will also need to install cmake and add its “bin” directory to the PATH environment variable. You will know this is done if the command cmake –help works on the terminal/powershell.

The following is a very simple example of how to link roadrunner into an executable and run a simulation from C++. Create a new folder with whatever name seems appropriate and create the following files:

.
├── CMakeLists.txt
└── main.cpp

The CMakeLists.txt file should contain the following:

 1cmake_minimum_required(VERSION 3.22)
 2project(UseRoadRunnerFromC)
 3
 4set(CMAKE_CXX_STANDARD 17)
 5
 6# could be command line variables (-DROADRUNNER_INSTALL_PREFIX=...)
 7set(ROADRUNNER_INSTALL_PREFIX "D:/roadrunner/roadrunner/roadrunner-install-rel")
 8set(LLVM_INSTALL_PREFIX "D:/roadrunner/llvm-13.x/llvm-13.x-msvc2022-x64-rel")
 9set(CMAKE_PREFIX_PATH
10        "${ROADRUNNER_INSTALL_PREFIX}/cmake" # needed because this is where poco installs config files to
11        "${ROADRUNNER_INSTALL_PREFIX}/lib/cmake" # all other normal packages install config files to here
12        )
13# for registering location of ImportRoadRunnerAndDependencies
14set(CMAKE_MODULE_PATH "${ROADRUNNER_INSTALL_PREFIX}/lib/cmake")
15
16# Import roadrunner and all necessary dependencies for linking roadrunner.
17# This command is a roadrunner convenience cmake script which does all of the
18# calls to find_package(xxx, CONFIG) for us. If we didn't include this
19# script, we would manually need to call find_package for roadrunner-static
20# as well as roadrunner dependencies. Checkout The script
21# under <rr_install_prefix>/lib/cmake.
22include(ImportRoadRunnerAndDependencies)
23
24# add an executable
25add_executable(UseRoadRunnerFromCxx main.cpp)
26
27# link roadrunner-static. Note that we have configured roadrunner-static target (which is imported
28# under the alias roadrunner-static::roadrunner-static) with PUBLIC visibility, which means
29# all includes and transitive linked libraries are automatically handled by cmake.
30# without this, you would have to manually link roadrunner dependencies and manually
31# include roadrunner include directories with something like:
32#   - target_include_directories(UseRoadRunnerFromCxx PRIVATE "${ROADRUNNER_INSTALL_PREFIX}/include")
33target_link_libraries(UseRoadRunnerFromCxx PRIVATE roadrunner-static::roadrunner-static)

Now you can use RoadRunner from C++.

 1#include <iostream>
 2#include "rr/rrRoadRunner.h"
 3
 4using namespace rr;
 5
 6static std::string getSBMLString(){
 7    return "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
 8           "<sbml xmlns=\"http://www.sbml.org/sbml/level3/version2/core\" level=\"3\" version=\"2\">\n"
 9           "  <model metaid=\"_case00001\" id=\"case00001\" name=\"case00001\" timeUnits=\"time\">\n"
10           "    <listOfUnitDefinitions>\n"
11           "      <unitDefinition id=\"volume\">\n"
12           "        <listOfUnits>\n"
13           "          <unit kind=\"litre\" exponent=\"1\" scale=\"0\" multiplier=\"1\"/>\n"
14           "        </listOfUnits>\n"
15           "      </unitDefinition>\n"
16           "      <unitDefinition id=\"substance\">\n"
17           "        <listOfUnits>\n"
18           "          <unit kind=\"mole\" exponent=\"1\" scale=\"0\" multiplier=\"1\"/>\n"
19           "        </listOfUnits>\n"
20           "      </unitDefinition>\n"
21           "      <unitDefinition id=\"time\">\n"
22           "        <listOfUnits>\n"
23           "          <unit kind=\"second\" exponent=\"1\" scale=\"0\" multiplier=\"1\"/>\n"
24           "        </listOfUnits>\n"
25           "      </unitDefinition>\n"
26           "    </listOfUnitDefinitions>\n"
27           "    <listOfCompartments>\n"
28           "      <compartment id=\"compartment\" name=\"compartment\" spatialDimensions=\"3\" size=\"1\" units=\"volume\" constant=\"true\"/>\n"
29           "    </listOfCompartments>\n"
30           "    <listOfSpecies>\n"
31           "      <species id=\"S1\" name=\"S1\" compartment=\"compartment\" initialAmount=\"0.00015\" substanceUnits=\"substance\" hasOnlySubstanceUnits=\"false\" boundaryCondition=\"false\" constant=\"false\"/>\n"
32           "      <species id=\"S2\" name=\"S2\" compartment=\"compartment\" initialAmount=\"0\" substanceUnits=\"substance\" hasOnlySubstanceUnits=\"false\" boundaryCondition=\"false\" constant=\"false\"/>\n"
33           "    </listOfSpecies>\n"
34           "    <listOfParameters>\n"
35           "      <parameter id=\"k1\" name=\"k1\" value=\"1\" constant=\"true\"/>\n"
36           "    </listOfParameters>\n"
37           "    <listOfReactions>\n"
38           "      <reaction id=\"reaction1\" name=\"reaction1\" reversible=\"false\">\n"
39           "        <listOfReactants>\n"
40           "          <speciesReference species=\"S1\" stoichiometry=\"1\" constant=\"true\"/>\n"
41           "        </listOfReactants>\n"
42           "        <listOfProducts>\n"
43           "          <speciesReference species=\"S2\" stoichiometry=\"1\" constant=\"true\"/>\n"
44           "        </listOfProducts>\n"
45           "        <kineticLaw>\n"
46           "          <math xmlns=\"http://www.w3.org/1998/Math/MathML\">\n"
47           "            <apply>\n"
48           "              <times/>\n"
49           "              <ci> compartment </ci>\n"
50           "              <ci> k1 </ci>\n"
51           "              <ci> S1 </ci>\n"
52           "            </apply>\n"
53           "          </math>\n"
54           "        </kineticLaw>\n"
55           "      </reaction>\n"
56           "    </listOfReactions>\n"
57           "  </model>\n"
58           "</sbml>";
59}
60
61int main() {
62    RoadRunner roadRunner(getSBMLString());
63    std::cout << *roadRunner.simulate(0, 1, 101) << std::endl;
64    return 0;
65}