2014-06-18 16 views
5

Sto chiamando una funzione IronPython da C#. Sembra che, per definizione, questa funzione acquisisca il suo ambito originale. Quando in seguito lo chiamerò senza un ambito esplicito, potrà comunque accedere ai valori da tale ambito originale. Anche se cambio i valori di scope, legge correttamente i nuovi valori. Date un'occhiata a questo esempio:Pertinenza di CodeContext quando si chiama la funzione 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); 
     } 
    } 
} 

Ora mi chiedo: La maggior parte dei sovraccarichi di PythonCalls.Call() si aspettano un oggetto CodeContext (che, se ho ben capito, rappresenta soprattutto un ambito). Sto perdendo qualcosa se chiamo una funzione IronPython come sopra, senza passare un contesto di codice? Dato che la funzione ha apparentemente catturato il suo ambito originale sulla creazione, non sembra esserci alcun punto nel passare un contesto di codice aggiuntivo. Ci sono situazioni in cui fa la differenza, se lo faccio?

risposta

0

Perché si chiama foo su PythonCall.Call? Prova a farlo in questo modo: scriptScope.Host.ScriptEngine.Operations.InvokeMember(CLASS-Instance, METHOD-Name, ARGUMENTS); di quanto Ironpython gestirà correttamente il CodeContext su di esso. È possibile trovare un'implementazione di esempio qui: DlrClass/InvokeMember.

Per quanto ne so, il CodeContext è più che il campo di applicazione, basta dare un'occhiata alla definizione:

/// <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 { // ... } 

Spero che questo aiuti!