2010-09-06 9 views
9

Ho sperimentato l'incorporamento di diversi linguaggi di scripting in un'applicazione C++, attualmente sto provando Stackless Python 3.1. Ho provato diversi tutorial ed esempi, i pochi che riesco a trovare, per provare a eseguire un semplice script da un'applicazione.Perché l'API Python/C si blocca su PyRun_SimpleFile?

Py_Initialize(); 

FILE* PythonScriptFile = fopen("Python Scripts/Test.py", "r"); 
if(PythonScriptFile) 
{ 
    PyRun_SimpleFile(PythonScriptFile, "Python Scripts/Test.py"); 
    fclose(PythonScriptFile); 
} 

Py_Finalize(); 

Per qualche strana ragione, l'esecuzione di questo pezzo di risultati di codice in una violazione di accesso a:

PyRun_SimpleFile(PythonScriptFile, "Python Scripts/Test.py"); 

Ho cercato on-line per gli altri con un problema simile e hanno trovato solo uno. La loro unica soluzione è stata una soluzione che sembra possibile solo in una versione precedente di Python: creazione di un oggetto file python e restituzione di FILE* da tale oggetto file python in PyRun_SimpleFile. Tali chiamate di funzioni non sono tuttavia disponibili, l'API di Python 3.1 crea oggetti file da un descrittore di file e restituisce descrittori di file, ma la funzione PyRun_SimpleFile richiede ancora un FILE*.

Sono in perdita su come eseguire qualsiasi script da file, a meno di caricare l'intero file in memoria manualmente e eseguirlo come una stringa gigante, certamente non una soluzione pratica.

Cosa dà? Come posso eseguire questa attività se l'API ha un errore interno?

Aggiornamento: Sono riuscito a creare Stackless Python 3.1 dall'origine e tuttavia l'arresto rimane completamente invariato, nonostante si utilizzi la stessa libreria di runtime C. Sia il mio progetto che l'origine Stackless Python 3.1 sono costruiti con il compilatore C++ di Visual Studio 2010 e il runtime C. Non ho più alcun dubbio su cosa potrebbe risolvere questo problema, a meno di modificare Python per usare un nome di file e non un FILE *. Un'altra soluzione terribile.

risposta

3

Sembra un problema di API non corrispondenti. Se il tuo codice e il runtime di Python sono stati compilati con compilatori diversi, o anche con diverse opzioni del compilatore, l'accesso al FILE * potrebbe causare una violazione di accesso. Puoi ricontrollare che hai costruito correttamente il tuo codice C?

Si dice che si sta incorporando Python nell'applicazione C++. Tieni presente che Python è un codice C, compilato come codice C. Forse questa è la fonte del problema?

+0

Aye, non ho creato la libreria Stackless Python 3.1 autonomamente. Ho letto che il problema potrebbe essere l'uso di FILE * da diversi runtime, quindi perché la soluzione era consentire alla libreria Python di creare il FILE * e restituirlo come argomento per la funzione. Quindi, non ho altra scelta che acquisire il codice sorgente e creare Stackless Python 3.1 da solo? –

+0

Se puoi costruire il tuo codice C, non dovresti avere alcuna difficoltà con il codice Stackless. –

5

Il tuo codice funziona correttamente sulla mia versione installata di Python 2.6. Ho anche creato stackless 3.1.2 dal sorgente e ha funzionato correttamente. Questo era con g ++ 4.4.3 su Ubuntu 10.04. Se sei su Windows, potresti voler controllare che sia lo stackless sia il tuo codice siano costruiti sullo stesso runtime C.

+0

Beh, è ​​lì che mi trovo nei guai. So che il runtime C è diverso. Sto usando Visual Studio 2010 e sono abbastanza sicuro che la maggior parte dei binari Python sono costruiti con Visual Studio 2008. Sto provando a creare il sorgente Stackless Python 3.1, ma non sono del tutto sicuro quali librerie, DLL e intestazioni sono necessari. Per non parlare ci sono alcuni problemi riguardanti alcuni dei moduli di estensione che non si creano a causa di file mancanti. Il file batch fornito per costruirli dipende da molti altri file mancanti, come avere SVN installato. –

+0

@Sion: Purtroppo, non c'è altro che posso offrire oltre a dire "controlla i documenti" e "buona fortuna". Non ho accesso a un computer di sviluppo Windows, figuriamoci a VS2010. C'è un modo per scrivere un piccolo wrapper per le parti rilevanti di stdio che è stato creato con la corretta versione di Visual Studio? –

+0

L'aiuto è comunque apprezzato, anche se a questo punto anche lo stesso compilatore e runtime non hanno avuto alcun effetto sulla risoluzione del problema. Potrei benissimo provare a contattare direttamente gli sviluppatori o altri guru di Python. –

12

mi è stato sempre un incidente simile & ha fatto il seguito:

PyObject* PyFileObject = PyFile_FromString("test.py", "r"); 
    PyRun_SimpleFileEx(PyFile_AsFile(PyFileObject), "test.py", 1); 

Si noti che questo era in python 2.7 però. Non so se l'API è cambiata in 3.x.

+0

Come sospetti, questo non funziona con Python 3. – MasterMind

9

questo funziona per me su Python 3:

PyObject *obj = Py_BuildValue("s", "test.py"); 
FILE *file = _Py_fopen_obj(obj, "r+"); 
if(file != NULL) { 
    PyRun_SimpleFile(file, "test.py"); 
} 

Spero Sarebbe utile.

+2

Funziona per me, ma con piccole modifiche: FILE * file = _Py_fopen ("test.py", "r +"); PyRun_SimpleFile (file, "test.py"); Questo dovrebbe essere contrassegnato come la risposta. – MasterMind

+1

@MasterMind: l'OP della risposta ovviamente voleva chiamare la funzione '_Py_fopen_obj' invece della funzione' _Py_fopen'. Ho modificato la risposta di conseguenza (quindi il codice della risposta dovrebbe ora funzionare immediatamente). La tua soluzione sembra essere più facile/più leggera però. Per qualche ragione, entrambe le soluzioni * only * hanno funzionato se avessi dichiarato 'const char *' filepath-variable ** dopo ** la funzione 'Py_Initialize()' o se inserissi direttamente la stringa come hai fatto nel tuo esempio. (per essere onesti: il wrapper Python C++ è un dolore e potrebbe essere molto più semplice) – mozzbozz

0

Se hai eseguito il test con VC 2010, avrai sicuramente problemi - VC9 (VS 2008) e VC10 (VS 2010) hanno DLL di supporto reciprocamente incompatibili che sono normalmente richieste (implementa printf, file i/o e quel tipo di cosa).Non è possibile combinarli se includono le librerie standard, come fa la build python.

Hai sempre la possibilità di utilizzare gcc (ad es. Cygwin o mingw) o di scaricare Visual Studio 2008 Express, che dovrebbe funzionare bene per la sperimentazione in embedding di python. Ho usato entrambi con la versione standard di Python 2.7.6.

0

E che dire di questa soluzione:

Py_SetProgramName(argv[0]); 
Py_Initialize(); 
PyRun_SimpleString("execfile(\"ex30.py\")"); 
Py_Finalize(); 

Dove ex30.py è il nome dello script python sto facendo funzionare.