====== Estendere Python grazie a swig ====== Autore: **//Fabio Di Matteo//** \\ Ultima revisione: **//13/07/2008//** \\ \\ Dal sito di swig:[[http://www.swig.org/|www.swig.org]]\\ \\ "SWIG is a software development tool that connects programs written in C and C++ with a variety of high-level programming languages. SWIG is used with different types of languages including common scripting languages such as Perl, PHP, Python, Tcl and Ruby. The list of supported languages also includes non-scripting languages such as C#, Common Lisp (CLISP, Allegro CL, CFFI, UFFI), Java, Lua, Modula-3, OCAML, Octave and R. Also several interpreted and compiled Scheme implementations (Guile, MzScheme, Chicken) are supported. SWIG is most commonly used to create high-level interpreted or compiled programming environments, user interfaces, and as a tool for testing and prototyping C/C++ software. SWIG can also export its parse tree in the form of XML and Lisp s-expressions. SWIG may be freely used, distributed, and modified for commercial and non-commercial use." ===== Istruire swig sul sorgente C da trattare ===== Il sorgente verrà trattato da swig grazie ad un file chiamato interfaccia dove sono specificati header e codice del nostro sorgente. \\ Consideriamo il seguente codice C [[programmazione:c:una_libreria_per_leggere_i_file_.desktop]] : #include #include #define MAXKEY 50 #define MAXVALUE 350 #define MAXLINE 450 int wordcount(char* line); char* keyread(char *path, char* key); void keywrite(char *path, char* key, char* value); int keydel(char *path, char* key); char* keyread(char *path, char* key){ FILE *f=fopen(path, "r"); char valuetmp[MAXVALUE], line[MAXVALUE+MAXKEY], *value, key_now[MAXKEY] ; int i; while (feof(f)==0){ fgets(line,MAXVALUE+MAXKEY,f); if (line[0]!='#'){ sscanf(line, "%[^'=']=%[^'=\n']",key_now, valuetmp); if (strcmp(key_now, key)==0){ value=malloc(sizeof(valuetmp)); strcpy(value,valuetmp); fclose(f); return value; } } } fclose(f); } void keywrite(char *path, char* key, char* value){ FILE *f=fopen(path, "r"); int i, pos=0, idxline=0 ; char valuetmp[MAXVALUE], *nline[MAXVALUE+MAXKEY], key_now[MAXKEY] ; //get key's position while (feof(f)==0){ pos++; nline[pos-1]=malloc(MAXLINE); fgets(nline[pos-1],MAXLINE,f); if (nline[pos-1][0]!='#'){ sscanf(nline[pos-1], "%[^'=']=%[^'=']",key_now, valuetmp); if (strcmp(key_now, key)==0 && idxline==0){ idxline=pos-1; } } } fclose(f); //edit or append key nline[idxline]=malloc(MAXLINE+15); if (idxline!=0){ //edit key sprintf(nline[idxline] ,"%s=%s\n",key,value); FILE *f=fopen(path, "w"); for (i=0;i<=pos-1;i++) fputs(nline[i],f); fclose(f); }else{ //append new key FILE *f=fopen(path, "a"); sprintf(nline[pos-1] ,"%s=%s",key,value);; fputs(nline[pos-1],f); fclose(f); } } int keydel(char *path, char* key){ FILE *f=fopen(path, "r"); int i, pos=0, idxline=0 ; char valuetmp[MAXVALUE], *nline[MAXVALUE+MAXKEY], key_now[MAXKEY] ; //get key's position while (feof(f)==0){ pos++; nline[pos-1]=malloc(MAXLINE+15); fgets(nline[pos-1],MAXLINE,f); if (nline[pos-1][0]!='#'){ sscanf(nline[pos-1], "%[^'=']=%[^'=']\n",key_now, valuetmp); if (strcmp(key_now, key)==0 && idxline==0){ idxline=pos-1; } } } fclose(f); //delete key if (idxline!=0){ FILE *f=fopen(path, "w"); for (i=0;i<=pos-1;i++){ if (i!=idxline)fputs(nline[i],f); } fclose(f); }else{ return -1; } } int wordcount(char* line){ int i,count=0; for(i=0; i ==== Creiamo il file di interfaccia ==== A partire dal codice sopra esposto ecco come potremmo scrivere il file di interfaccia ''keys.i'' a swig: %module keys %{ /*Qua ci fanno soltanto gli header*/ #include #include #define MAXKEY 50 #define MAXVALUE 350 #define MAXLINE 450 extern wordcount(char* line); extern keyread(char *path, char* key); extern keywrite(char *path, char* key, char* value); extern keydel(char *path, char* key); %} /*qua il sorgente*/ char* keyread(char *path, char* key){ FILE *f=fopen(path, "r"); char valuetmp[MAXVALUE], line[MAXVALUE+MAXKEY], *value, key_now[MAXKEY] ; int i; while (feof(f)==0){ fgets(line,MAXVALUE+MAXKEY,f); if (line[0]!='#'){ sscanf(line, "%[^'=']=%[^'=\n']",key_now, valuetmp); if (strcmp(key_now, key)==0){ value=malloc(sizeof(valuetmp)); strcpy(value,valuetmp); fclose(f); return value; } } } fclose(f); } void keywrite(char *path, char* key, char* value){ FILE *f=fopen(path, "r"); int i, pos=0, idxline=0 ; char valuetmp[MAXVALUE], *nline[MAXVALUE+MAXKEY], key_now[MAXKEY] ; //get key's position while (feof(f)==0){ pos++; nline[pos-1]=malloc(MAXLINE); fgets(nline[pos-1],MAXLINE,f); if (nline[pos-1][0]!='#'){ sscanf(nline[pos-1], "%[^'=']=%[^'=']",key_now, valuetmp); if (strcmp(key_now, key)==0 && idxline==0){ idxline=pos-1; } } } fclose(f); //edit or append key nline[idxline]=malloc(MAXLINE+15); if (idxline!=0){ //edit key sprintf(nline[idxline] ,"%s=%s\n",key,value); FILE *f=fopen(path, "w"); for (i=0;i<=pos-1;i++) fputs(nline[i],f); fclose(f); }else{ //append new key FILE *f=fopen(path, "a"); sprintf(nline[pos-1] ,"%s=%s",key,value);; fputs(nline[pos-1],f); fclose(f); } } int keydel(char *path, char* key){ FILE *f=fopen(path, "r"); int i, pos=0, idxline=0 ; char valuetmp[MAXVALUE], *nline[MAXVALUE+MAXKEY], key_now[MAXKEY] ; //get key's position while (feof(f)==0){ pos++; nline[pos-1]=malloc(MAXLINE+15); fgets(nline[pos-1],MAXLINE,f); if (nline[pos-1][0]!='#'){ sscanf(nline[pos-1], "%[^'=']=%[^'=']\n",key_now, valuetmp); if (strcmp(key_now, key)==0 && idxline==0){ idxline=pos-1; } } } fclose(f); //delete key if (idxline!=0){ FILE *f=fopen(path, "w"); for (i=0;i<=pos-1;i++){ if (i!=idxline)fputs(nline[i],f); } fclose(f); }else{ return -1; } } int wordcount(char* line){ int i,count=0; for(i=0; i Come vedete la direttiva ''%module'' specifica il nome del modulo python che verrà creato, subito sotto ci sono gli header, e in basso dopo l'ultima parentesi graffa c'è il corpo del codice sorgente con le nostre istruzioni.\\ Adesso non ci resta che creare il modulo python composto da libreria binaria e wrapper. ===== Makefile ===== Il seguente makefile creerà il modulo python: all: swig -python keys.i gcc -c keys.c keys_wrap.c -I/usr/include/python2.5 ld -shared keys.o keys_wrap.o -o _keys.so Sono 3 le istruzini, e in ordine: - viene creato il wrapper python per la nostra libreria; - viene creato un file oggetto (di nome keys.o ) con i nostri sorgenti e il wrapper creato ; - viene creata una libreria condivisa di nome '' _keys.so'' . ===== Proviamo il tutto in python ===== Creiamo nella stessa directory del modulo un file di nome ''test.py'' con il seguente codice: import keys icona=keys.keyread('audacious.desktop','Icon'); print keys; keys.keywrite('audacious.desktop','Icon', 'fileicona.png' ); exit; avviare il file con python test.py (dato che non abbiamo specificato l'interprete). Come si vede si sta usando la libreria proprio come lo si faceva in C in questo articolo: [[programmazione:c:una_libreria_per_leggere_i_file_.desktop]]