Skip to content

hku-ect/libsphactor

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Build Status Build status

libsphactor

"Extended nodal actor framework based on zactor"

Prototype Build Guide

OSX

Building Dependencies

There are two main dependencies:

  • libzmq
  • czmq

Dependencies for the build process / dependencies are:

  • git, libtool, autoconf, automake, cmake, make, pkg-config, pcre,

Building them should be pretty straight forward:

  • Get dependencies via brew:
brew install libtool autoconf automake pkg-config cmake make zeromq czmq

Building Libsphactor

Once the above dependencies are installed, you are ready to build libsphactor. The process for this is much the same:

  • Clone the repo
git clone http://github.com/hku-ect/libsphactor.git
  • Build the project
cd libsphactor
./autogen.sh
./configure
make
# optionally test the library
SPHACTOR_SOCKET_LIMIT=30 make check
sudo make install

See the minimal example below. Should work on OSX as well.

Creating an XCode project

  • Create a new macOS - Command Line Tool project
  • Enter a product name and other details, select C as the language
  • Select a folder
  • You'll be provided with an example C file. Paste the minimal example source from below to replace the provided C example
  • Select the project on the left pane. Goto Build Settings and select All + Combined
  • Look for "Search paths"
    • Add /usr/local/include to "Header Search Paths"
    • Add /usr/local/lib to "Library Search Paths"
  • Look for "Linking"
    • Add "-lsphactor" and "-lczmq" to "Other Linker Flags"

You can now run the program.

If you want to work on the library it self it is best to use Cmake to build a Xcode project. from the repository's root run:

mkdir xcodeproj
cd xcodeproj
cmake -G Xcode ..

This should generate a valid Xcode project that can run and pass tests.

Latest dependencies

Sometimes you need the latest dependencies. Here's how:

First uninstall already installed libs (optional):

brew uninistall zeromq czmq

Clone & build libzmq & czmq

git clone git://github.com/zeromq/libzmq.git
cd libzmq
./autogen.sh
./configure
make check
sudo make install
cd ..

git clone git://github.com/zeromq/czmq.git
cd czmq
./autogen.sh && ./configure && make check
sudo make install
cd ..

Debian/Ubuntu Linux

(tested on ubuntu 16.04)

Install dependencies

sudo apt-get update
sudo apt-get install -y \
    build-essential libtool \
    pkg-config autotools-dev autoconf automake \
    uuid-dev libpcre3-dev libsodium-dev libzmq5-dev libczmq-dev

Clone this repo, build and install

git clone https://github.com/hku-ect/libsphactor.git
cd libsphactor
./autogen.sh
./configure && make
sudo make install

You can now use libsphactor as a static (/usr/local/lib/libsphactor.a) or dynamic lib (/usr/local/lib/libsphactor.so). Include file are in /usr/local/include.


Windows

For windows you'll need the latest Visual Studio (i.e. 2019) and cmake.

From a Visualstudio command prompt use the following commands to build everything in c:\projects with binaries in c:\tmp

libzmq

set INSTALL_PREFIX=C:\tmp\build
set LIBZMQ_SOURCEDIR=C:\projects\libzmq
set LIBZMQ_BUILDDIR=%LIBZMQ_SOURCEDIR%\build
git clone --depth 1 --quiet https://github.com/zeromq/libzmq.git "%LIBZMQ_SOURCED
md "%LIBZMQ_BUILDDIR%"
cd "%LIBZMQ_BUILDDIR%"
cmake .. -DBUILD_STATIC=OFF -DBUILD_SHARED=ON -DZMQ_BUILD_TESTS=OFF -DCMAKE_INSTALL_PREFIX="%INSTALL_PREFIX%"
cmake --build . --config %Configuration% --target install

cmzq

set CZMQ_SOURCEDIR=C:\projects\czmq
set CZMQ_BUILDDIR="%CZMQ_SOURCEDIR%\build"
git clone --depth 1 --quiet https://github.com/zeromq/czmq.git "%CZMQ_SOURCEDIR%"
md "%CZMQ_BUILDDIR%"
cd "%CZMQ_BUILDDIR%"
cmake .. -DCZMQ_BUILD_STATIC=OFF -DCZMQ_BUILD_SHARED=ON -DCMAKE_PREFIX_PATH="%INSTALL_PREFIX%" -DCMAKE_INSTALL_PREFIX="%INSTALL_PREFIX%"
cmake --build . --config %Configuration% --target install

libsphactor

set SPH_SOURCEDIR=C:\projects\libsphactor
set SPH_BUILDDIR=%SPH_BUILDDIR%\build
git clone --depth 1 --quiet https://github.com/hku-ect/libsphactor.git "%SPH_SOURCEDIR%"
md "%SPH_BUILDDIR%"
cd "%SPH_BUILDDIR%"
cmake .. -DSPHACTOR_BUILD_STATIC=OFF -DSPHACTOR_BUILD_SHARED=ON -DCMAKE_C_FLAGS="-DCZMQ_BUILD_DRAFT_API=1" -DCMAKE_PREFIX_PATH="%INSTALL_PREFIX%" -DCMAKE_INSTALL_PREFIX="%INSTALL_PREFIX%"
cmake --build . --config Debug --target install
ctest -C Debug -V

Minimal example in C (Linux with gcc)

test.c:

#include <sphactor_library.h>
#include <czmq.h>

//  An actor is a method wich receives a sphactor_event as an argument
//  and returns a zmsg_t. Zmsg_t is just a message we can send.
static zmsg_t *
hello_sphactor(sphactor_event_t *ev, void *args)
{
    if ( ev->msg == NULL ) return NULL;
    assert(ev->msg);
    //  just echo what we receive
    char *cmd = zmsg_popstr(ev->msg);
    zsys_info("Hello actor %s says: %s", ev->name, cmd);
    zstr_free(&cmd);
    // if there are strings left publish them
    if ( zmsg_size(ev->msg) > 0 )
    {
        return ev->msg;
    }
    else
    {
        zmsg_destroy(&ev->msg);
    }
    return NULL;
}

//  This is identical to the first hello_actor
static zmsg_t *
hello_sphactor2(sphactor_event_t *ev, void *args)
{
    if ( ev->msg == NULL ) return NULL;
    assert(ev->msg);
    // just echo what we receive
    char *cmd = zmsg_popstr(ev->msg);
    zsys_info("Hello2 actor %s says: %s", ev->name, cmd);
    zstr_free(&cmd);
    // if there are strings left publish them
    if ( zmsg_size(ev->msg) > 0 )
    {
        return ev->msg;
    }
    else
    {
        zmsg_destroy(&ev->msg);
    }
    return NULL;
}

int main()
{
    //  create two actors
    sphactor_t *hello1 = sphactor_new ( hello_sphactor, NULL, NULL, NULL);
    sphactor_t *hello2 = sphactor_new ( hello_sphactor2, NULL, NULL, NULL);

    //  connect the two actors to each other
    sphactor_connect(hello1, sphactor_endpoint(hello2));
    sphactor_connect(hello2, sphactor_endpoint(hello1));

    //  send multiple strings to the first actor
    zstr_sendm( sphactor_socket(hello1), "SEND");  // this is an API command
    zstr_sendm( sphactor_socket(hello1), "HELLO"); // first string
    zstr_sendm( sphactor_socket(hello1), "WORLD"); // etc...
    zstr_sendm( sphactor_socket(hello1), "AND");
    zstr_sendm( sphactor_socket(hello1), "ALIEN");
    zstr_send( sphactor_socket(hello1), "SPACELINGS"); // finish message construction and send the message

    zclock_sleep(10); //  give some time for the test to complete, since it's threaded

    sphactor_destroy (&hello1);
    sphactor_destroy (&hello2);

    return 0;
}

Build this file and run:

gcc -o test main.c -lczmq -lsphactor
./test

If correct it wil show:

I: 19-12-03 13:20:49 Hello2 actor A8D382 says: HELLO
I: 19-12-03 13:20:49 Hello actor C3FA9D says: WORLD
I: 19-12-03 13:20:49 Hello2 actor A8D382 says: AND
I: 19-12-03 13:20:49 Hello actor C3FA9D says: ALIEN
I: 19-12-03 13:20:49 Hello2 actor A8D382 says: SPACELINGS

You can also use the static lib instead of the dynamic one:

gcc -o test main.c /usr/local/lib/libsphactor.a /usr/lib/x86_64-linux-gnu/libczmq.a -l zmq -lpthread

Minimal example in C++

Please note for C++ you need to include libsphactor.hpp instead of libsphactor.h!

#include <iostream>
#include "libsphactor.hpp"

// g++ sphactor_selftest.cpp -o test -I ../include/ .libs/libsphactor.a -l czmq

class Test
{
public:

    Test() {
    }

    ~Test() { }

    zmsg_t *
    handleMsg( sphactor_event_t *event ) {
        // just print the event
        printf("name: %s, type: %s", ev->name, ev->type);
        if ( event->msg == nullptr ) return nullptr;
        char *cmd = zmsg_popstr(event->msg);
        zsys_info("Cpp actor %s says: %s", event->name, cmd);
        // if there are strings left publish them
        if ( zmsg_size(event->msg) > 0 )
        {
            return event->msg;
        }
        else
        {
            zmsg_destroy(&event->msg);
        }
        return nullptr;
    }
};

int main()
{
    Test *a = new Test()
    Test *b = new Test();

    // register the Test class as an actor
    sphactor_register("cpp test", sphactor_member_handler<Test>);

    // create actor controllers for the actors
    sphactor_t *actora = sphactor_new(a, "hello-a", nullptr);
    sphactor_t *actorb = sphactor_new_by_type("cpp test", b, "hello-b", nullptr);

    // get the actor name
    const char *name = sphactor_ask_name(actora);
    assert( streq(name, "hello-a"));

    // set actora to be verbose
    sphactor_ask_set_verbose(actora, true);

    // connect the actors to each other
    sphactor_ask_connect(actora, sphactor_ask_endpoint(actorb));
    sphactor_ask_connect(actorb, sphactor_ask_endpoint(actora));
    zclock_sleep(10); // give time to connect

    // initiate a SEND (SEND API command just sends what it receives)
    zstr_sendm(sphactor_socket(actora), "SEND");
    zstr_sendm(sphactor_socket(actora), "HELLO");
    zstr_sendm(sphactor_socket(actora), "WORLD");
    zstr_sendm(sphactor_socket(actora), "AND");
    zstr_sendm(sphactor_socket(actora), "ALIEN");
    zstr_send(sphactor_socket(actora), "SPACELINGS");
    zclock_sleep(10); // give time to see messages printed

    // cleanup
    sphactor_destroy(&actora);
    sphactor_destroy(&actorb);
    delete( a );
    delete( b );
    sphactor_dispose();

    return 0;
}

Compile with:

g++ test.cpp -o test -lsphactor -lczmq

As a convenience you can also inherit the Sphactor class:

class Test : public Sphactor
{
public:

    Test() {
    }

    ~Test() { }
    
    // handle initialisation
    zmsg_t * handleInit(sphactor_event_t *ev)
    
    // handle timed events
    zmsg_t * handleTimer(sphactor_event_t *ev) { if ( ev->msg ) zmsg_destroy(&ev->msg); return nullptr; }

    // handle your own API commands
    zmsg_t * handleAPI(sphactor_event_t *ev) { if ( ev->msg ) zmsg_destroy(&ev->msg); return nullptr; }

    // handle receiving messages
    zmsg_t * handleSocket(sphactor_event_t *ev) { if ( ev->msg ) zmsg_destroy(&ev->msg); return nullptr; }

    // handle stopping your actor (destroying it is handled for you in the base class)
    zmsg_t * handleStop(sphactor_event_t *ev) { if ( ev->msg ) zmsg_destroy(&ev->msg); return nullptr; }
};

About

"Extended nodal actor framework based on zactor"

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published