0

I have several source files that run together as anonymous publish/subscribe nodes. There is a main function that collects all the nodes and launches them through their start functions.

// main.cpp
#include "nodeA.h"
#include "nodeB.h"

int main(int argc, char *argv[])
{
  /* some argument parsing here */
  start_node_a(argc, argv);
  start_node_b(argc, argv);
}

To make this easier to configure, I'd like to turn the main function into a shell script which launches these nodes. This would mean turning start_node() functions into main() functions so they run from the command line.

#!bin/bash
node_a -args
node_b -different_args

This makes it trickier to run tests, b/c the node main() functions would clash with the test main(), and there is no longer a start_node() function that an automated test could run.

My solution is to wrap the start_node functions in a main function, but this requires some extra boilerplate for each node, and some extra build wizardry to ignore main during test linking but not node building (I'm actually not sure if I can get this to work with gnumake & g++ yet).

// nodeA.cpp  
int main(int argc, char *argv[])
{
  start_node_a(argc, argv);
}

Is there a more elegant way to do this? A method of starting a program from a function call in tests, and starting a program from the command line?

*Note: I've also thought about system calls, but would consider that a worse solution than using the main() wrapper.

Arun A S
  • 6,421
  • 4
  • 29
  • 43
stebl
  • 175
  • 1
  • 1
  • 8
  • BTW, [system(3)](http://man7.org/linux/man-pages/man3/system.3.html) is *not* a system call (listed in [syscalls(2)](http://man7.org/linux/man-pages/man2/syscalls.2.html)....). It uses `fork`, `execve`, `/bin/sh` .... – Basile Starynkevitch Mar 02 '15 at 15:09
  • Interesting, I didn't know that. Since read up on it: [here](http://stackoverflow.com/questions/8086071/are-system-calls-evil) and [here](http://stackoverflow.com/questions/2923843/can-i-use-boost-library-for-crossplatform-application-executing/2925579#2925579). This may be acceptable for us – stebl Mar 02 '15 at 15:54

1 Answers1

0

Did you consider embedding an interpreter (like Lua or Guile) inside your program? You would then write some script (in Lua, Guile, etc....) to drive your various start_node_a etc...

So basically, you'll add some application-specific primitives bound and glued to the Lua or the Guile interpreters, and you'll write some Lua or Guile scripts. Both are well documented (here is Lua doc, here is Guile doc) and very used.

For Lua: create a state using lua_newstate, then use lua_register to add a primitive, luaL_dofile to run a file, luaL_dostring to evaluate a string.

For Guile: read the Programming Overview

BTW, I would recommend Guile (LGPL licensed) over Lua (MIT licensed), because I like more Scheme (the Guile language) than the Lua language. In all cases, be cautious about memory management.

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
  • I've heard of Lua but am unfamiliar with it, could you elaborate on how this would work? – stebl Mar 02 '15 at 15:54
  • I think this is a good solution. I've also looked at [this](http://www.lua.org/pil/25.html) example, which I found very helpful in getting started. Thanks! – stebl Mar 03 '15 at 14:18