Adding PyRun_String to Runtime
I would like to run Python strings and get an object return from .NET. To this end I added PyRun_String to the Runtime object and another method to PythonEngine ala the existing SimpleString implementation. Everything compiles, but Runtime.PyRun_String always returns a NULL, and it does not look like the code is being run. Is there any trick to adding new methods to the Runtime? // From Runtime.cs [DllImport(Runtime.dll, CallingConvention=CallingConvention.Cdecl, ExactSpelling=true, CharSet=CharSet.Ansi)] internal unsafe static extern IntPtr PyRun_String(string code, int start, IntPtr globals, IntPtr locals); // From Python.cs public static PyObject RunString(string code) { IntPtr globals = Runtime.PyEval_GetGlobals(); IntPtr locals = Runtime.PyEval_GetLocals(); IntPtr ret; ret = Runtime.PyRun_String(code, 257,globals, locals); Runtime.Decref(globals); Runtime.Decref(locals); if (ret == IntPtr.Zero) { throw new PythonException(); } return new PyObject(ret); }
Hi Michael - I assume you're running an older version of Python for NET? The current version has an implementation of RunString: public static PyObject RunString(string code) { IntPtr globals = Runtime.PyEval_GetGlobals(); IntPtr locals = Runtime.PyDict_New(); IntPtr builtins = Runtime.PyEval_GetBuiltins(); Runtime.PyDict_SetItemString(locals, "__builtins__", builtins); IntPtr flag = (IntPtr)257; /* Py_file_input */ IntPtr result = Runtime.PyRun_String(code, flag, globals, locals); Runtime.Decref(locals); if (result == IntPtr.Zero) { return null; } return new PyObject(result); } The trick is that for various reasons you can't depend on the PyEval_GetLocals call to return anything meaningful, so you have to build the locals dict manually. HTH, Brian Lloyd brian@zope.com V.P. Engineering 540.361.1716 Zope Corporation http://www.zope.com
-----Original Message----- From: pythondotnet-bounces@python.org [mailto:pythondotnet-bounces@python.org]On Behalf Of Michael Eddington Sent: Sunday, August 14, 2005 1:36 AM To: pythondotnet@python.org Subject: [Python.NET] Adding PyRun_String to Runtime
I would like to run Python strings and get an object return from .NET. To this end I added PyRun_String to the Runtime object and another method to PythonEngine ala the existing SimpleString implementation.
Everything compiles, but Runtime.PyRun_String always returns a NULL, and it does not look like the code is being run.
Is there any trick to adding new methods to the Runtime?
// From Runtime.cs
[DllImport(Runtime.dll, CallingConvention=CallingConvention.Cdecl, ExactSpelling=true, CharSet=CharSet.Ansi)] internal unsafe static extern IntPtr PyRun_String(string code, int start, IntPtr globals, IntPtr locals);
// From Python.cs
public static PyObject RunString(string code) { IntPtr globals = Runtime.PyEval_GetGlobals(); IntPtr locals = Runtime.PyEval_GetLocals(); IntPtr ret;
ret = Runtime.PyRun_String(code, 257,globals, locals);
Runtime.Decref(globals); Runtime.Decref(locals);
if (ret == IntPtr.Zero) { throw new PythonException(); }
return new PyObject(ret); } _________________________________________________ Python.NET mailing list - PythonDotNet@python.org http://mail.python.org/mailman/listinfo/pythondotnet
Brian, I upgraded to the latest distribution but still had issues with the RunString included. Seems GetGlobals also has issues. I ended up re-writing the implementation as such follows. This seems to work reliably. One difference from the two implementations is I'm sending __builtin__ as the globals dictionary Searching through the Python mail archives I found a couple of references that this is the correct thing todo. Also, I'm keeping the locals dictionary around, seems like the right things todo, but not sure. protected static PyDict locals = null; public static PyObject RunString(string code) { PyDict globals = new PyDict(Runtime.PyModule_GetDict(ImportModule("__builtin__").Handle)); if(locals == null) { locals = new PyDict(Runtime.PyDict_New()); } IntPtr flag = (IntPtr)257; /* Py_file_input */ IntPtr result = Runtime.PyRun_String(code, flag, globals.Handle, locals.Handle); if (result == IntPtr.Zero) { return null; } return new PyObject(result); } Brian Lloyd wrote:
Hi Michael - I assume you're running an older version of Python for NET? The current version has an implementation of RunString:
public static PyObject RunString(string code) { IntPtr globals = Runtime.PyEval_GetGlobals(); IntPtr locals = Runtime.PyDict_New();
IntPtr builtins = Runtime.PyEval_GetBuiltins(); Runtime.PyDict_SetItemString(locals, "__builtins__", builtins);
IntPtr flag = (IntPtr)257; /* Py_file_input */ IntPtr result = Runtime.PyRun_String(code, flag, globals, locals); Runtime.Decref(locals); if (result == IntPtr.Zero) { return null; } return new PyObject(result); }
The trick is that for various reasons you can't depend on the PyEval_GetLocals call to return anything meaningful, so you have to build the locals dict manually.
HTH,
Brian Lloyd brian@zope.com V.P. Engineering 540.361.1716 Zope Corporation http://www.zope.com
-----Original Message----- From: pythondotnet-bounces@python.org [mailto:pythondotnet-bounces@python.org]On Behalf Of Michael Eddington Sent: Sunday, August 14, 2005 1:36 AM To: pythondotnet@python.org Subject: [Python.NET] Adding PyRun_String to Runtime
I would like to run Python strings and get an object return from .NET. To this end I added PyRun_String to the Runtime object and another method to PythonEngine ala the existing SimpleString implementation.
Everything compiles, but Runtime.PyRun_String always returns a NULL, and it does not look like the code is being run.
Is there any trick to adding new methods to the Runtime?
// From Runtime.cs
[DllImport(Runtime.dll, CallingConvention=CallingConvention.Cdecl, ExactSpelling=true, CharSet=CharSet.Ansi)] internal unsafe static extern IntPtr PyRun_String(string code, int start, IntPtr globals, IntPtr locals);
// From Python.cs
public static PyObject RunString(string code) { IntPtr globals = Runtime.PyEval_GetGlobals(); IntPtr locals = Runtime.PyEval_GetLocals(); IntPtr ret;
ret = Runtime.PyRun_String(code, 257,globals, locals);
Runtime.Decref(globals); Runtime.Decref(locals);
if (ret == IntPtr.Zero) { throw new PythonException(); }
return new PyObject(ret); } _________________________________________________ Python.NET mailing list - PythonDotNet@python.org http://mail.python.org/mailman/listinfo/pythondotnet
participants (2)
-
Brian Lloyd
-
Michael Eddington