Difference between revisions of "Low-level API for Writing Extensions in GrADS v2.0"

From OpenGrADS
Jump to: navigation, search
Line 7: Line 7:
 
In addition, for each UDF, the user provides an entry in a ''User Defined Extension" (UDX) table
 
In addition, for each UDF, the user provides an entry in a ''User Defined Extension" (UDX) table
 
which tells GrADS where to look for the UDF.
 
which tells GrADS where to look for the UDF.
# Type  API     Name            Function                Library
+
#     A
  # ------ --- --------------- ---------------- ---------------------------   
+
#      P  GrADS     Library     Library              Short
    udf   0    hello             f_hello         ^hello.gex
+
# Type I Function  Function      Path              Description
 +
# ---- - ---------- ---------- -------------- -------------------------------   
 +
  udf 0 " "        " "        " "   "Simple Extension Example"
 +
  udf  0  hello     f_hello   ^libhello.gex "Hello, World! sample function"
 +
#..........................................................................
 +
 
 
The <tt>Name</tt> (''hello'' in this example) is the name of the function to be used in a GrADS expression; <tt>Function</tt> is the name of the C-function (''f_hello'' in this case) inside the dynamically linked library (DLL) <tt>Library</tt>. The <tt>API</tt> version (''0'' in this example) is used to denote a particular version of the UDF API, allowing for future extensions.
 
The <tt>Name</tt> (''hello'' in this example) is the name of the function to be used in a GrADS expression; <tt>Function</tt> is the name of the C-function (''f_hello'' in this case) inside the dynamically linked library (DLL) <tt>Library</tt>. The <tt>API</tt> version (''0'' in this example) is used to denote a particular version of the UDF API, allowing for future extensions.
  

Revision as of 18:52, 6 June 2014

The OpenGrADS User Defined Extensions in GrADS v1.9.0-rc1 was implemented in terms of the low-level GrADS data structures. While such approach provided maximum flexibility in so far as to provided access to all GrADS internals, it was a very fragile and tied to a particular version of GrADS. An internal change in data structure, even if it did not require changes in the extension source code, very often required re-compilation of the extensions. Therefore, this is not a recommended interface for developing new User Defined Extensions.

For each User Defined Function (UDF), the user provides a C function with a standard interface:

#include "grads.h"
int f_hello (struct gafunc *pfc, struct gastat *pst);

where grads.h is the main GrADS include file. The data structures gafunc and gastat are the same structures used to implement GrADS intrinsic functions. In fact, a UDF implemented this way can be easily implemented as a GrADS intrinsic function. In addition, for each UDF, the user provides an entry in a User Defined Extension" (UDX) table which tells GrADS where to look for the UDF.

  1. A
  2. P GrADS Library Library Short
  3. Type I Function Function Path Description
  4. ---- - ---------- ---------- -------------- -------------------------------
 udf  0  " "        " "        " "    "Simple Extension Example"
 udf  0   hello     f_hello   ^libhello.gex  "Hello, World! sample function"
  1. ..........................................................................

The Name (hello in this example) is the name of the function to be used in a GrADS expression; Function is the name of the C-function (f_hello in this case) inside the dynamically linked library (DLL) Library. The API version (0 in this example) is used to denote a particular version of the UDF API, allowing for future extensions.

The optional caret (^) in this example is useful to simplify installation: it tells GrADS that the DLL is found at the same directory where User Defined Extension table is located, freeing the user from having to set environment variables such as LD_LIBRARY_PATH.

Example: Hello World

Here is the full source code for the Hello World! extension:

#include <stdio.h>
#include "grads.h"

static counter = 0; /* Illustrates how to keep a state */
/* Sample Hello, World! user defined command */
int c_hello ( int argc, char **argv, struct gacmn *pcm) {
   int i;
   counter++;
   printf("[%d] Hello, GrADS v2.0 World! \n", counter);
   for (i=0; i<argc; i++)
   printf("    argv[%d] = <%s>\n", i, argv[i]);
   return 0;
}
/* Sample Hello, World! user defined function */
int f_hello (struct gafunc *pfc, struct gastat *pst) {
 int rc;
 counter++;
 printf("[%d] Hello, GrADS v2.0 World!\n", counter);
 rc = gaexpr("0",pst);                    /* return a zero grid  */
 return (rc);
}