我正在用C#调用IronPython函数。似乎在定义上,此函数捕获其原始范围。当我稍后在没有显式范围的情况下调用它时,它仍然可以访问该原始范围的值。即使我更改范围值,它也会正确读取新值。看一下这个例子:
using IronPython.Hosting;
using IronPython.Runtime;
using IronPython.Runtime.Operations;
using Microsoft.Scripting;
using Microsoft.Scripting.Hosting;
namespace IronPythonFuncTest {
class Program {
static void Main() {
ScriptEngine scriptEngine = Python.CreateEngine();
// Create scope with a global value for the script to use
ScriptScope scriptScope = scriptEngine.CreateScope();
scriptScope.SetVariable("someGlobalValue", 10);
// Execute script defining function foo(x)
string script = "def foo(): print(someGlobalValue)";
ScriptSource scriptSource = scriptEngine.
CreateScriptSourceFromString(script, SourceCodeKind.Statements);
scriptSource.Execute(scriptScope);
// Extract foo from the scope
PythonFunction foo = scriptScope.GetVariable<PythonFunction>("foo");
// Change someGlobalValue
scriptScope.SetVariable("someGlobalValue", 42);
// Call foo. This prints 42, not 10 (or nothing).
PythonCalls.Call(foo);
}
}
}
现在我想知道:PythonCalls.Call()
的大多数重载都期望一个CodeContext
对象(如果我理解正确的话,主要代表一个范围)。如果我在不传递代码上下文的情况下调用上面的IronPython函数,我会丢失一些东西吗?鉴于该函数显然在创建时捕获了其原始范围,因此传递额外的代码上下文似乎没有任何意义。是否存在使我有所作为的情况?
答案 0 :(得分:0)
为什么要通过foo
致电PythonCall.Call
?尝试这样做:scriptScope.Host.ScriptEngine.Operations.InvokeMember(CLASS-Instance, METHOD-Name, ARGUMENTS);
比Ironpython正确处理它自己的CodeContext
。您可以在此处找到示例实现:DlrClass/InvokeMember。
据我所知,CodeContext
不仅仅是范围,只需看看定义:
/// <summary>
/// Captures and flows the state of executing code from the generated
/// Python code into the IronPython runtime.
/// </summary>
[DebuggerTypeProxy(typeof(CodeContext.DebugProxy)), DebuggerDisplay("module: {ModuleName}", Type="module")]
public sealed class CodeContext { // ... }
希望这有帮助!