2010-09-06 8 views
9

He estado experimentando con la incrustación de diferentes lenguajes de scripting en una aplicación C++, actualmente estoy probando Stackless Python 3.1. He intentado varios tutoriales y ejemplos, los pocos que puedo encontrar, para intentar ejecutar un script simple desde una aplicación.¿Por qué la Python/C API falla en 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(); 

Por alguna extraña razón, la ejecución de este pedazo de código resultados en una violación de acceso en:

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

He buscado en línea para otros con un problema similar y ha encontrado un único. Su única solución era una solución que sólo parece posible en una versión anterior de Python: Creación de un objeto de archivo y devolver el pitón FILE* de ese objeto fichero de Python en PyRun_SimpleFile. Tales llamadas a funciones no están disponibles sin embargo, la API de Python 3.1 crea objetos de archivo de un descriptor de archivo y devuelve los descriptores de archivo, pero la función PyRun_SimpleFile todavía requiere un FILE*.

Estoy en una pérdida en cuanto a cómo ejecutar las secuencias de comandos de archivo, sin llegar a cargar el archivo en la memoria manualmente y funcionando como una cadena gigante, ciertamente no es una solución práctica.

Lo que da? ¿Cómo puedo lograr esta tarea si la API tiene un error interno?

Actualización: He logrado construir Stackless Python 3.1 desde la fuente y, sin embargo, el bloqueo permanece completamente sin cambios, a pesar de utilizar la misma biblioteca de tiempo de ejecución de C. Tanto mi proyecto como la fuente de Stackless Python 3.1 están construidos con el compilador C++ de Visual Studio 2010 y el tiempo de ejecución de C. Ya no tengo idea de qué podría resolver este problema, salvo la modificación de Python para usar un nombre de archivo y no un ARCHIVO *. Otra terrible solución.

Respuesta

3

Esto suena como un problema de APIs que no coinciden. Si su código y el tiempo de ejecución de Python fueron compilados con diferentes compiladores, o incluso con diferentes opciones del compilador, entonces el acceso al ARCHIVO * podría resultar en una violación de acceso. ¿Puedes verificar que has construido tu código C correctamente?

usted menciona que usted está incrustación de Python en su aplicación C++. Tenga en cuenta que Python es código C, compilado como código C. Tal vez esa es la fuente del problema?

+0

Sí, yo no construí la librería Stackless Python 3.1. Había leído que el problema podría ser el uso de ARCHIVOS * de diferentes tiempos de ejecución, por lo que la solución fue permitir que la biblioteca de Python creara el ARCHIVO * y lo devolviera para usarlo como argumento para la función. Entonces, ¿no tengo otra opción que adquirir la fuente y construir Stackless Python 3.1 yo mismo? –

+0

Si puedes construir tu código C, entonces no deberías tener ninguna dificultad con el código Stackless. –

5

el código funciona correctamente en mi versión instalada de Python 2.6. También construí stackless 3.1.2 desde la fuente y funcionó correctamente. Esto fue con g ++ 4.4.3 en Ubuntu 10.04. Si está en Windows, es posible que desee comprobar que tanto el stackless como su código se compilan contra el mismo tiempo de ejecución de C.

+0

Bueno, ahí es donde me estoy metiendo en problemas. Sé que el tiempo de ejecución de C es diferente. Estoy usando Visual Studio 2010 y estoy bastante seguro de que la mayoría de los binarios de Python están compilados con Visual Studio 2008. He intentado construir el origen de Stackless Python 3.1, pero no estoy del todo seguro de qué bibliotecas, archivos DLL y encabezados Se necesitan. Sin mencionar que hay algunos problemas con respecto a algunos de los módulos de extensión que no se crean debido a archivos perdidos. El archivo por lotes proporcionado para construirlos depende de varios otros archivos que faltan, como tener SVN instalado. –

+0

@Sion: Desafortunadamente, no hay nada más que pueda ofrecer además de decir "verificar los documentos" y "buena suerte". No tengo acceso a una máquina de desarrollo de Windows, y mucho menos a VS2010. ¿Hay alguna forma de escribir un pequeño contenedor para las partes relevantes de stdio que está construido con la versión de Visual Studio correcta? –

+0

No obstante, se agradece la ayuda, aunque en este punto incluso el mismo compilador y tiempo de ejecución no han tenido ningún efecto en resolver el problema. Es posible que tenga que intentar contactar a los desarrolladores u otros gurús de Python directamente. –

12

que estaba recibiendo un accidente similares & hizo el siguiente:

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

Tenga en cuenta que esto fue en Python 2.7 sin embargo. No sé si la API ha cambiado en 3.x.

+0

Como se sospechaba, esto no funciona con Python 3. – MasterMind

9

Esto funciona para mí en Python 3:

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

espero Sería útil.

+2

Obras para mí, pero con una pequeña modificación: ARCHIVO archivo * = _Py_fopen ("test.py", "r +"); PyRun_SimpleFile (archivo, "test.py"); Esto debe marcarse como la respuesta. – MasterMind

+1

@MasterMind: El OP de la respuesta obviamente quería llamar a la función '_Py_fopen_obj' en lugar de a la función' _Py_fopen'. Edité la respuesta en consecuencia (por lo que el código de la respuesta debería funcionar ahora). Sin embargo, su solución parece ser más fácil/más ligera. Por alguna razón, ambas soluciones * solo * funcionaron si declaraba el 'const char *' filepath-variable ** después de ** la función 'Py_Initialize()' o si pongo directamente la cadena como lo hizo en su ejemplo. (para ser sincero: el contenedor de Python C++ es un problema y podría ser mucho más simple) – mozzbozz

0

Si construyó su prueba con VC 2010, definitivamente tendrá problemas: VC9 (VS 2008) y VC10 (VS 2010) tienen archivos DLL de compatibilidad mutuamente incompatibles que generalmente se requieren (implemente printf, archivo de E/S y ese tipo de la cosa).No puede mezclarlos si incluyen las bibliotecas estándar, lo que hace la creación de python.

Siempre tiene la opción de usar gcc (por ejemplo, Cygwin o mingw) o descargar Visual Studio 2008 express, que debería funcionar bien para la experimentación en la incrustación de python. He usado ambos con la versión estándar de Python 2.7.6.

0

Y qué pasa con esta solución:

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

Dónde ex30.py que el nombre del script en Python, estoy corriendo.

Cuestiones relacionadas