Creating Lasso Methods

When Lasso first starts up, it looks for module files (Windows DLLs, OS X DYLIBs, or Linux SOs) in its “LassoModules” directory. As it encounters each module, it executes that module’s registerLassoModule function once and only once. LCAPI developers must write code to register each new custom method (or type or data source connector) in this registerLassoModule function. The following example function is required in every LCAPI module. It gets called once when Lasso starts up:

void registerLassoModule() {
   lasso_registerTagModule( "CAPITester", "testtag", myTagFunc,
      REG_FLAGS_TAG_DEFAULT, "simple test LCAPI tag" );
}

The preceding example registers a C function named myTagFunc to execute whenever the Lasso CAPITester_testtag method call is encountered in Lasso code. The first parameter CAPITester is the namespace in which testtag will be placed.

Once the method function is registered, Lasso will call it at appropriate times while parsing and executing Lasso code. The custom method functions will not be called if none of the custom methods are encountered while executing a script. When Lasso encounters one of your custom methods, it will be called with two parameters: an opaque data structure called a token, and an integer action which is currently unused. LCAPI provides many function calls that can get information about the environment, variables, parameters, etc., when provided with a token.

The passed-in token can also be used to acquire any parameters and to return a value from your custom method function.

Basic Custom Method Function

Use the following C++ code:

osError myTagFunc(lasso_request_t token, tag_action_t action)
{
   const char * retString = "Hello, World!";
   return lasso_returnTagValueString(token, retString, strlen(retString));
}

Below is the Lasso code needed to get the custom method to execute:

<p>Here is the custom tag:</p>
[CAPITester_testtag]
<!-- This should display "Hello, World" when this page executes -->

This will produce:

Here is the custom tag:
Hello, World

Custom Method Tutorial

This section provides a walkthrough of building an example method to show how LCAPI features are used. This code can be found in the “SampleMethod” folder in the LCAPI examples, which can be downloaded from this site.

The method will simply display its parameters, and it will look like the example below when called in Lasso code:

sample_method('some text here', -option1='named param', -option2=12.5)

Notice the method takes one unnamed parameter, one string keyword parameter -option1, and one numeric keyword parameter -option2. For keyword parameters, Lasso does not care about the order in which you pass them, so plan to make this method as flexible as possible by not assuming anything about their order. The following variations should work exactly the same:

sample_method('some text here', -option1='named param', -option2=12.5)
sample_method('some text here', -option2=12.5, -option1='named param')

LCAPI Method Module Code

Below is the C++ code for the custom method:

void registerLassoModule()
{
   lasso_registerTagModule( "sample", "method", myTagFunc,
      REG_FLAGS_TAG_DEFAULT, "sample test" );
}

osError myTagFunc( lasso_request_t token, tag_action_t action )
{
   std::basic_string<char> retValue;
   lasso_type_t opt2 = NULL;
   auto_lasso_value_t v;
   INITVAL(&v);

   if( lasso_findTagParam(token, "-option1", &v) == osErrNoErr ) {
      retValue.append("The value of -option1 is ");
      retValue.append(v.data);
   }

   if( lasso_findTagParam2(token, "-option2", &opt2) == osErrNoErr ) {
      double tempValue;
      char tempValueFmtd[128];

      lasso_typeGetDecimal(token, opt2, &tempValue);
      sprintf(tempValueFmtd, "%.15lg", tempValue);

      retValue.append(" The value of -option2 is ");
      retValue.append(tempValueFmtd);
   }

   int count = 0;
   lasso_getTagParamCount(token, &count);

   for( int i = 0; i < count; ++i )
   {
      lasso_getTagParam(token, i, &v);
      if( v.name == v.data ) {
         retValue.append(" The value of unnamed param is ");
         retValue.append(v.data);
      }
   }

   return lasso_returnTagValueString(token, retValue.c_str(), (int)retValue.length());
}

Method Module Code Walkthrough

This section provides a step-by-step walkthrough of the code for the custom method module.

  1. First, the new method is registered in the required registerLassoModule export function:

    void registerLassoModule()
    {
       lasso_registerTagModule( "sample", "method", myTagFunc,
          REG_FLAGS_TAG_DEFAULT, "sample test" );
    }
    
  2. Implement myTagFunc, which gets called when sample_method is encountered. All method functions have this prototype. When the method function is called, it’s passed an opaque token data structure.

    osError myTagFunc( lasso_request_t token, tag_action_t action )
    {
    

    The remainder of the code in the walkthrough includes the implementation for the myTagFunc function.

  3. Allocate a string to be this method’s return value:

    std::basic_string<char> retValue;
    
  4. The lasso_type_t variable named “opt2” and the auto_lasso_value_t variable named “v” will be temporary variables for holding parameter values. Start off by initializing them:

    lasso_type_t opt2 = NULL;
    auto_lasso_value_t v;
    INITVAL(&v);
    
  5. Call lasso_findTagParam in order to get the value of the -option1 parameter. If it is found (no error while finding the named parameter), append some information about it to our return value string:

    if( lasso_findTagParam(token, "-option1", &v) == osErrNoErr ) {
       retValue.append("The value of -option1 is ");
       retValue.append(v.data);
    }
    
  6. Look for the other named parameter -option2 and store its value into variable “opt2”. Because -option2 should be a decimal value, use lasso_findTagParam2, which will preserve the original data type of the value as opposed to converting it into a string like lasso_findTagParam will.

    if( lasso_findTagParam2(token, "-option2", &opt2) == osErrNoErr ) {
    
  7. Declare a temporary floating-point (double) value to hold the number passed in and then declare a temporary string to hold the converted number for display. Get the value of “opt2” as a decimal then print it to the “tempValueFmtd” variable.

    double tempValue;
    char tempValueFmtd[128];
    
    lasso_typeGetDecimal(token, opt2, &tempValue);
    sprintf(tempValueFmtd, "%.15lg", tempValue);
    
  8. Append the parameter’s information to the return string:

    retValue.append(" The value of -option2 is ");
    retValue.append(tempValueFmtd);
    
  9. Now, we’re going to look for the unnamed parameter. Because there’s no way to ask for unnamed parameters, we’re going to enumerate through all the parameters looking for one without a name. The integer “count” will hold the number of parameters found. Use lasso_getTagParamCount to find out how many parameters were passed into our method. The variable “count” now contains the number “3”, if we were indeed passed three parameters.

    int count = 0;
    lasso_getTagParamCount(token, &count);
    
    for( int i = 0; i < count; ++i )
    {
    
  10. Use lasso_getTagParam to retrieve a parameter by its index. If you design methods that require parameters to be in a particular order, use this function to retrieve parameters by index, starting at index 0. If the parameter is unnamed, that means it’s the one needed. Note that if the user passes in more than one unnamed parameter, this loop will find all of them, and will ignore any named parameters. (A parameter is unnamed if both the name and data of the struct point to the same value.)

    lasso_getTagParam(token, i, &v);
    if( v.name == v.data ) {
    
  11. Again, append a descriptive line of text about the unnamed parameter and its value.

    if( v.name == v.data ) {
       retValue.append(" The value of unnamed param is ");
       retValue.append(v.data);
    }
    
  12. Returning an error code is very important. If you return a non-zero error code, the interpreter will throw an exception indicating that this method failed fatally, causing Lasso’s standard page error routines to display an error message. In our example, lasso_returnTagValueString will return an error if it has a problem setting the return value.

    return lasso_returnTagValueString(token, retValue.c_str(), (int)retValue.length());