[ICS] IVORY CITY STSTEMS
mod_perlservice  
c client api  


C API REFERENCE

QUESTIONS/COMMENTS/BUGS: michaelcollins@ivorycity.com

DOWNLOAD:
xwspc-1.0.4.tar.gz
xwspclient_example.tar.gz

METHOD SUMMARY:
XWSPClient*    XWSPClient_new ( char* hostname, char* application, char* file);
dsany XWSPClient_call ( XWSPClient* xwspc, XWSPService* svce, ... );
void XWSPClient_setHostContext ( XWSPClient* xwspc, char* hostname );
void XWSPClient_setApplicationContext ( XWSPClient* xwspc, char* application_name );
void XWSPClient_setFileContext ( XWSPClient* xwspc, char* filename );
char* XWSPClient_getErrStr ( XWSPClient* xwspc );
void XWSPClient_destroy ( XWSPClient* xwspc );

USER DATA STRUCTURES:
struct XWSPService
{
  char* objname; /*Name of the object you want to call*/
  char* methodname; /*Name of the method within the object*/
  int argtypes[16]; /*Up to 15 arguments (0 terminated) of the specified types*/
};

Argument types are:
INTARG An integer argument
FLOATARG A floating point number argument
DOUBLEARG A double precision float argument
STRINGARG A string (char* type) argument
DSANYARG A DSANY argument for complex data types, see the ds api

OVERVIEW:
If you've already looked over the Perl API reference, you'll notice that the C API uses a different object name, XWSPClient. Don't sweat it. XWSPClient is actually a more accurate name and serves the same purpose as PService. XWSP is the transport protocol for the mod_perlservice system. If you want to learn more about it, check out the internals page. But it doesn't have any relevence to how the system works, and that's what you're here for, so lets get started.

Now you're a C programmer so you probably know that all the magic available to us in Perl probably won't be available to us in C, but we do have a few pretty neat tricks left.

Here's the crux:

#include "XWSPClient.h"
XWSPService hello = { "myservice", "hello", {STRINGARG,0} };

int
main()
{
   XWSPClient* xwspc = XWSPClient_new("www.somehost.com","someapplication","somefile.pm");
   dsany retds = XWSPClient_call( xwspc, &hello, "This is my string argument" );
   XWSPClient_destroy(xwspc);
}

The above code first defines a global service called hello. If you look at the definition of struct XWSPService, it consists of an object name, a method name, and an argument list. 'hello' is defined as server method "hello" in package myservice, and we have indicated that we intend to pass it a string when we call it.

In main, we construct a XWSPClient object and initialize the host name, application name and file name to "www.somehost.com", "someapplication", and "somefile.pm" respectively. Now, we're ready to start calling the server, so we pass a pointer to the 'hello' XWSPService structure as the second argument of XWSPClient_call, and one string argument, as we indicated we would. The XWSPClient will now call myservice::hello on the remote server and store the return value back in retds. Make sure you pass the same number of arguments and the correct types that you indicated in your XWSPService definition! Otherwise you'll probably crash.

One other note, XWSPService structures do not have to be static. You can malloc them or create them on the stack, so you have quite a bit of runtime flexibility. You may want to consider this if you have a particularly large number of server side methods.

At this point, you may want to learn more about how dynamic, and complex data structures are implemented in this system. This is managed by the ds api (ds for data structures). The documentation can be found here.

METHOD DOCUMENTATION
XWSPClient* XWSPClient_new(char* hostname, char* application, char* file);

Construct a new XWSPClient object.

USAGE
XWSPClient* xwspc = XWSPClient_new( "www.somehost.com", "someapplication", "somefile.pm");

ARGUMENTS
char* hostname The fully qualified domain name or ip of the server running apache and mod_perlservice
char* application The alias name of the application you wish to use, see mod_perlservice docs for more.
char* file The name of the file that contains the code you want to use.

dsany XWSPClient_call(XWSPClient* xwspc, XWSPService* svce, ... );

Call the sub routine on the server using the pre-set server, application, and file contexts set in the XWSPClient structure, and object and method set in the XWSPService. This method takes a variable number of arguments, but make sure you pass the same number and type of args you specified in the service definition, or else you might crash. Your arguments will be encoded and sent along with your request, where they will magically appear in the server method's @_. One of the most useful and important features of this system is the ability to pass complex nested data structures as arguments and recieve the same as return values. You can accomplish this through passing dsany types which may include arrays of hashes or hashes mixed with arrays, scalars, and hashes. See the ds api for more on this.
If an error occurs during the call, the function returns an empty dsany and an error message is set, see XWSPClient_getErrStr.

USAGE
XWSPService hello1 = {"somepackage","hello",{STRINGARG,FLOATARG,INTARG,0}};
XWSPService hello2 = {"somepackage","hello",{DSANY,0}};
dsany retval = XWSPClient_call(xwspc,&hello1,"My String", 3.14, 42);

switch(retval.type)
{
  case DSSTRING: printf("\nString return: %s", retval.any.stringType); break;
  case DSINT: printf("\nInt Return: %d", retval.any.intType); break;
  case DSFLOAT: printf("\nFloat return: %f", retval.any.floatType); break;
  case DSANYARRAY: dsany vzero;
dsanyarray_get(retval.any.dsanyarrayType,4,&vzero);
printf("\ndsanyarray return: %s", vzero.any.stringType);
break;
  case DSTABLE: dsany qrslt;
dsquery(retval,"users.wonder.[4].rating");
printf("\nqueried table returned: %d rating", qrslt.any.intType);
break;
}

retval = XWSPClient_call(xwspc,&hello2,retval);
if(dsany_isstring(retval)) printf("\nServer Said: %s", dsS(retval) );

ARGUMENTS
XWSPClient* xwspc Your xwspc object.
XWSPService* svce Any defined XWSPService where package and method can be found in the resources defined in your xwspc object.
[...] The variable arguments as defined in the XWSPService

void XWSPClient_setHostContext ( XWSPClient* xwspc, char* hostname );

Change the name of the host where mod_perlservice can be found. Now, when you call a remote method, the XWSPClient will connect to the new server.

USAGE
XWSPClient_setHostContext(xwspc,"www.newhost.com");

ARGUMENTS
newhostname: The domain name or IP address of the server where your application files can be found.

void XWSPClient_setApplicationContext( XWSPClient* xwspc, char* application_name );

Change the name of the application you're using. The application is basically the working directory where your files are found.

USAGE
XWSPClient_setApplicationContext(xwspc,"my_new_app");

ARGUMENTS
newappname: The name of the application you want to start using.

void XWSPClient_setFileContext( XWSPClient* xwspc, char* filename );

Change the name of the file you're using. The file contains the packages/objects and methods you want to use.

USAGE
XWSPClient_setFileContext(xwspc,"my_file.pm");

ARGUMENTS
newfilename: The file you want to start using.

char* XWSPClient_getErrStr( XWSPClient* xwspc );

In the event that a remote method call fails, the return value will be an empty dsany and an error message will be set. Use XWSPClient_getErrStr to get a text representation of the error.

USAGE
char* err = XWSPClient_getErrStr(xwspc);

void XWSPClient_destroy( XWSPClient* xwspc );

Clean up the XWSPClient object, and free memory.

USAGE
XWSPClient_destroy(xwspc);




Copyright 2004 Michael W. Collins, Ivory City Systems.
You have permission to copy and redistribute this document so long as it contains this original copyright.