Write a C/C++ function that computes distances to the Event Stream Processor interface. After compiling the function to a shared library, declare it using the CREATE LIBRARY statement, and call the function as needed in your CCL project.
For example, this function computes distance:
#include math.h double distance(int numvals, double * vals){ double sum = 0.0; for (int i=0; i<numvals; i++){ sum += vals[i]*vals[i]; } return sqrt(sum); }
To conform to the interface of the Event Stream Processor, write the function as:
#include <math.h> #include <vector> #include "DataValue.hpp" using namespace std; #ifdef _WIN32 #define __DLLEXPORT__ __declspec(dllexport) #else #define __DLLEXPORT__ #endif /************************************************************** * This function computes the distance using the given * arguments. * @numargs - Number of arguments to this function. * @top - Points to the last argument. Also holds the * return value from this function. * @nextArgs - The remaining arguments in the order provided. * @arena - Anything assigned to the arena is freed by the * the server. NOTE: Do not assign return values * to the arena. Also anything to be freed must * be allocated using malloc only (DO NOT USE new). *****************************************************************/ extern "C" __DLLEXPORT__ int32_t distance(int numargs, DataTypes::DataValue * top, DataTypes::DataValue * nextArgs, std::vector<void *>& arena){ double sum = 0.0; if (numargs <= 0){ //Return value top->setDouble(0.0); //Return code. return 0; } //If any of the arguments is null result is null. if(top->null) return 0; //Top of the stack points to the last argument. double dist = top->val.doublev * top->val.doublev; //Processes the arguments from last to first. for(int i=numargs-2; i>=0; i--){ //If any of the arguments is null result is null if((nextArgs+i)->null){ top->null = true; return 0; } //accumulate the square of the distances. dist +=(nextArgs + i)->val.doublev * (nextArgs + i)->val.doublev; } //Return value top->setDouble(sqrt(dist)); //Return code. return 0; }
The extern declaration ensures the function has the same name within the library and not the C++ function name.
The __DLLEXPORT__ preprocessor macro must be defined under Windows to make the external function available to ESP.
gcc -fPIC -shared -m64 -I.. -c -o distance.o distance.cpp gcc -fPIC -shared -m64 distance.o -o distance.so
CREATE LIBRARY DistanceLib LANGUAGE C FROM 'distance.so'( float distance(float, float, float); );
Ensure the name of the function matches the name of the function in the library.