// 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; */ /* } */ // nouvelle syntaxe SWIG 1.3.x : $target -> $1 et $source -> $input %typemap(python,in) PyObject *PyFunc { if (!PyCallable_Check($input)) { PyErr_SetString(PyExc_TypeError, "Need a callable object!"); return NULL; } $1 = $input; } %typemap(python,in) PyObject *PyFuncOnCx { if (!PyCallable_Check($input)) { PyErr_SetString(PyExc_TypeError, "Need a callable object!"); return NULL; } $1 = $input; } %typemap(python,in) PyObject *PyFuncOnDie { if (!PyCallable_Check($input)) { PyErr_SetString(PyExc_TypeError, "Need a callable object!"); return NULL; } $1 = $input; } // 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: