Next Previous Contents

3. Basic functions

3.1 Initialization and main loop

Initializing an Ivy agent with the Ivy C library is a two step process. First of all, you should initialize the library by calling function IvyInit. Once the library is initialized you can create timers and add subscriptions, but your agent is still not connected to any bus. In order to connect, you should call function IvyStart. In theory, initialization is then over. However in practice, as for any asynchronous communication or interaction library, nothing happens until your application has reached the main loop.

The Ivy C library provides its own main loop: IvyMainLoop. You should use it unless you already use a toolkit that provides its own main loop and you want to use that one. If it is the case, please refer to section XX. Otherwise, just call IvyMainLoop. From within the main loop, you can call IvyStop to exit the loop.

Here are more details on those functions:

void IvyInit (const char* agentname,
                        const char* hello_msg,
                        IvyApplicationCallback app_cb,
                        void *app_data,
                        IvyDieCallback die_cb,
                        void *die_data);
initializes the library. blahblah

void IvyStart (const char* bus);
connects your application to the bus specified in bus. The string provided should follow the convention described in section XX. Example: "127:2010".

void IvyMainLoop (void (*hook) (void));
makes your application enter the main loop in which it will handle asynchronous communications and signals.

void IvyStop ();
makes your application exit the main loop.

3.2 Emitting messages

Emitting a message on an Ivy bus is much like printing a message on the standard output. However, do not forget that your message will not be emitted if Ivy has not been properly initialized and if you do not have a main loop of some sort running. To emit a message, use IvySendMsg, which works like printf:

void IvySendMsg (const char* format, ...);
sends a message on the bus. This function has exactly the same behaviour as printf, sprintf or fprintf.

3.3 Subscribing to messages

Subscribing to messages consists in binding a callback function to a message pattern. Patterns are described by regular expressions with captures. When a message matching the regular expression is detected on the bus, the callback function is called. The captures (ie the bits of the message that match the parts of regular expression delimited by brackets) are passed to the callback function much like options are passed to main. Use function IvyBindMsg to bind a callback to a pattern, and function IvyUnbindMsg to delete the binding.

MsgRcvPtr IvyBindMsg (MsgCallback cb,
                void* data,
                const char* regex_format, ...);
binds callback function cb to the regular expression specified by regex_format and the optional following arguments. regex_format and the following arguments are handled as in printf.

void IvyUnbindMsg (MsgRcvPtr id);
deletes the binding specified by id

In what precedes, MsgRcvPtr is an opaque type used to identify bindings, data is a user pointer passed to the callback whenever it is called, and Msgcallback is defined as follows:

typedef void (*MsgCallback)(IvyClientPtr app, void *data, int argc, char **argv);

3.4 Example

The following application connects to an Ivy bus, translates messages "Hi [name]" to "Bonjour [name]", and quits on message "Bye".

#include <stdlib.h>
#include <stdio.h>
#include <getopt.h>
#include <ivy.h>
#include <ivyloop.h>

/* callback associated to "Hi" messages */
void HiCallback (IvyClientPtr app, void *data, int argc, char **argv)
{
        if (argc != 1)
                fprintf (stderr, "wrong format!\n");
        else
                IvySendMsg ("Bonjour %s", argv[0]);
}

void ByeCallback (IvyClientPtr app, void *data, int argc, char **argv)
{
        IvyStop ();
}

main (int argc, char**argv)
{
        /* handling of -b option */
        const char* bus = 0;
        char c;
        while (c = getopt (argc, argv, "b:") != EOF) {
                switch (c) {
                case 'b':
                        bus = optarg;
                        break;
                }
        }

        /* handling of environment variable */
        if (!bus)
                bus = getenv ("IVYBUS");

        /* initializations */
        IvyInit ("MagicTranslater", "Hello le monde", 0, 0, 0, 0);
        IvyStart (bus);

        /* bindings */
        IvyBindMsg (HiCallback, 0, "^Hi (.*)");
        IvyBindMsg (ByeCallback, 0, "^Bye$");

        /* main loop */
        IvyMainLoop (0);
}


Next Previous Contents