Writing your first C module
The AOLServer C API is very easy to develop towards. This short tutorial takes you through construction of an "nshello" module that provides a "ns_hello" function.
Step 0: Requirements
You need (at least) ns.h and Makefile.module.
On Debian, simply:
apt-get install aolserver4-dev
Step 1: Write your module code, "nshello.c" (this can be any name you like):
/* * Get the data types and constants you will need later on, * such as Tcl_Interp and NS_OK. */ #include "ns.h" #include <string.h> #include <sys/types.h> /* * Each module asserts its version via the required Ns_ModuleVersion variable */ int Ns_ModuleVersion = 1; /* * Declare that this module will implement this initialization method. */ int Ns_ModuleInit(char *hServer, char *hModule); /* * This can be named whatever you like, it is used during module initialisation * to contain specific initialisation steps for the Tcl interpreter itself, * such as registering commands like "ns_hello". */ static int HelloInterpInit(Tcl_Interp *interp, void *context); /* * Declare a C function that will be bound to the "ns_hello" Tcl command. */ static int HelloCmd(ClientData context, Tcl_Interp *interp, int argc, char **argv); /* * Implement the Ns_ModuleInit function we declared we would implement earlier. * This is called by the server right after the module is loaded. Here, you * can read configuration data, initialise internal data, and of course * register any Tcl commands. */ int Ns_ModuleInit(char *hServer, char *hModule) { /* * Invoke the server's Tcl interpreter initialisation and pass * it the callback we defined to our own interpreter initialisation. */ return (Ns_TclInitInterps(hServer, HelloInterpInit, NULL)); } /* * Implement the interpreter initialisation we declared and passed * during module init. Use Tcl_CreateCommand to register * the command "ns_hello", passing a callback to "HelloCmd" which * we declared earlier. */ static int HelloInterpInit(Tcl_Interp *interp, void *context) { Tcl_CreateCommand(interp, "ns_hello", HelloCmd, NULL, NULL); return NS_OK; } /* * Append "hello" and then all arguments to the result. */ static int HelloCmd(ClientData context, Tcl_Interp *interp, int argc, char **argv) { int i; Tcl_AppendResult(interp, "hello", NULL); for (i = 0; i < argc; i++) { Tcl_AppendResult(interp, " ", NULL); Tcl_AppendResult(interp, argv[i], NULL); } return NS_OK; }
That's it. That's an entire module.
Step 2: Build your module.
AOLServer includes a meta-Makefile Makefile.module that simplifies the construction of module makefiles. Simply define a few values in your owm Makefile, then include this meta-Makefile.
# # Module name # MOD = nshello.so # # Objects to build # OBJS = nshello.o # # Header files in THIS directory # HDRS = # # Extra libraries # MODLIBS = # # Compiler flags # CFLAGS = include /usr/lib/aolserver4/Makefile.module
Done. Now you can build your module with 'make'.
You should now have a nifty "nshello.so" shared object library sitting around. Copy "nshello.so" to /usr/lib/aolserver4/bin (or where you keep your server modules).
Step 3: Tell aolserver to load the module (/etc/aolserver4/aolserver4.tcl):
ns_section "ns/server/${servername}/modules" ns_param nshello nshello.so
Done. Restart aolserver and check the log file for errors.
Step 4: Use the function "ns_hello" in an ADP script:
<% ns_adp_puts [ns_hello "AOLServer module" "world!"] %>
Whoa! You get a strange result: hello ns_hello AOLServer module world!
Notice that "ns_hello" in there? That's because argv[0] is actually the name of the function used to call your interpreter! So, keep that in mind and happy AOLServer module hacking!