Building breve plugins.

Here are some general guidelines on how to wrap an snns function.

Declare a prototype for the wrapper function, like this:
int wrapper_for_snns_loadNet(stEval *args, stEval *result, void *instance);
The arguments to wrapper functions will always be what you see in that example.

Add an entry point for the wrapped function, like this:
brNewBreveCall(data, "breve_snns_loadNet", wrapper_for_snns_loadNet, AT_STRING, AT_STRING, 0);

breve_snns_loadNet is the name of the function as it will be used in your breve programs.
wrapper_for_snns_loadNet is the name of the wrapper function as declared in the plugin .c file.
The first thing after that is the type of value the function returns.
After that, and up to the ending 0, will come a list of inputs to the function.

Inside the wrapping function, if the function as used from within breve passes input data that the snns function needs, you can get them from args with the STSTRING, STINT, STFLOAT, etc., functions. For example, char *filename = STSTRING(&args[0]) turns the string that was passed as the first input from breve into a C++ array of characters.

Look for the function in the SNNS manual, which is available online. There's links to the documentation for some important functions at http://helios.hampshire.edu/jdavila/cs222/IP_NN.htm .

Pay attention to what type of return value the function generates. In most, if not all, cases you will want to communicate what the SNNS function returns to breve. If it does generate a return value, catch it in the appropriate type of variable (int, float, char*, or whatever the case might be). 

If what the function generates is an error code, catch it like this:
krui_err error_code;
error_code = krui_loadNet(filename, &netname);

and then do
char *  errMsg = krui_error(errCode);
to turn the code into a message.

Any text message that you want to communicate to breve, pass it with something like this:
 slMessage(0, "breveSNNS: loadNet failed with message %s (error code %d).", errMsg, errCode);


The value that the breve function will return is determined by the set command. With result declared as stEval *, you can do the following:
result->set(something);

That something will be what the breve function will return. You can put any type of value in there (int, float, string,...) and the set function will figure things out.


Finally, the return value for the wrapper function itself. if you return EC_OK, breve carries out happily, regardless of what happened in SNNS. If you return EC_ERROR, the breve program will abort.

Here's kind of a full example, for  loadNet:

the prototype:
int wrapper_for_snns_loadNet(stEval *args, stEval *result, void *instance);

Here you tell breve that there is a new function available to breve, called  breve_snns_loadNet. When a breve program calls breve_snns_loadNet, the plugin will execute  wrapper_for_snns_loadNet. The breve function, breve_snns_loadNet, takes a string as input, and returns a string.
  brNewBreveCall(data, "breve_snns_loadNet", wrapper_for_snns_loadNet, AT_STRING, AT_STRING, 0);


Here is the wrapper function:
int wrapper_for_snns_loadNet(stEval *args, stEval *result, void *instance) {
// takes the first argument used in the breve function, and turns it into a
// c++ string.

  char *filename = STSTRING(&args[0]);

  char *netname, *netname1;
  krui_err errCode;
  char *errMsg;
// calls the SNNS function.
  errCode = krui_loadNet(filename, &netname);

  netname1 = (char *)slMalloc((strlen(netname)+1) * sizeof(char));
  strcpy(netname1, netname);
  if(errCode == KRERR_NO_ERROR) {
    result->set( netname1 );
  }
  else
  {
// an error was detected. Turn the code into a string message.
    errMsg = krui_error(errCode);
// display the message within breve.
    slMessage(0, "breveSNNS: loadNet failed with message %s (error code %d).", errMsg, errCode);
// this is what the breve function will return.
    result->set("no network loaded");
  }

// breve will continue after control returns from this wrapper function.
  return EC_OK;
}