1

I am using Iron Python as an added 'for free' tool to test the an API that wrapps comms to some custom hardware so the non-development team can play with the hardware via python.

However I can't work out how to get .NET void func(params object[] args) to map to Python def (*args).

Here is some code to explain.

I have a type that allows injecting a logging callback to format and deal with messages is follows the signature of Console.WriteLine and Debug.WriteLine.

public class Engine
{
    Action<string, object[]> _logger;
    public void Run()
    {
        Log("Hello '{0}'", "world");
    }
    public void SetLog(Action<string, object[]> logger)
    {
        _logger = logger;
    }
    void Log(string msg, params object[] args)
    {
        _logger(msg, args);
    }
}

in my IronPython code

import clr
from System import *
from System.IO import Path
clr.AddReferenceToFileAndPath(Path.GetFullPath(r"MyAssembly.dll"))
from MyNamespace import *

def logger(msg, *args):
    print( String.Format(msg, args))
    print( String.Format(msg, list(args)))
    print( String.Format(msg, [args]))
    a=[]
    for i in args:
        a.append(i)
    print( String.Format(msg, a) )

e = Engine()
e.SetLog(logger)
e.Run()

output

Hello '('world',)'
Hello 'IronPython.Runtime.List'
Hello 'IronPython.Runtime.List'
Hello 'IronPython.Runtime.List'

I would like

Hello 'world'
3
  • possible duplicate of Assigning a Iron Python list to .NET array Commented Aug 17, 2012 at 12:54
  • If it is a duplicate of that post then either I don't understand my own question or I don't understand theirs (or both :-) Commented Aug 17, 2012 at 13:17
  • I think the question referenced by @HansPassant is not a hard duplicate but hints at one of the possible solutions (see my answer and the conversion to Array[object]). Commented Aug 19, 2012 at 12:28

2 Answers 2

2

Because String.Format handles your iron python objects (tuple for your first output case, lists for the last three) as single objects and is not aware that you would like the python collection to be used as params object[] you are getting the unexpected output. The single python object/tuple is implicitly created when def logger is invoked.

Depending on your actual use-case/style you can solve this in different ways.

The most python-y way would be expanding the arguments at their call site like Jeff explains in his answer:

def logger(msg, *args):
    print( String.Format(msg, *args) )

If you call logger only as from CLR as implementation of Action<string, object[]> you could just have args be a single (not variable) argument of type object[] like

def logger(msg, args):
    print( String.Format(msg, args) )

If you would like to call logger from python with variable arguments as well (and you don't mind the back and forth conversion) you could do

def logger(msg, *args):
    print( String.Format(msg, Array[object](args)) )
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, I used the Array[object](args) solution. The fact that I can use python at all is a bonus, so this cast which would be hidden away from most users is perfectly acceptable.
2

Unless I'm misunderstanding your question, this should work:

def logger(msg, *args):
    print(String.Format(msg, *args))

1 Comment

Expanding the var args at call cite seems to be more elegant! I will check/verify and delete my answer if that works out for all cases.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.