Developing C++ primitive operators

There are two types of C++ primitive operators: non-generic and generic.

Non-generic operators are written entirely in C++. There are two kinds of non-generic primitive operators: Hardcoded operators that use only the attribute-based API generated by the complier, and operators that use runtime reflection to inspect the type of tuples.

Generic operators use a mixed-mode templating system. Mixed-mode uses Perl code to generate the correct C++ code. By using the compile-time Perl API available in mixed-mode, SPL programmers can define operators that are fully type parametric (they can accept and manipulate any kind of stream type). Writing operator templates in mixed-mode is the most powerful means to develop operators. All of the operators in the SPL Standard Toolkit are defined as mixed-mode.

For more information, see Operators implemented in C++ and Developing C++ primitive operators.

Creating a C++ primitive operator

Create a C++ primitive operator that you can use in your streaming applications. See the C++ primitive operator guide for a complete example.

Procedure

  1. Add your Streams 5.5 instance to the Streams Explorer in VS Code if you haven’t already.
  2. Bring up the Command Palette and select Create C++ Primitive Operator.
  3. Follow the prompts to create the C++ primitive operator. Specify the following:

    • Project folder path: The project folder path for the primitive operator. Use the Browse… button to create and select an empty folder on your machine. The primitive operator files will be created in this folder.
    • Operator namespace: The SPL namespace for the primitive operator.
    • Operator name: The name of the primitive operator.
    • Generic operator: The SPL language supports writing two styles of C++ primitive operators, namely: generic operators and non-generic operators.
      • Generic operators can handle various stream types, different numbers of ports, and most importantly, can be configured with parameters and output assignments that involve SPL expressions.
      • Alternately, non-generic operators are less configurable and are often used for one-time tasks that do not require high levels of reuse.

Results

Based on the selected operator type, a C++ primitive operator is created in the specified project folder with the following artifacts:

  • Operator model (<operator-name>.xml): An XML file that describes syntactic and semantic properties of the operator.
  • Code generator templates (<operator-name>_*.cgt): The header and the implementation files that contain the operator logic.
  • Code generators (<operator-name>_*.pm): The code generators, in the form of Perl modules, which are derived from the code generator templates.

The folder structure for the C++ project is:

/+ <project-folder>
   /+ <operator-namespace>
      /+ <operator-name>
         /+ <operator-name>.xml
         /+ <operator-name>_cpp.cgt
         /+ <operator-name>_cpp.pm
         /+ <operator-name>_h.cgt
         /+ <operator-name>_h.pm
   /+ impl
      /+ include
      /+ lib
      /+ src
   /+ Makefile

Note that a Makefile file is also created. This is used to build the C++ primitive operator. The file looks like:

TOOLKIT_NAME=<project-folder>

all: build-toolkit

build-toolkit:
	$(STREAMS_INSTALL)/bin/spl-make-toolkit -i . -m -n $(TOOLKIT_NAME)

What to do next

Implement the primitive operator by customizing the code generator templates. This depends on the operator type you chose.

Use the comments in the files as guides.

For more information, see Developing C+++ primitive operators.

When you’re ready, build the C++ primitive operator to generate a toolkit that you can use in your streaming applications.

Building a C++ primitive operator

Build a C++ primitive operator to generate a toolkit that you can use in your streaming applications. See the C++ primitive operator guide for a complete example.

Before you begin

Your C++ project must have the following folder structure.

Note: If you created your operator using the Create C++ Primitive Operator command, then your project will have been created with the correct structure.

/+ <project-folder>
   /+ <operator-namespace>
      /+ <operator-name>
         /+ <operator-name>.xml
         /+ <operator-name>_cpp.cgt
         /+ <operator-name>_cpp.pm
         /+ <operator-name>_h.cgt
         /+ <operator-name>_h.pm
   /+ impl
      /+ include
      /+ lib
      /+ src
   /+ Makefile

The Makefile must build a toolkit using spl-make-toolkit. A simple Makefile would be the following:

TOOLKIT_NAME=<project-folder>

all: build-toolkit

build-toolkit:
	$(STREAMS_INSTALL)/bin/spl-make-toolkit -i . -m -n $(TOOLKIT_NAME)

Procedure

  1. Add your Streams 5.5 instance to the Streams Explorer in VS Code if you haven’t already.
  2. Right-click on a C++ project folder, .xml file, .pm file, or .xml file and select Build C++ Primitive Operator.
  3. Follow the prompts to submit the build.

Results

After a build completes successfully, the indexed toolkit is extracted to the project folder (overwriting the existing files). You will be presented with two options:

  • Download Toolkit: Downloads the toolkit archive file (.tgz) to the toolkit folder.
  • Add Toolkit to Toolkit Path: Adds the toolkit to a toolkit path folder (defined in the Toolkit Paths setting). This makes the indexed toolkit available to use in your Streams applications.

The toolkit will have the following folder structure. The authored files are marked with + and generated files are marked with *.

/+ <project-folder>
   /+ <operator-namespace>
      /+ <operator-name>
         /+ <operator-name>.xml
         /+ <operator-name>_cpp.cgt
         /* <operator-name>_cpp.pm
         /+ <operator-name>_h.cgt
         /* <operator-name>_h.pm
   /+ Makefile
   /* toolkit.xml

What to do next

Learn how to use the toolkit in your SPL applications here.