The MIMIC C++ API requires the use of Gnu C++ 4.8.5 on the Linux platforms, or Visual Studio 2012 on Windows. If compiling on Visual Studio 2013 on Windows, you can enable "2012 mode" as documented here where it says
You can use Visual Studio 2013 to open a C++ project that was created in Visual Studio 2012 or Visual Studio 2010 SP1. If you want to use the Visual Studio 2013 build environment to build a project that was created in Visual Studio 2012, you must have both versions of Visual Studio installed on the same computer.
The user needs to use the header and library files shipped with a MIMIC installation to build a C++ application or action binary. All required API files are shipped under the "cpp" directory in the installation. The structure and contents of this directory is as follows :
[-] cpp [-] inc COMMON mimic_action.hh mimic_agent.hh mimic_api.hh mimic_apiutils.hh mimic_client.hh mimic_errorinfo.hh mimic_exports.hh mimic_helper.hh mimic_session.hh mimic_valuespace.hh [-] lib WINDOWS libcppapi.lib libcppapi_internal.lib libgci.lib libwin.lib pthreads.lib SOLARIS libcompat.a libcppapi.a libcppapi_internal.a libgci_pthreads.a LINUX libcppapi.a libcppapi_internal.a libgci_pthreads.a [-] src WINDOWS Build-action-vc6.bat Build-app-vc6.bat UNIX Makefile-testaction Makefile-hello Makefile-testapp COMMON hello.cc entryStatus.cc ifAdminStatus.cc mimic_helper.cc rowStatus.cc start.cc testaction.cc testapp.cc testtimer.cc timefilter.cc
Sample "Unix Makefiles" or "Windows batchfiles" are shipped for building a typical C++ client application or a C++ action. Also sample source code is provided to serve a easy starting point.
The equivalent to the Hello, World! program for MIMIC is to clear the current lab configuration, equivalent to File->New, load a new configuration like File->Open. , and start the first agent. The Hello, World! program for the C++ MIMIC API is in hello.cc You can accomplish this by building the program, eg. on Linux:
% make -f Makefile-hello binaries g++ -g -I../inc -DDEBUG -D_REENTRANT -c -o hello.o hello.cc g++ -o hello hello.o ../lib/libcppapi.a ../lib/libgci_pthreads.a -lpthread
then run the program.
While you are doing this, notice how your MIMICview reacts to the commands - it synchronizes with the simulator to keep up with the latest state. When the first agent turns green, it has synchronized to your state. You have seen that you can control MIMIC from any number of clients using the MIMIC API.
The cpp/src/testapp.cc program is a sample test program.
% make -f Makefile-testapp g++ -g -I../inc -DDEBUG -D_REENTRANT -c -o testapp.o testapp.cc g++ -o testapp testapp.o ../lib/libcppapi.a ../lib/libgci_pthreads.a -lpthread % cd .. % src/testapp TestApp: starting... test_sesssion_init : Session : 0x80aa6c0 test_sesssion_init over TestApp: config file = agent.cfg TestApp: max agents = 0 TestApp: last agent = 6 TestApp: version = 5.40 TestApp: num clients = 2 TestApp: configured agents = [1, 2, 3, 4, 5, 6] TestApp: active data : TestApp: configured changed agents = [1, 2, 3, 4, 5, 6] TestApp: state changes : agent = 1 state = 2 agent = 2 state = 2 agent = 3 state = 2 agent = 4 state = 2 agent = 5 state = 2 agent = 6 state = 2 ...
The Script Generator will generate C++ code from MIMICView dialogs.
The C++ actions need to be compiled into a dynamically loadable library (.so on Unix, .dll on Windows). It also needs to export a specific interface that can be invoked by the simulator. This requires the code to be structured in a certain manner, which is illustrated in the following sample code:
#include "mimic_action.hh" #ifdef WIN32 __declspec( dllexport ) #endif extern "C" int process_action_message ( int msg_id, void* msg_data ) { switch( msg_id ) { // on load only case ACTION_MODULE_REGISTER: { action_module_register_t *reg_data = (action_module_register_t*)msg_data; // verify version for the simulator reg_data->version.sprintf ( ACTION_BUILD_ID ); return ACTION_SUCCESS; } // on load only case ACTION_MODULE_INIT: { action_module_init_t *init_data = (action_module_init_t*)msg_data; //... return ACTION_SUCCESS; } // on unload only case ACTION_MODULE_UNINIT: { action_module_uninit_t *uninit_data = (action_module_uninit_t*)msg_data; //... return ACTION_SUCCESS; } // on every invocation case ACTION_MODULE_RUN: { action_module_run_t *run_data = (action_module_run_t*)msg_data; // access globals printf ( "SharedDir = %s\n", run_data->globals->get("gSharedDir") ); // ... return ACTION_SUCCESS; } } return ACTION_SUCCESS; // default success }
As per the code segment above, the DLL is required to export a well-known function "process_action_message" which takes an integer and an opaque pointer as arguments. This is invoked by the simulator for various events.
The REGISTER and LOAD are called during loading of the action, UNINIT is called during unloading of the action and RUN is called for each invocation of the action.
The header "cpp/inc/mimic_action.hh" defines function prototypes as well as data structures required to implement the DLL. Some sample implementations are also available in cpp/src/testaction.cc, cpp/src/entryStatus.cc, cpp/src/rowStatus.cc, cpp/src/start.cc, cpp/src/timefilter.cc.