Search code examples
c#.netironpythonembeddingvalue-type

How to handle value types when embedding IronPython in C#?


There is a well known issue when it comes to using .NET value types in IronPython. This has recently caused me a headache when trying to use Python as an embedded scripting language in C#. The problem can be summed up as follows:

Given a C# struct such as:

struct Vector {
    public float x;
    public float y;
}

And a C# class such as:

class Object {
    public Vector position;
}

The following will happen in IronPython:

obj = Object()
print obj.position.x    # prints ‘0’
obj.position.x = 1
print obj.position.x    # still prints ‘0’

As the article states, this means that value types are mostly immutable. However, this is a problem as I was planning on using a vector library that is implemented as seen above. Are there any workarounds for working with existing libraries that rely on value types? Modifying the library would be the very last resort, but I'd rather avoid that.


Solution

  • There's no need to modify the library, just use a proxy.

    struct Vector {
        public float X;
        public float Y;
    }
    
    class BetterVector {
        public float X;
        public float Y;
        public Vector Optimized { get { return new Vector(X, Y); } }
    }
    
    class Object {
        public BetterVector Position { get; set; }
    }
    

    Now the Python code can set fields as normal and your code can call Optimized when it needs to feed the data to OpenGL or XNA or whatever you're using.

    You can even use implicit coercion if calling Optimized seems like too much work:

    class BetterVector {
       // ...
       public static implicit operator Vector(BetterVector v) {
           return v.Optimized;
       }
    }