Search code examples
c#.netironpythondynamic-language-runtime

IronPython DLR; passing parameters to compiled code?


I'm currently doing the following to create and execute a simple python calculation, using DLR:

ScriptRuntime runtime = Python.CreateRuntime();
ScriptEngine engine = runtime.GetEngine("py");

MemoryStream ms = new MemoryStream();
runtime.IO.SetOutput(ms, new StreamWriter(ms));

ScriptSource ss = engine.CreateScriptSourceFromString("print 1+1", SourceCodeKind.InteractiveCode);

CompiledCode cc = ss.Compile();
cc.Execute();

int length = (int)ms.Length;
Byte[] bytes = new Byte[length];
ms.Seek(0, SeekOrigin.Begin);
ms.Read(bytes, 0, (int)ms.Length);
string result = Encoding.GetEncoding("utf-8").GetString(bytes, 0, (int)ms.Length);

Console.WriteLine(result);

Which prints '2' to the console, but;

I want to get the result of 1 + 1 without having to print it (as that seems to be a costly operation). Anything I assign the result of cc.Execute() to is null. Is there any other way I can get the resulting variables from Execute()?

I am also trying to find a way to pass in parameters, i.e. so the result is arg1 + arg2 and have no idea how to do that; the only other overload for Execute takes ScriptScope as a parameter, and I've never used python before. Can anyone help?

[Edit] The answer to both questions: (Desco's accepted as pointed me in the right direction)

ScriptEngine py = Python.CreateEngine();
ScriptScope pys = py.CreateScope();

ScriptSource src = py.CreateScriptSourceFromString("a+b");
CompiledCode compiled = src.Compile();

pys.SetVariable("a", 1);
pys.SetVariable("b", 1);
var result = compiled.Execute(pys);

Console.WriteLine(result);

Solution

  • You can either evaluate expression in Python and return its result (1) or assign value to some variable in scope and later pick it (2):

        var py = Python.CreateEngine();
    
        // 1
        var value = py.Execute("1+1");
        Console.WriteLine(value);
    
        // 2
        var scriptScope = py.CreateScope();
        py.Execute("a = 1 + 1", scriptScope);
        var value2 = scriptScope.GetVariable("a");
        Console.WriteLine(value2);