Update of /cvsroot/playerstage/code/player/examples/plugins/exampleinterface
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv24767/exampleinterface
Added Files:
Makefile.am Makefile.example README eginterf.c eginterf.h
eginterf_client.c eginterf_client.h eginterf_driver.cc
eginterf_xdr.c eginterf_xdr.h example.cfg example_client.c
Log Message:
Adding example plugin interface
--- NEW FILE: example.cfg ---
# This block describes a plugin interface. Note the interface name and code
# need to match what you set in your interface definition header. Also be
# careful not to conflict with any existing interface names and codes.
interface
(
name "eginterf"
code 100
plugin "libeginterf"
)
driver
(
name "eginterfdriver"
plugin "libeginterfdriver"
provides ["eginterf:0"]
)
--- NEW FILE: eginterf.h ---
/*
* The new interface is declared in this file. It consists of a few parts:
*
* #define'd interface code and name string
*
* These are used throughout the interface. Be careful not to conflict with
* existing Player interfaces when setting them.
*
* Message subtype codes
*
* These are used by both the client and the server to differentiate between
* different messages within the same type group (e.g. different types of data
* message).
*
* Message structures
*
* Each message structure defines the layout of data in the body of a message.
* One message structure can be used by multiple types and subtypes.
*
* Exported plugin interface function
*/
#ifndef __EGINTERF_H
#define __EGINTERF_H
#include <libplayerxdr/playerxdr.h>
#include <libplayerxdr/functiontable.h>
#define PLAYER_EGINTERF_CODE 100
#define PLAYER_EGINTERF_STRING "eginterf"
#define EGINTERF_DATA 1
#define EGINTERF_REQ 1
#define EGINTERF_CMD 1
typedef struct player_eginterf_data
{
uint32_t stuff_count;
double *stuff;
} player_eginterf_data;
typedef struct player_eginterf_req
{
int value;
} player_eginterf_req;
typedef struct player_eginterf_cmd
{
char doStuff;
} player_eginterf_cmd;
playerxdr_function_t* player_plugininterf_gettable (void);
#endif // __EGINTERF_H
--- NEW FILE: eginterf_driver.cc ---
/*
* This file implements a driver using the pluggable interface. See the plugin
* driver example for details of how it works.
*/
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <libplayercore/playercore.h>
#include "eginterf.h"
////////////////////////////////////////////////////////////////////////////////
// The class for the driver
class EgInterfDriver : public Driver
{
public:
// Constructor; need that
EgInterfDriver(ConfigFile* cf, int section);
// Must implement the following methods.
virtual int Setup();
virtual int Shutdown();
// This method will be invoked on each incoming message
virtual int ProcessMessage(MessageQueue* resp_queue,
player_msghdr * hdr, void * data);
};
// A factory creation function, declared outside of the class so that it
// can be invoked without any object context (alternatively, you can
// declare it static in the class). In this function, we create and return
// (as a generic Driver*) a pointer to a new instance of this driver.
Driver* EgInterfDriver_Init(ConfigFile* cf, int section)
{
// Create and return a new instance of this driver
return((Driver*)(new EgInterfDriver(cf, section)));
}
// A driver registration function, again declared outside of the class so
// that it can be invoked without object context. In this function, we add
// the driver into the given driver table, indicating which interface the
// driver can support and how to create a driver instance.
void EgInterfDriver_Register(DriverTable* table)
{
table->AddDriver("eginterfdriver", EgInterfDriver_Init);
}
////////////////////////////////////////////////////////////////////////////////
// Constructor. Retrieve options from the configuration file and do any
// pre-Setup() setup.
EgInterfDriver::EgInterfDriver(ConfigFile* cf, int section)
: Driver(cf, section, false, PLAYER_MSGQUEUE_DEFAULT_MAXLEN,
PLAYER_EGINTERF_CODE)
{
return;
}
////////////////////////////////////////////////////////////////////////////////
// Set up the device. Return 0 if things go well, and -1 otherwise.
int EgInterfDriver::Setup()
{
puts("EgInterfDriver initialising");
srandom (time (NULL));
puts("EgInterfDriver ready");
return(0);
}
////////////////////////////////////////////////////////////////////////////////
// Shutdown the device
int EgInterfDriver::Shutdown()
{
puts("Shutting EgInterfDriver down");
puts("EgInterfDriver has been shutdown");
return(0);
}
int EgInterfDriver::ProcessMessage(MessageQueue* resp_queue, player_msghdr *
hdr, void * data)
{
player_eginterf_data resp;
player_eginterf_req reqResp;
if (Message::MatchMessage (hdr, PLAYER_MSGTYPE_CMD, EGINTERF_CMD,
device_addr))
{
printf ("EgInterfDriver: Received command: %d\n",
reinterpret_cast<player_eginterf_cmd*> (data)->doStuff);
if (reinterpret_cast<player_eginterf_cmd*> (data)->doStuff)
{
resp.stuff_count =
reinterpret_cast<player_eginterf_cmd*> (data)->doStuff;
resp.stuff = new
double[reinterpret_cast<player_eginterf_cmd*> (data)->doStuff];
printf ("EgInterfDriver: Sending data:\n");
for (char ii = 0; ii <
reinterpret_cast<player_eginterf_cmd*> (data)->doStuff; ii++)
{
double temp = (((double) random ()) / RAND_MAX)
* 10.0f;
resp.stuff[ii] = temp;
printf ("\t%f\n", resp.stuff[ii]);
}
Publish (device_addr, resp_queue, PLAYER_MSGTYPE_DATA,
EGINTERF_DATA, &resp, sizeof (resp), NULL);
}
delete[] resp.stuff;
}
else if (Message::MatchMessage (hdr, PLAYER_MSGTYPE_REQ, EGINTERF_REQ,
device_addr))
{
printf ("EgInterfDriver: Got request: %d\n",
reinterpret_cast<player_eginterf_req*> (data)->value);
reqResp.value = RAND_MAX;
printf ("EgInterfDriver: Sending response: %d\n",
reqResp.value);
Publish (device_addr, resp_queue, PLAYER_MSGTYPE_RESP_ACK,
EGINTERF_REQ, &reqResp, sizeof (reqResp), NULL);
}
return(0);
}
////////////////////////////////////////////////////////////////////////////////
// Extra stuff for building a shared object.
extern "C" {
int player_driver_init(DriverTable* table)
{
puts("EgInterfDriver initializing");
EgInterfDriver_Register(table);
puts("EgInterfDriver done");
return(0);
}
}
--- NEW FILE: eginterf_client.h ---
/*
* This file declares a C client library proxy for the interface. The functions
* are defined in eginterf_client.c.
*/
typedef struct
{
/* Device info; must be at the start of all device structures. */
playerc_device_t info;
/* Other stuff the proxy should store during its lifetime. */
uint32_t stuff_count;
double *stuff;
int value;
} eginterf_t;
eginterf_t *eginterf_create (playerc_client_t *client, int index);
void eginterf_destroy (eginterf_t *device);
int eginterf_subscribe (eginterf_t *device, int access);
int eginterf_unsubscribe (eginterf_t *device);
int eginterf_cmd (eginterf_t *device, char value);
int eginterf_req (eginterf_t *device, int blah);
--- NEW FILE: Makefile.example ---
CSOURCES=eginterf_client.c \
eginterf.c \
eginterf_xdr.c
COBJECTS=eginterf_client.o \
eginterf.o \
eginterf_xdr.o
CCSOURCES=eginterf_driver.cc
CCOBJECTS=eginterf_driver.o
all: libeginterf.so libeginterfdriver.so example_client
$(COBJECTS): $(CSOURCES)
$(CC) `pkg-config --cflags playercore` -Wall -fpic -g3 `pkg-config
--cflags playercore` -c $^
$(CCOBJECTS): $(CCSOURCES)
$(CXX) -Wall -fpic -g3 `pkg-config --cflags playercore` -c $<
libeginterf.so: $(COBJECTS)
$(CC) -shared -nostartfiles -o $@ $^
libeginterfdriver.so: $(CCOBJECTS)
$(CXX) -shared -nostartfiles -o $@ $^
example_client: example_client.c
$(CC) -g3 -o $@ `pkg-config --cflags playerc` $< `pkg-config --libs
playerc` -L. -leginterf
clean:
rm -f *.o *.so example_client
--- NEW FILE: Makefile.am ---
PLAYERC_CFLAGS = -I$(top_srcdir) \
-I$(top_srcdir)/client_libs/
PLAYERC_LIB_DIRS=-L${top_builddir}/libplayerxdr \
-L${top_builddir}/libplayercore \
-L${top_builddir}/client_libs/libplayerc
PLAYERC_DEPS = $(top_builddir)/client_libs/libplayerc/libplayerc.la \
$(top_builddir)/libplayerxdr/libplayerxdr.la \
$(top_builddir)/libplayercore/libplayererror.la
AM_CPPFLAGS = -Wall -g $(PLAYERC_CFLAGS)
exampledir = $(prefix)/share/player/examples/plugins/exampleinterface
example_PROGRAMS = example_client
example_DATA = eginterf_client.c eginterf.c eginterf_xdr.c eginterf_driver.cc
Makefile.example example.cfg
EXTRA_DIST = Makefile.example example.cfg
example_LTLIBRARIES = libeginterfdriver.la libeginterf
libeginterfdriver_la_SOURCES = eginterf_driver.cc
libeginterf_la_SOURCEs = eginterf_client.c eginterf.c eginterf_xdr.c
example_client_SOURCES = example_client.c
example_client_LDADD = -lplayerc $(PLAYERC_LIB_DIRS) -lplayerxdr -lplayererror
example_client_DEPENDENCIES = $(PLAYERC_DEPS)
--- NEW FILE: eginterf_client.c ---
/*
* This file implements a C client proxy for the interface defined in
* eginterf_client.h. The following functions are essential, others depend on
* the design of your interface:
*
* eginterf_create Creates a proxy for the interface
* eginterf_destroy Destroys a proxy for the interface
* eginterf_subscribe Subscribes to a device that provides the interface
* eginterf_unsubscribe Unsubscribes from a subscribed device
* eginterf_putmsg Called by the client library whenever there a data
* message is received for this proxy
*/
#include <string.h>
#include <stdlib.h>
#include <libplayerc/playerc.h>
#include <libplayercore/error.h>
#include "eginterf.h"
#include "eginterf_client.h"
void eginterf_putmsg (eginterf_t *device, player_msghdr_t *header, uint8_t
*data, size_t len);
eginterf_t *eginterf_create (playerc_client_t *client, int index)
{
eginterf_t *device;
device = (eginterf_t*) malloc (sizeof (eginterf_t));
memset (device, 0, sizeof (eginterf_t));
playerc_device_init (&device->info, client, PLAYER_EGINTERF_CODE,
index, (playerc_putmsg_fn_t) eginterf_putmsg);
device->stuff_count = 0;
device->stuff = NULL;
device->value = 0;
return device;
}
void eginterf_destroy (eginterf_t *device)
{
playerc_device_term (&device->info);
free (device);
}
int eginterf_subscribe (eginterf_t *device, int access)
{
return playerc_device_subscribe (&device->info, access);
}
int eginterf_unsubscribe (eginterf_t *device)
{
return playerc_device_unsubscribe (&device->info);
}
void eginterf_putmsg (eginterf_t *device, player_msghdr_t *header, uint8_t
*data, size_t len)
{
if((header->type == PLAYER_MSGTYPE_DATA) && (header->subtype ==
EGINTERF_DATA))
{
assert(header->size > 0);
player_eginterf_data *stuffData = (player_eginterf_data *) data;
if (device->stuff != NULL)
free (device->stuff);
if ((device->stuff = (double*) malloc (stuffData->stuff_count))
== NULL)
printf ("Failed to allocate space to store stuff
locally");
else
memcpy (device->stuff, stuffData->stuff,
stuffData->stuff_count * sizeof(double));
device->stuff_count = stuffData->stuff_count;
}
else
printf ("skipping eginterf message with unknown type/subtype:
%s/%d\n", msgtype_to_str(header->type), header->subtype);
}
int eginterf_cmd (eginterf_t *device, char value)
{
player_eginterf_cmd cmd;
memset (&cmd, 0, sizeof (player_eginterf_cmd));
cmd.doStuff = value;
return playerc_client_write (device->info.client, &device->info,
EGINTERF_CMD, &cmd, NULL);
}
int eginterf_req (eginterf_t *device, int blah)
{
int result = 0;
player_eginterf_req req;
player_eginterf_req rep;
memset (&rep, 0, sizeof (player_eginterf_req));
req.value = blah;
if ((result = playerc_client_request (device->info.client,
&device->info, EGINTERF_REQ, &req, &rep, sizeof (player_eginterf_req))) < 0)
return result;
device->value = rep.value;
return 0;
}
--- NEW FILE: eginterf_xdr.h ---
/*
* The functions that tell XDR how to pack, unpack, deep copy and clean up
* message structures are declared here. This file was generated automatically
* by playerxdrgen.py, then cleaned up.
*/
#include "eginterf.h"
int xdr_player_eginterf_data(XDR* xdrs, player_eginterf_data* msg);
int player_eginterf_data_pack(void* buf, size_t buflen, player_eginterf_data*
msg, int op);
unsigned int player_eginterf_data_dpcpy(const player_eginterf_data* src,
player_eginterf_data* dest);
void player_eginterf_data_cleanup(player_eginterf_data* msg);
int xdr_player_eginterf_req(XDR* xdrs, player_eginterf_req* msg);
int player_eginterf_req_pack(void* buf, size_t buflen, player_eginterf_req*
msg, int op);
int xdr_player_eginterf_cmd(XDR* xdrs, player_eginterf_cmd* msg);
int player_eginterf_cmd_pack(void* buf, size_t buflen, player_eginterf_cmd*
msg, int op);
--- NEW FILE: README ---
Here's a very simple example of how to write a plugin interface. This example
uses several other aspects of player, including configuration files, a
libplayerc client program and a plugin driver. For details on creating and using
these, see the User Manual.
To build this example, edit the Makefile according to where you've got
Player installed and then type 'make'.
To try it, run (in separate terminals):
$ player example.cfg
$ ./example_client
--- NEW FILE: eginterf.c ---
/*
* This file contains the function table used to tell Player how to serialise
* your interface messages.
* The format is as follows:
*
* {interface code, message type, message subtype,
* pack function, deep copy function, clean up function}
*
* Note that a deep copy function and a clean up function are only necessary if
* the structure used for that message contains dynamically allocated arrays. If
* they are not needed, specify NULL instead.
*
* The XDR functions specified in this table must be linked as a part of the
* interface library. They can be written by hand, but it may be easier to use
* the playerxdrgen.py script in PLAYER_SRC/libplayerxdr. For example:
*
* python ../../../libplayerxdr/playerxdrgen.py -distro eginterf.h
eginterf_xdr.c eginterf_xdr.h
*
* The files generated by this script will probably need some cleaning up,
* especially the header file.
*
* The other part of the file is the function that will be exported in the
* dynamically shared library and imported by the Player server. This must
* return a pointer to the function table. Clients can link the library at
* compile time and access the table directly in their call to
* playerc_add_xdr_ftable(). However, if using multiple plugin interfaces in
* a client, ensure that they don't use the same name for their function table.
*/
#include "eginterf.h"
#include "eginterf_xdr.h"
// Function table for this interface
static playerxdr_function_t eginterf_ftable[] =
{
{PLAYER_EGINTERF_CODE, PLAYER_MSGTYPE_DATA, EGINTERF_DATA,
(player_pack_fn_t)player_eginterf_data_pack,
(player_dpcpy_fn_t)player_eginterf_data_dpcpy,
(player_cleanup_fn_t)player_eginterf_data_cleanup},
{PLAYER_EGINTERF_CODE, PLAYER_MSGTYPE_REQ, EGINTERF_REQ,
(player_pack_fn_t)player_eginterf_req_pack, NULL, NULL},
{PLAYER_EGINTERF_CODE, PLAYER_MSGTYPE_CMD, EGINTERF_CMD,
(player_pack_fn_t)player_eginterf_cmd_pack, NULL, NULL},
/* This NULL element signals the end of the list */
{0,0,0,NULL,NULL,NULL}
};
playerxdr_function_t* player_plugininterf_gettable (void)
{
return eginterf_ftable;
}
--- NEW FILE: eginterf_xdr.c ---
/*
* The functions that tell XDR how to pack, unpack, deep copy and clean up
* message structures are defined here. This file was generated automatically
* by playerxdrgen.py.
*/
#include <libplayerxdr/playerxdr.h>
#include <string.h>
#include "eginterf_xdr.h"
int
xdr_player_eginterf_data(XDR* xdrs, player_eginterf_data* msg)
{
if(xdr_u_int(xdrs,&msg->stuff_count) != 1)
return(0);
if(xdrs->x_op == XDR_DECODE)
{
if((msg->stuff = malloc(msg->stuff_count*sizeof(double))) == NULL)
return(0);
}
{
double* stuff_p = msg->stuff;
if(xdr_array(xdrs, (char**)&stuff_p, &msg->stuff_count, msg->stuff_count,
sizeof(double), (xdrproc_t)xdr_double) != 1)
return(0);
}
return(1);
}
int
player_eginterf_data_pack(void* buf, size_t buflen, player_eginterf_data* msg,
int op)
{
XDR xdrs;
int len;
if(!buflen)
return(0);
xdrmem_create(&xdrs, buf, buflen, op);
if(xdr_u_int(&xdrs,&msg->stuff_count) != 1)
return(-1);
if(op == PLAYERXDR_DECODE)
{
if((msg->stuff = malloc(msg->stuff_count*sizeof(double))) == NULL)
return(-1);
}
{
double* stuff_p = msg->stuff;
if(xdr_array(&xdrs, (char**)&stuff_p, &msg->stuff_count, msg->stuff_count,
sizeof(double), (xdrproc_t)xdr_double) != 1)
return(-1);
}
if(op == PLAYERXDR_ENCODE)
len = xdr_getpos(&xdrs);
else
len = sizeof(player_eginterf_data);
xdr_destroy(&xdrs);
return(len);
}
unsigned int
player_eginterf_data_dpcpy(const player_eginterf_data* src,
player_eginterf_data* dest)
{
if(src == NULL)
return(0);
unsigned int size = 0;
if(src->stuff != NULL && src->stuff_count > 0)
{
if((dest->stuff = malloc(src->stuff_count*sizeof(double))) == NULL)
return(0);
memcpy(dest->stuff, src->stuff, src->stuff_count*sizeof(double));
size += src->stuff_count*sizeof(double);
}
else
dest->stuff = NULL;
return(size);
}
void
player_eginterf_data_cleanup(player_eginterf_data* msg)
{
if(msg == NULL)
return;
if(msg->stuff == NULL)
return;
free(msg->stuff);
}
int
xdr_player_eginterf_req(XDR* xdrs, player_eginterf_req* msg)
{
if(xdr_int(xdrs,&msg->value) != 1)
return(0);
return(1);
}
int
player_eginterf_req_pack(void* buf, size_t buflen, player_eginterf_req* msg,
int op)
{
XDR xdrs;
int len;
if(!buflen)
return(0);
xdrmem_create(&xdrs, buf, buflen, op);
if(xdr_int(&xdrs,&msg->value) != 1)
return(-1);
if(op == PLAYERXDR_ENCODE)
len = xdr_getpos(&xdrs);
else
len = sizeof(player_eginterf_req);
xdr_destroy(&xdrs);
return(len);
}
int
xdr_player_eginterf_cmd(XDR* xdrs, player_eginterf_cmd* msg)
{
if(xdr_char(xdrs,&msg->doStuff) != 1)
return(0);
return(1);
}
int
player_eginterf_cmd_pack(void* buf, size_t buflen, player_eginterf_cmd* msg,
int op)
{
XDR xdrs;
int len;
if(!buflen)
return(0);
xdrmem_create(&xdrs, buf, buflen, op);
if(xdr_char(&xdrs,&msg->doStuff) != 1)
return(-1);
if(op == PLAYERXDR_ENCODE)
len = xdr_getpos(&xdrs);
else
len = sizeof(player_eginterf_cmd);
xdr_destroy(&xdrs);
return(len);
}
--- NEW FILE: example_client.c ---
/*
* This simple client illustrates the use of a plugin interface. It subscribes
* to a device providing the interface, then tests each message.
*
* The important point to note for the purposes of this example is the call to
* playerc_add_xdr_ftable(). This function adds the XDR serialisation functions
* to Player's internal table so that messages sent and received by this client
* can be serialised correctly.
*/
#include <stdio.h>
#include <libplayerc/playerc.h>
#include "eginterf_client.h"
#include "eginterf.h"
int main(int argc, const char **argv)
{
int i;
playerc_client_t *client;
eginterf_t *device;
// Create a client and connect it to the server.
client = playerc_client_create(NULL, "localhost", 6665);
if (0 != playerc_client_connect(client))
{
printf ("Could not connect\n");
return -1;
}
if (playerc_add_xdr_ftable (player_plugininterf_gettable (), 0) < 0)
printf ("Could not add xdr functions\n");
// Create and subscribe to a position2d device.
device = eginterf_create(client, 0);
if (eginterf_subscribe(device, PLAYER_OPEN_MODE) != 0)
{
printf ("Could not subscribe\n");
return -1;
}
// Send a command, get back a data message
eginterf_cmd (device, 5);
playerc_client_read (client);
for (i = 0; i < device->stuff_count; i++)
printf ("Stuff[%d] = %f\n", i, device->stuff[i]);
// Send a request
if (eginterf_req (device, 3) < 0)
printf ("Request failed\n");
else
printf ("Request succeeded, got value: %d\n", device->value);
// Shutdown
eginterf_unsubscribe(device);
eginterf_destroy(device);
playerc_client_disconnect(client);
playerc_client_destroy(client);
return 0;
}
-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
Playerstage-commit mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/playerstage-commit