Function models for C++ native functions

To create a function model, you create a function.xml file that is structured as a sequence of one or more functionSet elements.

The functionSet element from the schema for the function.xml represents the set of native functions declared within or included from a C++ header file. It contains three subelements. The first one is the headerFileName element, which contains the name of the header file that declares the C++ functions or includes other header files that declare them. The second (optional) element is named cppNamespacename, which gives the C++ namespace for the functions. If the cppNamespacename element is not present, the SPL namespace, with "." converted to "::" is used. The third element is named functions, which contains a sequence of one or more function elements, each representing a native function signature in SPL format. An optional cppName attribute specifies the C++ name of the function. If not present, the SPL function name is used. The fourth element is an optional one, named dependenciesType. It is a sequence of one or more library elements, each representing a library dependency. The library element format is the same as the one used for operator models. Library dependencies specify the include directories, library paths, and library names that are required to compile and link SPL applications to use the functions that are listed in the function set.

A function model sample
<functionModel 
   xmlns="http://www.ibm.com/xmlns/prod/streams/spl/function" 
   xmlns:cmn="http://www.ibm.com/xmlns/prod/streams/spl/common" 
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
   xsi:schemaLocation="http://www.ibm.com/xmlns/prod/streams/spl/function functionModel.xsd"> 
  <functionSet> 
    <!-- header file to include from within C++ code --> 
    <headerFileName>Sample.h</headerFileName> 
    <!-- functions lists the SPL prototypes of the functions implemented in this library --> 
    <functions> 
      <!-- use of CDATA allows easy use of < in the prototypyes --> 
      <function>
        <description>Increment all list elements by a given amount</description>
        <prototype cppName="increment_by"><![CDATA[ void incrementBy(mutable list<int32> l, 
int32 incr) ]]></prototype>
</function> <function> <description>Join two lists</description> <prototype><![CDATA[ list<int32> joinLists(list<int32> a, list<int32> b) ]]></prototype> </function> </functions> <dependencies> <!-- This library can have several dependencies. We only use one here --> <library> <!-- A description for this library --> <cmn:description>Sample-Functions</cmn:description> <cmn:managedLibrary> <!-- the name of the library for linking. Will be used as -lSample --> <cmn:lib>Sample</cmn:lib> <!-- Where to find the library. Relative to the current directory. Will be used as -L<dir>/lib --> <cmn:libPath>lib</cmn:libPath> <!-- Where to find the include file. Relative to the current directory. Will be used as -I<dir> --> <cmn:includePath>./</cmn:includePath> </cmn:managedLibrary> </library> </dependencies> </functionSet> </functionModel>

The cppName attribute on routine incrementBy allows the SPL program to call routine incrementBy, but invokes the C++ routine increment_by, which must be declared in Sample.h. Use of cppName allows SPL programs to invoke C++ routines that might conflict with SPL keywords, or contain characters such as $ that are not allowed in most SPL identifiers.

The C++ header file that is needed for using the functions that are listed is named Sample.h. The native functions that are included in this function model file are implemented in a library that is described as Sample-Functions. The header files are in the directory ./, which is relative to the location of the function.xml file. The library path for the C++ library that implements the functions are in the ./lib directory, again relative to the directory that contains the function model file. Finally, the name of the C++ library name is Sample, which means that the library file is named as either libSample.so (dynamic) or libSample.a (static). The directory structure for this sample is:

/+ function.xml
/+ Sample.h  
/+ lib  
  /+ libSample.so
C++ libraries for more than one platform can also be provided. In this case, thecmn:command element can be used to pick the right one to use at compilation time. The following is such an example:
<library>
  <cmn:description>Sample-Functions</cmn:description>
  <cmn:managedLibrary>
    <cmn:libPath>lib</cmn:libPath>
    <cmn:includePath>./</cmn:includePath>
    <cmn:command>get-lib-conf</cmn:command>
  </cmn:managedLibrary>
</library>
The directory structure is:
/+ function.xml
/+ get-lib-conf
/+ Sample.h
/+ lib-x86_64
  /+ libSample.so
/+ lib-ppc64
  /+ libSample.so
The get-lib-conf script that is used in this example is as follows:
#!/bin/bash
if [ "$1" == "libPath" ]; then       
  arch=$(uname -m)
  if [ $arch == "x86_64" ]; then
    echo "./lib-x86_64"
  elif [ $arch == "ppc64" ]; then
    echo "./lib-ppc64"
  else
    echo "Unsupported platform $arch" >&2
    exit 1;
  fi
fi