From a5803c3a3e49d5d10e017a70c9e94d0545d59a09 Mon Sep 17 00:00:00 2001 From: pavet Date: Thu, 9 Sep 2004 15:33:37 +0000 Subject: Initial revision --- ivycpy.i | 865 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 865 insertions(+) create mode 100644 ivycpy.i (limited to 'ivycpy.i') diff --git a/ivycpy.i b/ivycpy.i new file mode 100644 index 0000000..3dcc449 --- /dev/null +++ b/ivycpy.i @@ -0,0 +1,865 @@ +// SWIG Module for making a python wrapper to C ivy library +// -#- c-mode -#- +// +// warning avoid any phrase starting with "pyIvy +// or ending with MsgAsS" +// or ending with ErrorAsS" +// cause these patterns are patched afterwards in order to neat +// Ivycpy library naming +// + +%module ivycpy + +// part 1 on place ici entre %{%} les inclusions, pre-declarations importantes, +// fonctions locales qui vont etre associées au wrapper ce code sera conservé +// intact par SWIG + +%{ +#include +#include +#include +#include +#include +#include +#include +#include +/* #define MYAPP "ivycpy" */ +#include <_tkinter.h> + + /* #include */ +%} +// part 1 on place ici les types de donnees faisant partie des elements +// à wrapper + +/* define */ +/* numero par default du bus */ +/* #define DEFAULT_BUS 2010 */ + +/* typedef : debut */ +typedef struct _clnt_lst *IvyClientPtr; +typedef enum { IvyApplicationConnected, IvyApplicationDisconnected } + IvyApplicationEvent; + +typedef struct _timer *TimerId; + +/* a voir si a laisser ici */ +/* extern void */ +/* IvyDefaultApplicationCallback( IvyClientPtr app, void *user_data, IvyApplicationEvent event ) ; */ + +/* pour ces callbacks le clientdata sert à ... */ +/* callback appele sur connexion deconnexion d'une appli */ +/* typedef void (*IvyApplicationCallback)( */ +/* IvyClientPtr app, void *user_data, IvyApplicationEvent event); */ + +/* callback appele sur reception de die */ +/* typedef void (*IvyDieCallback)( */ +/* IvyClientPtr app, void *user_data, int id) ; */ + +/* callback appele sur reception de messages normaux */ +/* typedef void (*MsgCallback)( */ +/* IvyClientPtr app, void *user_data, int argc, char **argv ) ; */ + +/* callback appele sur reception de messages directs */ +/* typedef void (*MsgDirectCallback)( IvyClientPtr app, void *user_data, int id, char *msg ) ; */ + +/* identifiant d'une expression reguliere ( Bind/Unbind ) */ +/* typedef struct _msg_rcv *MsgRcvPtr; */ + +/* typedef : fin */ + +/* les fonctions proprement dite : debut */ + +/* filtrage des regexps */ +/* void IvyClasses( int argc, const char **argv); */ + + +/* query sur les applications connectees */ +/* char *IvyGetApplicationName( IvyClientPtr app ); */ +/* char *IvyGetApplicationHost( IvyClientPtr app ); */ +/* IvyClientPtr IvyGetApplication( char *name ); */ +/* char *IvyGetApplicationList(); */ +/* char **IvyGetApplicationMessages( IvyClientPtr app); demande de reception d'un message */ + +/* void *mcb_as_data, cette donnee doit etre passee dans le user_data */ + +/* void IvyUnbindMsg( MsgRcvPtr id ); */ + +/* emission d'un message d'erreur */ +/* void IvySendError( IvyClientPtr app, int id, const char *message); */ + +/* emmission d'un message die pour terminer l'application */ +/* void IvySendDieMsg( IvyClientPtr app ); */ + +/* emission d'un message retourne le nb effectivement emis */ + +/* int IvySendMsg(const char *message); */ + +/* Message Direct Inter-application */ + +/* void IvyBindDirectMsg( MsgDirectCallback callback, void *user_data); */ +/* void IvySendDirectMsg( IvyClientPtr app, int id, char *msg ); */ + +/* qq donnees privees necessaires */ + +/* il faudra ici traiter les pbs de callback de facon propre +voir trash1 ou les exemples sur les callbacks en Python */ + + +// ---------------------------------------------------------------- +// Python helper functions for adding callbacks +// ---------------------------------------------------------------- + +%{ +/* typedef struct { */ +/* PyObject *func, */ +/* void *true_userdata */ +/* } _Userdata4cb , *_PUserdata4cb ; */ + +typedef MsgRcvPtr *MsgRcvArray ; +typedef TimerId *TimerIdArray ; + +/* donnees et fonctions de gestion des infos MsgRcvPtr retournés par + IvyBindMsg */ +static MsgRcvArray msgrcvarray ; +static int bindingid_number = 0 ; + +/* donnees et fonctions de gestion des timer retournés par + TimerRepeatAfter */ +static TimerIdArray timerarray ; +static int timerid_number = 0 ; + +static int lloopmode ; /* 0 if Ivyloop else TkLoop */ + +static int +addRcvMsg(MsgRcvPtr rcvptr) +{ + int i, bindingid ; + for(i=0;i=0 && binding_id < bindingid_number) + return msgrcvarray[binding_id] ; + else + return NULL ; +} +static void +delRcvMsg(int binding_id) +{ + if (binding_id >=0 && binding_id < bindingid_number) + msgrcvarray[binding_id] = NULL ; +} +static void +printmsgrcvarray() +{ + int i; + for(i=0;i=0 && timerid < timerid_number) + return timerarray[timerid] ; + else + return NULL ; +} +static void +delIvyTimer(int timerid) +{ + if (timerid >=0 && timerid < timerid_number) + timerarray[timerid] = NULL ; +} +static void +printtimerarray() +{ + int i; + for(i=0;ifunc ; */ + /* la signature python doit etre proc(n) elle ne retourne rien */ + + arglist = Py_BuildValue("(i)", (int) event); + result = PyEval_CallObject(func,arglist); + Py_DECREF(arglist); + LEAVE_PYTHON +} +static void +pyIvyApplicationCallback(IvyClientPtr app, void *user_data, + IvyApplicationEvent event) +{ + PyObject *func, *arglist; + PyObject *result; + +#ifdef __DEBUG__ + printf("-pyIvyApplicationCallback\n"); +#endif + func = (PyObject *) user_data; + /* cette verif est inutile ; elle a deja ete faite lors de + l'enregistrement du callback */ + if (!PyCallable_Check(func)) { + PyErr_SetString(PyExc_TypeError, "Need a callable object!"); + return ; + }; + /* user_data->func ; */ + /* la signature python doit etre proc(n) elle ne retourne rien */ + + arglist = Py_BuildValue("(i)", (int) event); + result = PyEval_CallObject(func,arglist); + Py_DECREF(arglist); +} +static void +pytkIvyDieCallback(IvyClientPtr app, void *user_data, int id) +{ + PyObject *func, *arglist; + PyObject *result; + +#ifdef __DEBUG__ + printf("-pytkIvyApplicationCallback\n"); +#endif + + + ENTER_PYTHON + func = (PyObject *) user_data; + /* cette verif est inutile ; elle a deja ete faite lors de + l'enregistrement du callback */ + if (!PyCallable_Check(func)) { + PyErr_SetString(PyExc_TypeError, "Need a callable object!"); + return ; + }; + /* user_data->func ; */ + /* la signature python doit etre proc(n) elle ne retourne rien */ + + arglist = Py_BuildValue("(i)", id); + result = PyEval_CallObject(func,arglist); + Py_DECREF(arglist); + LEAVE_PYTHON +} +static void +pyIvyDieCallback(IvyClientPtr app, void *user_data, int id) +{ + PyObject *func, *arglist; + PyObject *result; + +#ifdef __DEBUG__ + printf("-pyIvyApplicationCallback\n"); +#endif + func = (PyObject *) user_data; + /* cette verif est inutile ; elle a deja ete faite lors de + l'enregistrement du callback */ + if (!PyCallable_Check(func)) { + PyErr_SetString(PyExc_TypeError, "Need a callable object!"); + return ; + }; + /* user_data->func ; */ + /* la signature python doit etre proc(n) elle ne retourne rien */ + + arglist = Py_BuildValue("(i)", id ); + result = PyEval_CallObject(func,arglist); + Py_DECREF(arglist); +} + +/* callback fixe (ce sera tjs le même) appellé par pyIvyBindMsg */ +static void +pytkMsgCallback( IvyClientPtr app, void *user_data, int argc, char **argv ) +{ + PyObject *func, *arglist; + PyObject *result; + PyObject *pyargv ; + int i ; + +#ifdef __DEBUG__ + printf("-pytkMsgCallback\n"); +#endif + + ENTER_PYTHON + func = (PyObject *) user_data; + + /* cette verif est inutile ; elle a deja ete faite lors de + l'enregistrement du callback */ + if (!PyCallable_Check(func)) { + PyErr_SetString(PyExc_TypeError, "Need a callable object!"); + return ; + }; + /* user_data->func ; */ + /* la signature python doit etre proc(*arg)) + elle ne retourne rien */ + + pyargv = PyTuple_New(argc); + for (i = 0; i < argc; i++) { + PyTuple_SetItem(pyargv,i,PyString_FromString(argv[i])); + } + /* this codes is useless; the tuple (pyargv) is directly passed + to the Python call back + arglist = Py_BuildValue("(iO)", argc, pyargv); + result = PyEval_CallObject(func,arglist); + Py_DECREF(arglist); */ + + result = PyEval_CallObject(func, pyargv) ; + LEAVE_PYTHON + +} + +static void +pyMsgCallback( IvyClientPtr app, void *user_data, int argc, char **argv ) +{ + PyObject *func, *arglist; + PyObject *result; + PyObject *pyargv ; + int i ; + +#ifdef __DEBUG__ + printf("-pyMsgCallback\n"); +#endif + func = (PyObject *) user_data; + + /* cette verif est inutile ; elle a deja ete faite lors de + l'enregistrement du callback */ + if (!PyCallable_Check(func)) { + PyErr_SetString(PyExc_TypeError, "Need a callable object!"); + return ; + }; + /* user_data->func ; */ + /* la signature python doit etre proc(*arg) + elle ne retourne rien */ + + pyargv = PyTuple_New(argc); + for (i = 0; i < argc; i++) { + PyTuple_SetItem(pyargv,i,PyString_FromString(argv[i])); + } + /* this codes is useless; the tuple (pyargv) is directly passed + to the Python call back + arglist = Py_BuildValue("(iO)", argc, pyargv); + result = PyEval_CallObject(func,arglist); + Py_DECREF(arglist); */ + + result = PyEval_CallObject(func, pyargv) ; +} + +/* jeu de 2 callback fixes (mode tk ou sans (ce sera tjs le même) appellé par + pyIvyBindDirectMsg */ +static void +pytkMsgDirectCallback( IvyClientPtr app, void *user_data, int id, char *msg ) +{ + PyObject *func; + PyObject *result; + +#ifdef __DEBUG__ + printf("-pytkMsgDirectCallback\n"); +#endif + + ENTER_PYTHON + func = (PyObject *) user_data; + + /* cette verif est inutile ; elle a deja ete faite lors de + l'enregistrement du callback */ + if (!PyCallable_Check(func)) { + PyErr_SetString(PyExc_TypeError, "Need a callable object!"); + return ; + }; + /* user_data->func ; */ + /* la signature python doit etre proc(arg)) + elle ne retourne rien */ + + result = PyEval_CallObject(func, PyString_FromString(msg)) ; + + LEAVE_PYTHON +} + +static void +pyMsgDirectCallback( IvyClientPtr app, void *user_data, int id, char *msg ) +{ + PyObject *func; + PyObject *result; + +#ifdef __DEBUG__ + printf("-pyMsgDirectCallback\n"); +#endif + func = (PyObject *) user_data; + + /* cette verif est inutile ; elle a deja ete faite lors de + l'enregistrement du callback */ + if (!PyCallable_Check(func)) { + PyErr_SetString(PyExc_TypeError, "Need a callable object!"); + return ; + }; + /* user_data->func ; */ + /* la signature python doit etre proc(arg) + elle ne retourne rien */ + result = PyEval_CallObject(func, PyString_FromString(msg)) ; + +} + +/* facade to IvyBindMsg avoiding vararg problem */ +static int +pyIvyBindMsg (PyObject *PyFunc, const char *msg) /* void *user_data, */ +{ + MsgRcvPtr result ; + int binding_id = -1 ; + + /* le user_data est le pointeur PyFunc */ + if (lloopmode) { + result = IvyBindMsg(pytkMsgCallback, (void *) PyFunc , msg); + } + else { + result = IvyBindMsg(pyMsgCallback, (void *) PyFunc , msg); + } + /* on conserve une trace de result sous la forme d'une table + indexé i -> (result) ; cet indice sera incrémenté et retourné + comme valeur de retour */ +#ifdef __DEBUG__ + printf("-IvyBindMsg retourne %x \n", (int) result); +#endif + binding_id = addRcvMsg(result) ; +#ifdef __DEBUG__ + printmsgrcvarray(); +#endif + Py_INCREF(PyFunc); + Py_INCREF(Py_None) ; + return binding_id ; +} +static void +pyIvyUnBindMsg (int binding_id) +{ /* on passe à pyIvyUnBindMsg l'indexe du MsgRcvPtr retourné par + pyIvyBindMsg */ + MsgRcvPtr rcvid ; + rcvid = getRcvMsg(binding_id) ; + if (rcvid != NULL) { + printf("-IvyUnbindMsg %x \n" , (int) rcvid) ; + IvyUnbindMsg(rcvid); + delRcvMsg(binding_id); + }; +#ifdef __DEBUG__ + printmsgrcvarray() ; +#endif +} + +/* facade to IvyBindDirectMsg avoiding vararg problem */ +static void +pyIvyBindDirectMsg (PyObject *PyFunc) /* void *user_data, */ +{ + /* le user_data est le pointeur PyFunc */ + if (lloopmode) { + IvyBindDirectMsg(pytkMsgDirectCallback, (void *) PyFunc); + } + else { + IvyBindDirectMsg(pyMsgDirectCallback, (void *) PyFunc); + } + /* on conserve une trace de result sous la forme d'une table + indexé i -> (result) ; cet indice sera incrémenté et retourné + comme valeur de retour */ +#ifdef __DEBUG__ + printmsgrcvarray(); +#endif + Py_INCREF(PyFunc); + Py_INCREF(Py_None) ; +} + +/* facade to IvySendMsg avoiding vararg problem */ +int +pyIvySendMsg(const char *message) +{ + return(IvySendMsg(message)); +} +void +pyIvySendError( IvyClientPtr app, int id, const char *message) +{ + IvySendError(app,id,message); +} + +/* for ivy timer */ + +static void +pyTimerCallback(TimerId id , void *user_data, unsigned long delta ) +{ + PyObject *func ; + PyObject *result; + +#ifdef __DEBUG__ + printf("-pyTimerCallback\n"); +#endif + func = (PyObject *) user_data; + + /* cette verif est inutile ; elle a deja ete faite lors de + l'enregistrement du callback */ + if (!PyCallable_Check(func)) { + PyErr_SetString(PyExc_TypeError, "Need a callable object!"); + return ; + }; + /* la signature de la fonction python a appellé doit etre + proc() */ + result = PyEval_CallObject(func,NULL); +} +static void +pytkTimerCallback(TimerId id , void *user_data, unsigned long delta ) +{ + PyObject *func ; + PyObject *result; + +#ifdef __DEBUG__ + printf("-pytkTimerCallback\n"); +#endif + + ENTER_PYTHON + func = (PyObject *) user_data; + + /* cette verif est inutile ; elle a deja ete faite lors de + l'enregistrement du callback */ + if (!PyCallable_Check(func)) { + PyErr_SetString(PyExc_TypeError, "Need a callable object!"); + return ; + }; + /* la signature de la fonction python a appellé doit etre + proc() */ + result = PyEval_CallObject(func,NULL); + LEAVE_PYTHON +} + +/* add an ivy timer */ +/* retourne l'indice du timer pour identification ultérieure */ +static int +pyIvyTimerRepeatAfter(int count, int time, PyObject *PyFunc) +{ + TimerId timer ; + int timerid ; +#ifdef __DEBUG__ + printf("-pyIvyTimerRepeatAfter\n"); +#endif + if (lloopmode) { + timer = TimerRepeatAfter(count, (long) time, pytkTimerCallback, + (void *) PyFunc); + } + else { + timer = TimerRepeatAfter(count, time, pyTimerCallback, + (void *) PyFunc); + } + timerid = addIvyTimer(timer); +#ifdef __DEBUG__ + printtimerarray(); +#endif + Py_INCREF(PyFunc); + Py_INCREF(Py_None) ; + return timerid ; +} +static void +pyIvyTimerModify( int timerid, int time ) +{ + TimerId timer ; + timer = getIvyTimer(timerid); + if (timer != NULL) { + printf("-modifying timer %x \n", (int) timer); + TimerModify(timer, (long) time); + } +} +static void +pyIvyTimerRemove( int timerid) +{ + TimerId timer ; + timer = getIvyTimer(timerid); + if (timer != NULL) { + printf("-removing timer %x \n", (int) timer); + TimerRemove(timer); + delIvyTimer(timerid); + } +} + +/* IvyMainLoop */ +static void +pyIvyMainLoop() +{ + IvyMainLoop(0); /* pyHookCallback, (void *) PyFunc ); */ + Py_INCREF(Py_None) ; +} + +/* code repris de ivytcl.h ecrit par FR. Colin et S. Chatty */ +struct _channel { + HANDLE fd; + void *data; + ChannelHandleDelete handle_delete; + ChannelHandleRead handle_read; + }; +static int channel_initialized = 0; + +static void pyIvyChannelInit(void) +{ +#ifdef __DEBUG__ + printf("-pyIvyChannelInit\n"); +#endif + if ( channel_initialized ) return; + /* pour eviter les plantages quand les autres applis font core-dump */ +#ifndef WIN32 + signal( SIGPIPE, SIG_IGN); +#endif + channel_initialized = 1; +} + +static void +IvyHandleFd(ClientData cd, + int mask) +{ + Channel channel = (Channel)cd; + + /*printf("-handle event %d\n", mask);*/ + if (mask == TCL_READABLE) { + (*channel->handle_read)(channel,channel->fd,channel->data); + } + else if (mask == TCL_EXCEPTION) { + (*channel->handle_delete)(channel->data); + } +} + +static Channel pyIvyChannelSetUp( + HANDLE fd, + void *data, + ChannelHandleDelete handle_delete, + ChannelHandleRead handle_read) +{ + Channel channel; + +#ifdef __DEBUG__ + printf("-pyIvyChannelSetUp\n"); +#endif + channel = (Channel)ckalloc( sizeof (struct _channel) ); /* ckalloc */ + if ( !channel ) { + fprintf(stderr,"NOK Memory Alloc Error\n"); + exit(0); + } + + channel->handle_delete = handle_delete; + channel->handle_read = handle_read; + channel->data = data; + channel->fd = fd; + + /*printf("-Create handle fd %d\n", fd);*/ + /* Py_BEGIN_ALLOW_THREADS*/ +/* ENTER_TCL */ + Tcl_CreateFileHandler(fd, TCL_READABLE|TCL_EXCEPTION, IvyHandleFd, + (ClientData) channel); +/* LEAVE_TCL */ + /* Py_END_ALLOW_THREADS */ + + return channel; + +} + +static void pyIvyChannelClose( Channel channel ) +{ +#ifdef __DEBUG__ + printf("-pyIvyChannelClose\n"); +#endif + + if ( channel->handle_delete ) + (*channel->handle_delete)( channel->data ); + Tcl_DeleteFileHandler(channel->fd); + + ckfree((char *) channel); + +} + +static void +pyIvyInit( + const char *AppName, /* nom de l'application */ + const char *ready, /* ready Message peut etre NULL */ + int loopmode, /* 1 = mode Tk , 0 = mode Ivyloop */ + PyObject *PyFuncOnCx, /* callback appele sur connection deconnection + d'une appli */ + /* void *data, user data passe au callback */ + PyObject *PyFuncOnDie) /* last change callback before die + void *die_data ) user data */ +{ +#ifdef __DEBUG__ + printf("-pyIvyInit\n"); +#endif + + lloopmode = loopmode ; + if (loopmode == 1) { + channel_init = pyIvyChannelInit ; + channel_setup = pyIvyChannelSetUp; + channel_close = pyIvyChannelClose; + IvyInit(AppName,ready, + pytkIvyApplicationCallback, (void *) PyFuncOnCx, + pytkIvyDieCallback, (void *) PyFuncOnDie); + } + else { + IvyInit(AppName,ready, + pyIvyApplicationCallback, (void *) PyFuncOnCx, + pyIvyDieCallback, (void *) PyFuncOnDie); + } + + Py_INCREF(PyFuncOnCx); + Py_INCREF(PyFuncOnDie); + +} + +%} + +// part 2 +// on place ici les declarations complementaires : typemap, etc + +// ------------------------------------------------------------------- +// SWIG typemap allowing us to grab a Python callable object +// ------------------------------------------------------------------- + +%typemap(python,in) PyObject *PyFunc { + if (!PyCallable_Check($source)) { + PyErr_SetString(PyExc_TypeError, "Need a callable object!"); + return NULL; + } + $target = $source; +} + +%typemap(python,in) PyObject *PyFuncOnCx { + if (!PyCallable_Check($source)) { + PyErr_SetString(PyExc_TypeError, "Need a callable object!"); + return NULL; + } + $target = $source; +} + +%typemap(python,in) PyObject *PyFuncOnDie { + if (!PyCallable_Check($source)) { + PyErr_SetString(PyExc_TypeError, "Need a callable object!"); + return NULL; + } + $target = $source; +} + + +// part 3 +// on place ici les donnees, fonctions a wrapper + +void +pyIvyInit( + const char *AppName, /* nom de l'application */ + const char *ready, /* ready Message peut etre NULL */ + int loopmode, + PyObject *PyFuncOnCx, /* callback appele sur connection deconnection + d'une appli */ + /* void *data, user data passe au callback */ + PyObject *PyFuncOnDie); /* last change callback before die */ + /* void *die_data ); user data */ + +int +pyIvyBindMsg (PyObject *PyFunc, const char *msg); +void +pyIvyUnBindMsg (int binding_id); +void +IvyStart (const char*); +void +IvyStop (); +int +pyIvySendMsg(const char *message); +void +pyIvyMainLoop(); +char * +IvyGetApplicationList(); +IvyClientPtr +IvyGetApplication( char *name ); + +char * +IvyGetApplicationName( IvyClientPtr app ); +char *IvyGetApplicationHost( IvyClientPtr app ); +/* emission d'un message d'erreur */ +void +pyIvySendError( IvyClientPtr app, int id, const char *message); + +/* emission d'un message die pour terminer l'application */ +void +IvySendDieMsg( IvyClientPtr app ); + +/* send and bind direct */ +void +IvySendDirectMsg( IvyClientPtr app, int id, char *msg ); + +/* binddirect a venir */ +void +pyIvyBindDirectMsg (PyObject *PyFunc); + +/* fonction a wrapper concernant les timer */ +int +pyIvyTimerRepeatAfter(int count, int time, PyObject *PyFunc); +void +pyIvyTimerModify( int timerid, int time ); +void +pyIvyTimerRemove( int timerid); + +// for emacs +// Local Variables: +// mode: C +// indent-tabs-mode: t +// tab-width: 4 +// End: -- cgit v1.1