Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# / IronPython Interop with shared C# Class Library

I'm trying to use IronPython as an intermediary between a C# GUI and some C# libraries, so that it can be scripted post compile time.

I have a Class library DLL that is used by both the GUI and the python and is something along the lines of this:

namespace MyLib
{
    public class MyClass
    {
        public string Name { get; set; }
        public MyClass(string name)
        {
            this.Name = name;
        }
    }
}

The IronPython code is as follows:

import clr
clr.AddReferenceToFile(r"MyLib.dll")
from MyLib import MyClass

ReturnObject = MyClass("Test")

Then, in C# I would call it as follows:

ScriptEngine engine = Python.CreateEngine();
ScriptScope scope = null;

scope = engine.CreateScope();
ScriptSource source = engine.CreateScriptSourceFromFile("Script.py");

source.Execute(scope);

MyClass mc = scope.GetVariable<MyClass>("ReturnObject ")

When I call this last bit of code, source.Execute(scope) runs returns successfully, but when I try the GetVariable call, it throw the following exception

Microsoft.Scripting.ArgumentTypeException: expected MyClass , got MyClass 

So, you can see that the class names are exactly the same, but for some reason it thinks they are different.

The DLL is in a different directory than the .py file (I just didn't bother to write out all the path setup stuff), could it be that there is an issue with the interpreter for IronPython seeing these objects as difference because it's somehow seeing them as being in a different context or scope?

like image 882
Adam Haile Avatar asked Jun 09 '10 19:06

Adam Haile


1 Answers

This error indicates that your assembly is getting loaded into multiple CLR loader contexts. Rather than adding the reference using clr.AddReferenceToFile you can either switch to clr.AddReference or you can load the assembly from C#. For the former you need to make sure that the assembly is available somewhere that .NET can normally load it (the GAC or in the application base of the process). For the latter you can just do:

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

from your C# host code. Personally I like this 2nd solution a little bit more because not only does it work it saves your users from needing to do the clr.AddRef call from Python.

like image 149
Dino Viehland Avatar answered Nov 14 '22 23:11

Dino Viehland