[Commits] python.it commit r171 - python/contrib/faq/trunk

commit a svn.python.it commit a svn.python.it
Mer 31 Maggio 2006 00:14:38 CEST


Author: meo
Date: Wed May 31 00:14:35 2006
New Revision: 171

Modified:
   python/contrib/faq/trunk/extending.ht
Log:
Versione definitiva (almeno spero ;)

Modified: python/contrib/faq/trunk/extending.ht
==============================================================================
--- python/contrib/faq/trunk/extending.ht	(original)
+++ python/contrib/faq/trunk/extending.ht	Wed May 31 00:14:35 2006
@@ -1,523 +1,523 @@
-Title: FAQ Estendere/Includere Python
-Content-type: text/x-rst
-
-====================================
-FAQ Estendere/Includere Python
-====================================
-
-:Date: $Date: 2004-04-08 17:05:47 +0200 (gio, 08 apr 2004) $
-:Version: $Revision: 7294 $
-:Web site: http://www.python.org/
-:Traduzione: Bartolomeo Bogliolo 1 Aprile 2006
-
-.. contents::
-.. sectnum::
-
-
-**Traduzione Italiana**
-
-Questo documento, di pubblico dominio, e' stato tradotto da 
-`Meo Bogliolo <mailto:meo a bogliolo.name?subject=Traduzione Embedding FAQ>`_ 
-(revisionato da 
-`Daniele Tricoli <mailto:eriol a huine.org?subject=Traduzione Embedding FAQ>`_ 
-): potete contattarli per qualsiasi
-commento o correzione.
-
-
-Si possono creare proprie funzioni in C?
-------------------------------------------
-Si, e' possibile creare moduli built-in che contengono funzioni,
-variabili, eccezioni ed anche nuovi tipi in C. Tutto cio' e' spiegato
-nel documento "Extending and Embedding the Python Interpreter" (http://docs.python.org/ext/ext.html).  
-
-Anche la maggior parte dei libri di livello intermedio o avanzato
-su Python trattano l'argomento.
-
-
-Si possono creare proprie funzioni in C++?
---------------------------------------------
-Si, utilizzando le caratteristiche di compatibilita' al C tipiche del C++.
-Si deve porre ``extern "C" { ... }`` a delimitare gli include file di Python
-e porre ``extern "C"`` prima di ogni funzione che debba essere chiamata
-dall'interprete Python.
-Oggetti C++ globali o statici con costruttori non sono
-adatti per tale utilizzo.
-
-
-Scrivere in C e' difficile; ci sono altre possibilita'?
---------------------------------------------------------
-Vi sono una serie di alternative a scrivere estensioni in C,
-dipende da cosa si cerca di fare.
-
-Se e' necessaria una maggior velocita' di esecuzione
-`Psyco <http://psyco.sourceforge.net/>`_ 
-genera codice assembler x86 
-dal bytecode Python. E' possibile utilizzare Psyco per compilare le
-funzioni piu' critiche del codice ed ottenere un notevole incremento
-di prestazioni con uno sforzo molto limitato, naturalmente se si
-utilizza un sistema con un processore x86 compatibile.
-
-`Pyrex <http://www.cosc.canterbury.ac.nz/~greg/python/Pyrex/>`_
-e' un compilatore che accetta una sintassi leggermente modificata di Python
-e genera il corrispondente codice C. Pyrex consente di scrivere
-un'estensione senza dover imparare le API C di Python.
-
-Se debbono essere interfacciate librerie C per cui non esista ancora
-un'estensione per Python si puo' effettuare un wrapping
-delle funzioni e dei tipi di dati con 
-`SWIG <http://www.swig.org>`_.
-Per le librerie C++ si possono utilizzare
-`SIP <http://www.riverbankcomputing.co.uk/sip/>`_,
-`CXX <http://cxx.sourceforge.net/>`_,
-`Boost <http://www.boost.org/libs/python/doc/index.html>`_
-o `Weave <http://www.scipy.org/site_content/weave>`_.
-
-
-Come si possono eseguire comandi Python dal C?
-------------------------------------------------------------
-La funzione piu' ad alto livello e'
-``PyRun_SimpleString()``
-che riceve come argomento una singola stringa che deve essere
-eseguita nel contesto del modulo 
-``__main__`` e restituisce 0 in caso di successo e -1
-quando occorre un'eccezione (compreso ``SyntaxError``).
-Se e' necessario un maggior controllo deve essere utilizzata
-``PyRun_String()``;
-si veda il sorgente di ``PyRun_SimpleString()`` in Python/pythonrun.c.
-
-
-Si puo' calcolare il valore di un'espressione Python dal C?
-----------------------------------------------------------------
-Richiamando la funzione ``PyRun_String()``, citata nella domanda
-precedente, con il simbolo di partenza
-``Py_eval_input``; essa
-parsifica un espressione, la valuta e restituisce il suo valore. 
-
-
-Come si estraggono i valori in C da un oggetto Python?
-------------------------------------------------------
-Dipende dal tipo d'oggetto. Se e' una tupla
-``PyTupleSize(o)`` restituisce la sua lunghezza e  ``PyTuple_GetItem(o, i)``
-restituisce il suo i-esimo elemento.
-Le liste hanno funzioni simili: ``PyListSize(o)``
-e ``PyList_GetItem(o, i)``.  
-
-Per le stringhe ``PyString_Size(o)`` restituisce
-la sua lunghezza e ``PyString_AsString(o)`` un puntatore al suo valore.
-Si noti che le stringhe in Python possono contenere byte a null e quindi
-la funzione C ``strlen()``
-non deve essere utilizzata.
-
-Per controllare il tipo di un oggetto innanzi tutto bisogna assicurarsi
-che non sia NULL e quindi utilizzare
-``PyString_Check(o)``, ``PyTuple_Check(o)``,
-``PyList_Check(o)``, ecc.
-
-E' anche disponibile un'API di alto livello agli oggetti Python
-che e' fornita dall'interfaccia chiamata 'astratta' -- si legga
-``Include/abstract.h`` per maggiori dettagli.  Permette di
-interfacciarsi con ogni tipo di sequenza Python utilizzando
-chiamate come
-``PySequence_Length()``, ``PySequence_GetItem()``, ecc.)
-cosi' come altri utili protocolli.
-
-
-Come si puo' richiamare Py_BuildValue() per creare una tupla di lunghezza arbitraria?
----------------------------------------------------------------------------------------
-Non e' possibile.
-E' necessario richiamare
-``t = PyTuple_New(n)`` e caricarla con gli oggetti
-utilizzando ``PyTuple_SetItem(t, i, o)`` -- si deve notare che questa
-tecnica "consuma"
-un contatore di riferimento ad ``o``, quindi e' necessario richiamare ``Py_INCREF``.
-Le liste hanno funzioni similari come ``PyList_New(n)`` e
-``PyList_SetItem(l, i, o)``. 
-Si noti che si *deve* impostare un valore a tutti gli elementi di una
-tupla prima di passare la tupla all'interprete Python --
-``PyTuple_New(n)`` inizializza i valori a NULL, che non e' un valore
-valido per Python.
-
-
-Come si puo' richiamare un metodo di un oggetto in C?
-------------------------------------------------------
-La funzione ``PyObject_CallMethod()`` puo' essere utilizzata per richiamare
-un qualsiasi metodo di un oggetto.
-I parametri sono l'oggetto, il nome del metodo da richiamare,
-una stringa di formato come quella utilizzata con
-``Py_BuildValue()`` ed il valore degli argomenti::
-
-    PyObject *
-    PyObject_CallMethod(PyObject *object, char *method_name,
-                        char *arg_format, ...);
-
-Questo funziona per ogni oggetto che abbia metodi -- sia che siano
-built-in che definiti dall'utente. Il programmatore ha la responsabilita'
-di lanciare ``Py_DECREF`` sul valore di ritorno.
-
-Ad esempio per richiamare il metodo "seek" su un oggetto file con
-argomenti 10, 0 ("f" e' il puntatore all'oggetto file)::
-
-        res = PyObject_CallMethod(f, "seek", "(ii)", 10, 0);
-        if (res == NULL) {
-                ... an exception occurred ...
-        }
-        else {
-                Py_DECREF(res);
-        }
-
-Poiche' ``PyObject_CallObject()`` richiede *sempre* una tupla come
-lista di argomenti, per richiamare una funzione senza argomenti deve
-essere passato "()" come formato e per chiamare una funzione con un
-argomento questo va posto tra parentesi: "(i)".
-
-
-Come si puo' raccogliere l'output da PyErr_Print() (o da qualunque cosa che scriva su standard output/error)?
---------------------------------------------------------------------------------------------------------------
-Nel codice Python si deve definire un oggetto che supporti il metodo
-``write()``.
-Quindi va assegnato questo oggetto a ``sys.stdout`` e ``sys.stderr``.
-Ora chiamando print_error o lasciando operare il meccanismo di traceback
-standard l'output sara' ridiretto ovunque il metodo ``write()`` lo invia.
-
-Il modo piu' semplice di farlo e' utilizzare la classe StringIO della
-libreria standard.
-
-Codice d'esempio per catturare stdout::
-
-	>>> class StdoutCatcher:
-	...     def __init__(self):
-	...         self.data = ''
-	...     def write(self, stuff):
-	...         self.data = self.data + stuff
-	...  
-	>>> import sys
-	>>> sys.stdout = StdoutCatcher()
-	>>> print 'foo'
-	>>> print 'hello world!'
-	>>> sys.stderr.write(sys.stdout.data)
-	foo
-	hello world!
-
-
-Come si accede ad un modulo Python dal C?
----------------------------------------------------------
-Per ottenere un puntatore al modulo si utilizza::
-
-        module = PyImport_ImportModule("<modulename>");
-
-Se il modulo non e' ancora stato importato (ovvero non e' ancora presente in
-``sys.modules``), questo viene inizializzato; altrimenti
-restituisce semplicemente
-il valore di ``sys.modules["<modulename>"]``. 
-Deve essere notato che questo non inserisce
-il modulo in alcun namespace -- assicura solamente che il modulo sia
-inizializzato e caricato in ``sys.modules``.
-
-A questo punto e' possibile accedere agli attributi del modulo
-(ogni nome definito nel modulo) come segue:
-
-        attr = PyObject_GetAttrString(module, "<attrname>");
-
-Chiamando ``PyObject_SetAttrString()``
-si possono anche assegnare valori alle variabili del modulo.
-
-
-Come si interfaccia un oggetto C++ da Python?
-------------------------------------------------------
-A seconda delle necessita' vi sono differenti soluzioni. Per farlo
-manualmente si consiglia di iniziare a leggere
-`il documento "Extending and Embedding" <http://docs.python.org/ext/ext.html>`_.
-Per quello che riguarda il run-time di Python non c'e' una grande
-differenza tra il C ed il C++ -- percio' la strategia di costruire un
-nuovo tipo Python
-intorno ad una struttura C (puntatore) funziona anche con gli
-oggetti C++.
-
-Per le librerie C++ si possono utilizzare
-`SIP <http://www.riverbankcomputing.co.uk/sip/>`_,
-`CXX <http://cxx.sourceforge.net/>`_,
-`Boost <http://www.boost.org/libs/python/doc/index.html>`_,
-o `Weave <http://www.scipy.org/site_content/weave>`_.
-`SWIG <http://www.swig.org>`_
-e' un tool automatico simile che supporta solo librerie C.
-
-
-Aggiungendo un modulo nel file di Setup il make fallisce. Perche'?
-----------------------------------------------------------------------
-Il Setup deve finire con un carattere di fine riga, se non e' presente
-la costruzione fallisce. (Risolvere questo problema richiederebbe un
-noioso shell script,
-ed il bug e' cosi' poco importante che non ne vale la pena.)
-
-
-Come si effettua il debug di un'estensione?
---------------------------------------------
-Utilizzando il GDB con estensioni caricate dinamicamente, non e' possibile
-impostare un breakpoint nell'estensione fino a che non e' caricata.
-
-Basta aggiungere nel file ``.gdbinit`` (o eseguire interattivamente),
-il comando::
-
-	br _PyImport_LoadDynamicModule
-
-Quindi, eseguendo GDB::
-
-	$ gdb /local/bin/python
-	gdb) run myscript.py
-	gdb) continue # repeat until your extension is loaded
-	gdb) finish   # so that your extension is loaded
-	gdb) br myfunction.c:50
-	gdb) continue
-
-
-Cercando di compilare un modulo Python su un sistema Linux risultano mancanti alcuni file. Perche'?
---------------------------------------------------------------------------------------------------
-La maggior parte delle versioni pacchettizzate di Python non include la
-directory /usr/lib/python2.x/config/ che contiene alcuni file necessari
-per compilare le estensioni Python. 
-
-Per Red Hat e' necessario installare l'RPM python-devel.
-
-Per Debian, e' necessario lanciare il comando ``apt-get install python-dev``.
-
-
-Cosa significa "SystemError: _PyImport_FixupExtension: module nomemodulo not loaded"?
--------------------------------------------------------------------------------------------------------
-Significa che e' stata creato un modulo d'estensione chiamato "nomemodulo",
-ma la funzione di init non lo inizializza con quel nome.
-
-Ogni funzione di init di un modulo deve avere una linea simile a::
-
-  module = Py_InitModule("nomemodulo", nomemodulo_functions);
-
-Se la stringa passata a questa funzione non ha lo stesso nome del
-modulo d'estensione viene sollevata l'eccezione ``SystemError``.
-
-
-Come e' possibile restituire "incomplete input" a fronte di un "invalid input"?
---------------------------------------------------------------------------------
-A volte si vuole emulare il comportamento dell'interprete interattivo di Python
-che restituisce un prompt di continuazione quando l'input non e'
-completo (e.g. e' stato digitato l'inizio di una istruzione di "if",
-non e' stata chiusa una parentesi o gli apici tripli di stringa)
-ma restituisce un errore di sintassi immediatamente quando l'input
-non e' corretto.
-
-In Python si puo' utilizzare il modulo ``codeop``, che approssima il
-comportamento del parser a sufficienza. Ad esempio lo utilizza IDLE.
-
-Il modo piu' facile per farlo in C e' richiamare ``PyRun_InteractiveLoop()``
-(magari in un thread separato) e lasciare che sia l'interprete Python
-a gestire l'input. E' anche possibile far puntare ``PyOS_ReadlineFunctionPointer``
-ad una routine custom di gestione dell'input. Si vedano ``Modules/readline.c`` e
-``Parser/myreadline.c`` per ulteriori indicazioni.
-
-Tuttavia a volte si deve eseguire l'interprete Python nello
-stesso thread dell'applicazione e non e' possibile far
-interrompere
-``PyRun_InteractiveLoop()`` in attesa di un input dell'utente.
-L'unica soluzione e' chiamare ``PyParser_ParseString()`` e controllare quando
-``e.error`` e' uguale a ``E_EOF`` (che indica che l'input non e' completo).
-Ecco un frammento di codice d'esempio, non testato, ispirato ad un programma di
-Alex Farber::
-
-  #include <Python.h>
-  #include <node.h>
-  #include <errcode.h>
-  #include <grammar.h>
-  #include <parsetok.h>
-  #include <compile.h>
-
-  int testcomplete(char *code)
-    /* code should end in \n */
-    /* return -1 for error, 0 for incomplete, 1 for complete */
-  {
-    node *n;
-    perrdetail e;
-
-    n = PyParser_ParseString(code, &_PyParser_Grammar,
-                             Py_file_input, &e);
-    if (n == NULL) {
-      if (e.error == E_EOF) 
-        return 0;
-      return -1;
-    }
-
-    PyNode_Free(n);
-    return 1;
-  }
-
-Un'altra soluzione e' di compilare la stringa ricevuta con
-``Py_CompileString()``. Se si compila senza errori si puo' provare ad eseguire il
-codice chiamando ``PyEval_EvalCode()``. Altrimenti si salva l'input per dopo.
-Se la compilazione fallisce si deve cercare se si tratta di un errore o se
-e' richiesto altro input estraendo il messaggio dalla tupla dell'eccezione
-e confrontandola con la stringa "unexpected EOF while parsing".
-Ecco un esempio completo che utilizza la libreria GNU readline
-(si puo' ignorare SIGINT nel richiamare readline())::
-
-  #include <stdio.h>
-  #include <readline.h>
-
-  #include <Python.h>
-  #include <object.h>
-  #include <compile.h>
-  #include <eval.h>
-
-  int main (int argc, char* argv[])
-  {
-    int i, j, done = 0;                          /* lengths of line, code */
-    char ps1[] = ">>> ";
-    char ps2[] = "... ";
-    char *prompt = ps1;
-    char *msg, *line, *code = NULL;
-    PyObject *src, *glb, *loc;
-    PyObject *exc, *val, *trb, *obj, *dum;
-
-    Py_Initialize ();
-    loc = PyDict_New ();
-    glb = PyDict_New ();
-    PyDict_SetItemString (glb, "__builtins__", PyEval_GetBuiltins ());
-
-    while (!done)
-    {
-      line = readline (prompt);
-
-      if (NULL == line)                          /* CTRL-D pressed */
-      {
-        done = 1;
-      }
-      else
-      {
-        i = strlen (line);
-
-        if (i > 0)
-          add_history (line);                    /* save non-empty lines */
-
-        if (NULL == code)                        /* nothing in code yet */
-          j = 0;
-        else
-          j = strlen (code);
-
-        code = realloc (code, i + j + 2);
-        if (NULL == code)                        /* out of memory */
-          exit (1);
-
-        if (0 == j)                              /* code was empty, so */
-          code[0] = '\0';                        /* keep strncat happy */
-
-        strncat (code, line, i);                 /* append line to code */
-        code[i + j] = '\n';                      /* append '\n' to code */
-        code[i + j + 1] = '\0';
-
-        src = Py_CompileString (code, "<stdin>", Py_single_input);       
-
-        if (NULL != src)                         /* compiled just fine - */
-        {
-          if (ps1  == prompt ||                  /* ">>> " or */
-              '\n' == code[i + j - 1])           /* "... " and double '\n' */
-          {                                               /* so execute it */
-            dum = PyEval_EvalCode ((PyCodeObject *)src, glb, loc);
-            Py_XDECREF (dum);
-            Py_XDECREF (src);
-            free (code);
-            code = NULL;
-            if (PyErr_Occurred ())
-              PyErr_Print ();
-            prompt = ps1;
-          }
-        }                                        /* syntax error or E_EOF? */
-        else if (PyErr_ExceptionMatches (PyExc_SyntaxError))           
-        {
-          PyErr_Fetch (&exc, &val, &trb);        /* clears exception! */
-
-          if (PyArg_ParseTuple (val, "sO", &msg, &obj) &&
-              !strcmp (msg, "unexpected EOF while parsing")) /* E_EOF */
-          {
-            Py_XDECREF (exc);
-            Py_XDECREF (val);
-            Py_XDECREF (trb);
-            prompt = ps2;
-          }
-          else                                   /* some other syntax error */
-          {
-            PyErr_Restore (exc, val, trb);
-            PyErr_Print ();
-            free (code);
-            code = NULL;
-            prompt = ps1;
-          }
-        }
-        else                                     /* some non-syntax error */
-        {
-          PyErr_Print ();
-          free (code);
-          code = NULL;
-          prompt = ps1;
-        }
-
-        free (line);
-      }
-    }
-
-    Py_XDECREF(glb);
-    Py_XDECREF(loc);
-    Py_Finalize();
-    exit(0);
-  }
-
-
-
-Come si cercano simboli g++ non definiti __builtin_new o __pure_virtual?
------------------------------------------------------------------------------------
-Per caricare i moduli di estensione g++ bisogna ricompilare Python, effettuare il relink
-utilizzando g++ (cambiando LINKCC nel Makefile dei Moludi Python) e
-effettuare il link i moduli d'estensione utilizzando il g++
-(e.g., "g++ -shared -o mymodule.so mymodule.o").
-
-
-Si possono creare classi con alcuni metodi implementati in C ed altri in Python (eg. mediante ereditarieta')?
------------------------------------------------------------------------------------------------------------------------------------------------------
-A partire da Python 2.2, si puo' ereditare dalle classi builtin come int, list, dict, ecc.
-
-La Boost Python Library (BPL, http://www.boost.org/libs/python/doc/index.html)
-fornisce un modo per farlo dal C++ (ad esempio e' possibile ereditare da una
-classe d'estensione scritta in C++ utilizzando il BPL).
-
-
-Perche' importando un modulo si verifica l'errore "undefined symbol: PyUnicodeUCS2*"?
---------------------------------------------------------------------------------------------------
-Poiche' si sta utilizzando una versione di Python che utilizza
-una rappresentazione a 4 byte
-dei caratteri Unicode mentre si sta importando un modulo che e' stato compilato
-con un Python che utilizza una rappresentazione a 2 byte (che e' il default).
-
-Se il nome del simbolo non definito inizia con
-``PyUnicodeUCS4``, il problema e' l'opposto: Python utilizza caratteri
-Unicode a 2 byte ed il modulo d'estensione e' stato compilato con
-un Python che utilizza caratteri Unicode a 4 byte.
-
-Questo problema si verifica spesso utilizzando pacchetti d'estensione
-precostruiti. RedHat
-Linux 7.x, in particolare forniva un binario "python2" compilato con
-Unicode a 4 byte. Questo causa problemi di link solo se l'estensione
-utilizza una qualsiasi funzione ``PyUnicode_*()``. E' anche un problema
-se l'estensione utilizza una qualsiasi specifica di formato relativa
-agli Unicode per
-``Py_BuildValue`` (o simili) oppure una specifica di parametri per
-``PyArg_ParseTuple()``.
-
-E' possibile verificare la dimensione di un carattere Unicode sull'interprete
-Python controllando il valore di sys.maxunicode::
-
-  >>> import sys
-  >>> if sys.maxunicode > 65535:
-  ...     print 'UCS4 build'
-  ... else:
-  ...     print 'UCS2 build'
-
-L'unico modo per risolvere il problema e' di utilizzare moduli
-d'estensione compilati con un binario Python che utilizzi la stessa dimensione
-per i caratteri Unicode.
-
-
+Title: FAQ Estendere/Includere Python
+Content-type: text/x-rst
+
+====================================
+FAQ Estendere/Includere Python
+====================================
+
+:Date: $Date: 2004-04-08 17:05:47 +0200 (gio, 08 apr 2004) $
+:Version: $Revision: 7294 $
+:Web site: http://www.python.org/
+:Traduzione: Bartolomeo Bogliolo 1 Aprile 2006 (rev. 1.1)
+
+.. contents::
+.. sectnum::
+
+
+**Traduzione Italiana**
+
+Questo documento, di pubblico dominio, e' stato tradotto da 
+`Meo Bogliolo <mailto:meo a bogliolo.name?subject=Traduzione Embedding FAQ>`_ 
+(revisionato da 
+`Daniele Tricoli <mailto:eriol a huine.org?subject=Traduzione Embedding FAQ>`_ 
+): potete contattarli per qualsiasi
+commento o correzione.
+
+
+Si possono creare proprie funzioni in C?
+------------------------------------------
+Si, e' possibile creare moduli built-in che contengono funzioni,
+variabili, eccezioni ed anche nuovi tipi in C. Tutto cio' e' spiegato
+nel documento "Extending and Embedding the Python Interpreter" (http://docs.python.org/ext/ext.html).  
+
+Anche la maggior parte dei libri di livello intermedio o avanzato
+su Python trattano l'argomento.
+
+
+Si possono creare proprie funzioni in C++?
+--------------------------------------------
+Si, utilizzando le caratteristiche di compatibilita' al C tipiche del C++.
+Si deve porre ``extern "C" { ... }`` a delimitare gli include file di Python
+e porre ``extern "C"`` prima di ogni funzione che debba essere chiamata
+dall'interprete Python.
+Oggetti C++ globali o statici con costruttori non sono
+adatti per tale utilizzo.
+
+
+Scrivere in C e' difficile; ci sono altre possibilita'?
+--------------------------------------------------------
+Vi sono una serie di alternative a scrivere estensioni in C,
+dipende da cosa si cerca di fare.
+
+Se e' necessaria una maggior velocita' di esecuzione
+`Psyco <http://psyco.sourceforge.net/>`_ 
+genera codice assembler x86 
+dal bytecode Python. E' possibile utilizzare Psyco per compilare le
+funzioni piu' critiche del codice ed ottenere un notevole incremento
+di prestazioni con uno sforzo molto limitato, naturalmente se si
+utilizza un sistema con un processore x86.
+
+`Pyrex <http://www.cosc.canterbury.ac.nz/~greg/python/Pyrex/>`_
+e' un compilatore che accetta una sintassi leggermente modificata di Python
+e genera il corrispondente codice C. Pyrex consente di scrivere
+un'estensione senza dover imparare le API C di Python.
+
+Se debbono essere interfacciate librerie C per cui non esista ancora
+un'estensione per Python si puo' effettuare un wrapping
+delle funzioni e dei tipi di dati con 
+`SWIG <http://www.swig.org>`_.
+Per le librerie C++ si possono utilizzare
+`SIP <http://www.riverbankcomputing.co.uk/sip/>`_,
+`CXX <http://cxx.sourceforge.net/>`_,
+`Boost <http://www.boost.org/libs/python/doc/index.html>`_
+o `Weave <http://www.scipy.org/site_content/weave>`_.
+
+
+Come si possono eseguire comandi Python dal C?
+------------------------------------------------------------
+La funzione piu' ad alto livello e'
+``PyRun_SimpleString()``
+che riceve come argomento una singola stringa che deve essere
+eseguita nel contesto del modulo 
+``__main__`` e restituisce 0 in caso di successo e -1
+quando occorre un'eccezione (compreso ``SyntaxError``).
+Se e' necessario un maggior controllo deve essere utilizzata
+``PyRun_String()``;
+si veda il sorgente di ``PyRun_SimpleString()`` in Python/pythonrun.c.
+
+
+Si puo' calcolare il valore di un'espressione Python dal C?
+----------------------------------------------------------------
+Richiamando la funzione ``PyRun_String()``, citata nella domanda
+precedente, con il simbolo di partenza
+``Py_eval_input``; essa
+parsifica un espressione, la valuta e restituisce il suo valore. 
+
+
+Come si estraggono i valori in C da un oggetto Python?
+------------------------------------------------------
+Dipende dal tipo d'oggetto. Se e' una tupla
+``PyTupleSize(o)`` restituisce la sua lunghezza e  ``PyTuple_GetItem(o, i)``
+restituisce il suo i-esimo elemento.
+Le liste hanno funzioni simili: ``PyListSize(o)``
+e ``PyList_GetItem(o, i)``.  
+
+Per le stringhe ``PyString_Size(o)`` restituisce
+la sua lunghezza e ``PyString_AsString(o)`` un puntatore al suo valore.
+Si noti che le stringhe in Python possono contenere byte a null e quindi
+la funzione C ``strlen()``
+non deve essere utilizzata.
+
+Per controllare il tipo di un oggetto innanzi tutto bisogna assicurarsi
+che non sia NULL e quindi utilizzare
+``PyString_Check(o)``, ``PyTuple_Check(o)``,
+``PyList_Check(o)``, ecc.
+
+E' anche disponibile un'API di alto livello agli oggetti Python
+che e' fornita dall'interfaccia chiamata 'astratta' -- si legga
+``Include/abstract.h`` per maggiori dettagli.  Permette di
+interfacciarsi con ogni tipo di sequenza Python utilizzando
+chiamate come
+``PySequence_Length()``, ``PySequence_GetItem()``, ecc.)
+cosi' come altri utili protocolli.
+
+
+Come si puo' richiamare Py_BuildValue() per creare una tupla di lunghezza arbitraria?
+---------------------------------------------------------------------------------------
+Non e' possibile.
+E' necessario richiamare
+``t = PyTuple_New(n)`` e caricarla con gli oggetti
+utilizzando ``PyTuple_SetItem(t, i, o)`` -- si deve notare che questa
+tecnica "consuma"
+un contatore di riferimento ad ``o``, quindi e' necessario richiamare ``Py_INCREF``.
+Le liste hanno funzioni similari come ``PyList_New(n)`` e
+``PyList_SetItem(l, i, o)``. 
+Si noti che si *deve* impostare un valore a tutti gli elementi di una
+tupla prima di passare la tupla all'interprete Python --
+``PyTuple_New(n)`` inizializza i valori a NULL, che non e' un valore
+valido per Python.
+
+
+Come si puo' richiamare un metodo di un oggetto in C?
+------------------------------------------------------
+La funzione ``PyObject_CallMethod()`` puo' essere utilizzata per richiamare
+un qualsiasi metodo di un oggetto.
+I parametri sono l'oggetto, il nome del metodo da richiamare,
+una stringa di formato come quella utilizzata con
+``Py_BuildValue()`` ed il valore degli argomenti::
+
+    PyObject *
+    PyObject_CallMethod(PyObject *object, char *method_name,
+                        char *arg_format, ...);
+
+Questo funziona per ogni oggetto che abbia metodi -- sia che siano
+built-in che definiti dall'utente. Il programmatore ha la responsabilita'
+di lanciare ``Py_DECREF`` sul valore di ritorno.
+
+Ad esempio per richiamare il metodo "seek" su un oggetto file con
+argomenti 10, 0 ("f" e' il puntatore all'oggetto file)::
+
+        res = PyObject_CallMethod(f, "seek", "(ii)", 10, 0);
+        if (res == NULL) {
+                ... an exception occurred ...
+        }
+        else {
+                Py_DECREF(res);
+        }
+
+Poiche' ``PyObject_CallObject()`` richiede *sempre* una tupla come
+lista di argomenti, per richiamare una funzione senza argomenti deve
+essere passato "()" come formato e per chiamare una funzione con un
+argomento questo va posto tra parentesi: "(i)".
+
+
+Come si puo' raccogliere l'output da PyErr_Print() (o da qualunque cosa che scriva su standard output/error)?
+--------------------------------------------------------------------------------------------------------------
+Nel codice Python si deve definire un oggetto che supporti il metodo
+``write()``.
+Quindi va assegnato questo oggetto a ``sys.stdout`` e ``sys.stderr``.
+Ora chiamando print_error o lasciando operare il meccanismo di traceback
+standard l'output sara' ridiretto ovunque il metodo ``write()`` lo invia.
+
+Il modo piu' semplice di farlo e' utilizzare la classe StringIO della
+libreria standard.
+
+Codice d'esempio per catturare stdout::
+
+	>>> class StdoutCatcher:
+	...     def __init__(self):
+	...         self.data = ''
+	...     def write(self, stuff):
+	...         self.data = self.data + stuff
+	...  
+	>>> import sys
+	>>> sys.stdout = StdoutCatcher()
+	>>> print 'foo'
+	>>> print 'hello world!'
+	>>> sys.stderr.write(sys.stdout.data)
+	foo
+	hello world!
+
+
+Come si accede ad un modulo Python dal C?
+---------------------------------------------------------
+Per ottenere un puntatore al modulo si utilizza::
+
+        module = PyImport_ImportModule("<modulename>");
+
+Se il modulo non e' ancora stato importato (ovvero non e' ancora presente in
+``sys.modules``), questo viene inizializzato; altrimenti
+restituisce semplicemente
+il valore di ``sys.modules["<modulename>"]``. 
+Deve essere notato che questo non inserisce
+il modulo in alcun namespace -- assicura solamente che il modulo sia
+inizializzato e caricato in ``sys.modules``.
+
+A questo punto e' possibile accedere agli attributi del modulo
+(ogni nome definito nel modulo) come segue:
+
+        attr = PyObject_GetAttrString(module, "<attrname>");
+
+Chiamando ``PyObject_SetAttrString()``
+si possono anche assegnare valori alle variabili del modulo.
+
+
+Come si interfaccia un oggetto C++ da Python?
+------------------------------------------------------
+A seconda delle necessita' vi sono differenti soluzioni. Per farlo
+manualmente si consiglia di iniziare a leggere
+`il documento "Extending and Embedding" <http://docs.python.org/ext/ext.html>`_.
+Per quello che riguarda il run-time di Python non c'e' una grande
+differenza tra il C ed il C++ -- percio' la strategia di costruire un
+nuovo tipo Python
+intorno ad una struttura C (puntatore) funziona anche con gli
+oggetti C++.
+
+Per le librerie C++ si possono utilizzare
+`SIP <http://www.riverbankcomputing.co.uk/sip/>`_,
+`CXX <http://cxx.sourceforge.net/>`_,
+`Boost <http://www.boost.org/libs/python/doc/index.html>`_,
+o `Weave <http://www.scipy.org/site_content/weave>`_.
+`SWIG <http://www.swig.org>`_
+e' un tool automatico simile che supporta solo librerie C.
+
+
+Aggiungendo un modulo nel file di Setup il make fallisce. Perche'?
+----------------------------------------------------------------------
+Il Setup deve finire con un carattere di fine riga, se non e' presente
+la costruzione fallisce. (Risolvere questo problema richiederebbe un
+noioso shell script,
+ed il bug e' cosi' poco importante che non ne vale la pena.)
+
+
+Come si effettua il debug di un'estensione?
+--------------------------------------------
+Utilizzando il GDB con estensioni caricate dinamicamente, non e' possibile
+impostare un breakpoint nell'estensione fino a che non e' caricata.
+
+Basta aggiungere nel file ``.gdbinit`` (o eseguire interattivamente),
+il comando::
+
+	br _PyImport_LoadDynamicModule
+
+Quindi, eseguendo GDB::
+
+	$ gdb /local/bin/python
+	gdb) run myscript.py
+	gdb) continue # repeat until your extension is loaded
+	gdb) finish   # so that your extension is loaded
+	gdb) br myfunction.c:50
+	gdb) continue
+
+
+Cercando di compilare un modulo Python su un sistema Linux risultano mancanti alcuni file. Perche'?
+----------------------------------------------------------------------------------------------------
+La maggior parte delle versioni pacchettizzate di Python non include la
+directory /usr/lib/python2.x/config/ che contiene alcuni file necessari
+per compilare le estensioni Python. 
+
+Per Red Hat e' necessario installare l'RPM python-devel.
+
+Per Debian, e' necessario lanciare il comando ``apt-get install python-dev``.
+
+
+Cosa significa "SystemError: _PyImport_FixupExtension: module nomemodulo not loaded"?
+-------------------------------------------------------------------------------------------------------
+Significa che e' stata creato un modulo d'estensione chiamato "nomemodulo",
+ma la funzione di init non lo inizializza con quel nome.
+
+Ogni funzione di init di un modulo deve avere una linea simile a::
+
+  module = Py_InitModule("nomemodulo", nomemodulo_functions);
+
+Se la stringa passata a questa funzione non ha lo stesso nome del
+modulo d'estensione viene sollevata l'eccezione ``SystemError``.
+
+
+Come e' possibile restituire "incomplete input" a fronte di un "invalid input"?
+--------------------------------------------------------------------------------
+A volte si vuole emulare il comportamento dell'interprete interattivo di Python
+che restituisce un prompt di continuazione quando l'input non e'
+completo (e.g. e' stato digitato l'inizio di una istruzione di "if",
+non e' stata chiusa una parentesi o gli apici tripli di stringa)
+ma restituisce un errore di sintassi immediatamente quando l'input
+non e' corretto.
+
+In Python si puo' utilizzare il modulo ``codeop``, che approssima il
+comportamento del parser a sufficienza. Ad esempio lo utilizza IDLE.
+
+Il modo piu' facile per farlo in C e' richiamare ``PyRun_InteractiveLoop()``
+(magari in un thread separato) e lasciare che sia l'interprete Python
+a gestire l'input. E' anche possibile far puntare ``PyOS_ReadlineFunctionPointer``
+ad una routine custom di gestione dell'input. Si vedano ``Modules/readline.c`` e
+``Parser/myreadline.c`` per ulteriori indicazioni.
+
+Tuttavia a volte si deve eseguire l'interprete Python nello
+stesso thread dell'applicazione e non e' possibile far
+interrompere
+``PyRun_InteractiveLoop()`` in attesa di un input dell'utente.
+L'unica soluzione e' chiamare ``PyParser_ParseString()`` e controllare quando
+``e.error`` e' uguale a ``E_EOF`` (che indica che l'input non e' completo).
+Ecco un frammento di codice d'esempio, non testato, ispirato ad un programma di
+Alex Farber::
+
+  #include <Python.h>
+  #include <node.h>
+  #include <errcode.h>
+  #include <grammar.h>
+  #include <parsetok.h>
+  #include <compile.h>
+
+  int testcomplete(char *code)
+    /* code should end in \n */
+    /* return -1 for error, 0 for incomplete, 1 for complete */
+  {
+    node *n;
+    perrdetail e;
+
+    n = PyParser_ParseString(code, &_PyParser_Grammar,
+                             Py_file_input, &e);
+    if (n == NULL) {
+      if (e.error == E_EOF) 
+        return 0;
+      return -1;
+    }
+
+    PyNode_Free(n);
+    return 1;
+  }
+
+Un'altra soluzione e' di compilare la stringa ricevuta con
+``Py_CompileString()``. Se si compila senza errori si puo' provare ad eseguire il
+codice chiamando ``PyEval_EvalCode()``. Altrimenti si salva l'input per dopo.
+Se la compilazione fallisce si deve cercare se si tratta di un errore o se
+e' richiesto altro input estraendo il messaggio dalla tupla dell'eccezione
+e confrontandola con la stringa "unexpected EOF while parsing".
+Ecco un esempio completo che utilizza la libreria GNU readline
+(si puo' ignorare SIGINT nel richiamare readline())::
+
+  #include <stdio.h>
+  #include <readline.h>
+
+  #include <Python.h>
+  #include <object.h>
+  #include <compile.h>
+  #include <eval.h>
+
+  int main (int argc, char* argv[])
+  {
+    int i, j, done = 0;                          /* lengths of line, code */
+    char ps1[] = ">>> ";
+    char ps2[] = "... ";
+    char *prompt = ps1;
+    char *msg, *line, *code = NULL;
+    PyObject *src, *glb, *loc;
+    PyObject *exc, *val, *trb, *obj, *dum;
+
+    Py_Initialize ();
+    loc = PyDict_New ();
+    glb = PyDict_New ();
+    PyDict_SetItemString (glb, "__builtins__", PyEval_GetBuiltins ());
+
+    while (!done)
+    {
+      line = readline (prompt);
+
+      if (NULL == line)                          /* CTRL-D pressed */
+      {
+        done = 1;
+      }
+      else
+      {
+        i = strlen (line);
+
+        if (i > 0)
+          add_history (line);                    /* save non-empty lines */
+
+        if (NULL == code)                        /* nothing in code yet */
+          j = 0;
+        else
+          j = strlen (code);
+
+        code = realloc (code, i + j + 2);
+        if (NULL == code)                        /* out of memory */
+          exit (1);
+
+        if (0 == j)                              /* code was empty, so */
+          code[0] = '\0';                        /* keep strncat happy */
+
+        strncat (code, line, i);                 /* append line to code */
+        code[i + j] = '\n';                      /* append '\n' to code */
+        code[i + j + 1] = '\0';
+
+        src = Py_CompileString (code, "<stdin>", Py_single_input);       
+
+        if (NULL != src)                         /* compiled just fine - */
+        {
+          if (ps1  == prompt ||                  /* ">>> " or */
+              '\n' == code[i + j - 1])           /* "... " and double '\n' */
+          {                                               /* so execute it */
+            dum = PyEval_EvalCode ((PyCodeObject *)src, glb, loc);
+            Py_XDECREF (dum);
+            Py_XDECREF (src);
+            free (code);
+            code = NULL;
+            if (PyErr_Occurred ())
+              PyErr_Print ();
+            prompt = ps1;
+          }
+        }                                        /* syntax error or E_EOF? */
+        else if (PyErr_ExceptionMatches (PyExc_SyntaxError))           
+        {
+          PyErr_Fetch (&exc, &val, &trb);        /* clears exception! */
+
+          if (PyArg_ParseTuple (val, "sO", &msg, &obj) &&
+              !strcmp (msg, "unexpected EOF while parsing")) /* E_EOF */
+          {
+            Py_XDECREF (exc);
+            Py_XDECREF (val);
+            Py_XDECREF (trb);
+            prompt = ps2;
+          }
+          else                                   /* some other syntax error */
+          {
+            PyErr_Restore (exc, val, trb);
+            PyErr_Print ();
+            free (code);
+            code = NULL;
+            prompt = ps1;
+          }
+        }
+        else                                     /* some non-syntax error */
+        {
+          PyErr_Print ();
+          free (code);
+          code = NULL;
+          prompt = ps1;
+        }
+
+        free (line);
+      }
+    }
+
+    Py_XDECREF(glb);
+    Py_XDECREF(loc);
+    Py_Finalize();
+    exit(0);
+  }
+
+
+
+Come si cercano simboli g++ non definiti __builtin_new o __pure_virtual?
+-----------------------------------------------------------------------------------
+Per caricare i moduli di estensione g++ bisogna ricompilare Python, effettuare il relink
+utilizzando g++ (cambiando LINKCC nel Makefile dei Moludi Python) e
+effettuare il link i moduli d'estensione utilizzando il g++
+(e.g., "g++ -shared -o mymodule.so mymodule.o").
+
+
+Si possono creare classi con alcuni metodi implementati in C ed altri in Python (eg. mediante ereditarieta')?
+-----------------------------------------------------------------------------------------------------------------------------------------------------
+A partire da Python 2.2, si puo' ereditare dalle classi builtin come int, list, dict, ecc.
+
+La Boost Python Library (BPL, http://www.boost.org/libs/python/doc/index.html)
+fornisce un modo per farlo dal C++ (ad esempio e' possibile ereditare da una
+classe d'estensione scritta in C++ utilizzando il BPL).
+
+
+Perche' importando un modulo si verifica l'errore "undefined symbol: PyUnicodeUCS2*"?
+--------------------------------------------------------------------------------------------------
+Poiche' si sta utilizzando una versione di Python che utilizza
+una rappresentazione a 4 byte
+dei caratteri Unicode mentre si sta importando un modulo che e' stato compilato
+con un Python che utilizza una rappresentazione a 2 byte (che e' il default).
+
+Se il nome del simbolo non definito inizia con
+``PyUnicodeUCS4``, il problema e' l'opposto: Python utilizza caratteri
+Unicode a 2 byte ed il modulo d'estensione e' stato compilato con
+un Python che utilizza caratteri Unicode a 4 byte.
+
+Questo problema si verifica spesso utilizzando pacchetti d'estensione
+precostruiti. RedHat
+Linux 7.x, in particolare forniva un binario "python2" compilato con
+Unicode a 4 byte. Questo causa problemi di link solo se l'estensione
+utilizza una qualsiasi funzione ``PyUnicode_*()``. E' anche un problema
+se l'estensione utilizza una qualsiasi specifica di formato relativa
+agli Unicode per
+``Py_BuildValue`` (o simili) oppure una specifica di parametri per
+``PyArg_ParseTuple()``.
+
+E' possibile verificare la dimensione di un carattere Unicode sull'interprete
+Python controllando il valore di sys.maxunicode::
+
+  >>> import sys
+  >>> if sys.maxunicode > 65535:
+  ...     print 'UCS4 build'
+  ... else:
+  ...     print 'UCS2 build'
+
+L'unico modo per risolvere il problema e' di utilizzare moduli
+d'estensione compilati con un binario Python che utilizzi la stessa dimensione
+per i caratteri Unicode.
+
+


More information about the Commits mailing list