Tuesday, May 3, 2011

How to pass a lambda expression to a C# constructor from an IronPython script?

I'm integrating an IronPython scritping engine into my C# raytracer which, so far, has been a breeze even though I'm completely new to Python. There is one particular thing, though, that I need help with. I have a C# class which defines a constructor like this:

public CameraAnimation(Action<Camera, float> animation)

In C#, I would instantiate this like so:

var camAnimation = new CameraAnimation((camera, time) => camera.Position += new Vector(1, 0, 0));

I can't quite figure out how to make a similar assignment for the Action object in IronPython, so how would the Python syntax look?

From stackoverflow
  • Assuming I interpreted this right, and Action is a generic delegate, the below works (the stubs I used are included).

    Python:

    import clr
    clr.AddReference("IronPythonDelegates")
    
    import IronPythonDelegates
    
    def camActionPy(camera, time):
      print "Camera: " + str(camera) + ", time: " + str(time)
    
    IronPythonDelegates.CameraAnimation(camActionPy);
    

    CSharp:

    namespace IronPythonDelegates
    {
        public class Camera{}
    
        public class CameraAnimation
        {
        private System.Action<Camera, float> animation;
    
        public CameraAnimation(System.Action<Camera, float> animation)
        {
            this.animation = animation;
            this.animation(new Camera(), 1.5f);
        }
        }
     }
    

    I corrected the above to use System.Action, and it no longer requires explicit reflection. It's a bit weird though. For some reason, I could construct a user-created delegate like:

    explicitTestAction = IronPythonDelegates.TestAction[IronPythonDelegates.Camera, System.Single](camActionPy);
    IronPythonDelegates.CameraAnimation(explicitTestAction);
    

    but could not do so with System.Action. E.g. with

    explicitSystemAction = System.Action[IronPythonDelegates.Camera, System.Single](camActionPy)
    IronPythonDelegates.CameraAnimation(explicitSystemAction);
    

    explicitSystemAction is null. TestAction was just defined as:

    public delegate void TestAction(T1 one, T2 two);

    But luckily either way it's fine to just do:

    CameraAnimation(System.Action) or CameraAnimation(TestAction)

    though for some reason I don't remember that working when I first tried...

    Matthew Flaschen : Note, I found System.Action, but unfortunately changing it to use that inexplicably broke the code... Looking at it now.
    srivatsn : Did you add a reference to System.Core.dll? System.Action is defined in mscorlib but System.Action is defined in System.Core.
    Matthew Flaschen : Yes, I have a reference to System.Core. As noted, I have it working now.

0 comments:

Post a Comment

Note: Only a member of this blog may post a comment.