tags:

views:

77

answers:

2

I have embedded an IronPython engine in a C# application. I want to expose some custom commands (methods) to the interpreter. How do I do this?

Currently, I have something like this:

public delegate void MyMethodDel(string printText);

Main(string[] args)
{
    ScriptEngine engine = Python.CreateEngine();
    ScriptScope scope = engine.CreateScope();

    MyMethodDel del = new MyMethodDel(MyPrintMethod);
    scope.SetVariable("myprintcommand", del);

    while(true)
    {
        Console.Write(">>>");
        string line = Console.ReadLine();

        ScriptSource script = engine.CreateScriptSourceFromString(line, SourceCodeKind.SingleStatement);
        CompiledCode code = script.Compile();
        script.Execute(scope);
    }
}

void MyPrintMethod(string text)
{
    Console.WriteLine(text);
}

I can use this like this:

>>>myprintcommand("Hello World!")
Hello World!
>>>

This works fine. I wanted to know, if this is the correct way/best practice to do what I want to achieve?

How can I expose overloads of the same method. For example, if I wanted to expose a method like myprintcommand(string format, object[] args).

With the way I am currently doing it, the key "myprintcommand" can be mapped to only one delegate. Therefore I will have to change the name of the command/method if I want to expose the overloaded "myprintcommand" to the interpreter. Is there any other way to achieve what I want?

+2  A: 

You would probably have to write your own logic for that. Eg:

public delegate void MyMethodDel(params object[] args);

void MyPrintMethod(params object[] args)
{
  switch (args.Length)
  {
    case 1:
      Console.WriteLine((string)args[0]);
      break;
    ...
    default:
      throw new InvalidArgumentCountException();
  }
}

This may or may not work; I am not sure how they handle the 'params' attribute anymore.

leppie
A: 

There's an easier way to do this. Instead of using the script scope to make a member accessible to IronPython, you can load the C# assembly into the engine runtime.

engine.Runtime.LoadAssembly(typeof(MyClass).Assembly);

This will preload the assembly containing the class MyClass. For example, assuming that MyPrintMethod is a static member of MyClass, you would then be able to make the following call from the IronPython interpreter.

from MyNamespace import MyClass
MyClass.MyPrintMethod('some text to print')
MyClass.MyPrintMethod('some text to print to overloaded method which takes a bool flag', True)
Tom E