C#/ IronPython与共享C#类库互操作

时间:2022-09-02 12:01:48

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.

我正在尝试使用IronPython作为C#GUI和一些C#库之间的中介,以便它可以在编译后编写脚本。

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

我有一个类库DLL,由GUI和python使用,是这样的:

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

The IronPython code is as follows:

IronPython代码如下:

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

ReturnObject = MyClass("Test")

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

然后,在C#中我将其称为如下:

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

当我调用最后一段代码时,source.Execute(scope)运行成功返回,但是当我尝试GetVariable调用时,它抛出以下异常

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?

DLL与.py文件位于不同的目录中(我只是没有写出所有路径设置的东西),可能是因为IronPython的解释器存在问题,因为它看起来不同,因为它是某种方式看到他们处于不同的背景或范围?

2 个解决方案

#1


11  

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:

此错误表示您的程序集已加载到多个CLR加载程序上下文中。您可以切换到clr.AddReference,也可以从C#加载程序集,而不是使用clr.AddReferenceToFile添加引用。对于前者,您需要确保程序集在.NET可以正常加载它的位置(GAC或进程的应用程序库)中可用。对于后者你可以这样做:

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.

来自您的C#主机代码。就个人而言,我更喜欢这个第二个解决方案,因为它不仅可以帮助您节省用户从Python进行clr.AddRef调用。

#2


1  

You might try running your program under the debugger and breaking execution prior to the GetVariable call. Go to the "modules" window and see if there are two versions of your C# class library DLL loaded. If that's the case, then that's the explanation.

您可以尝试在调试器下运行程序并在GetVariable调用之前中断执行。转到“模块”窗口,查看是否加载了两个版本的C#类库DLL。如果是这样,那就是解释。

If that's the problem, then the solution is to make sure C# and Python worlds agree on the types. One solution is to put everything in the same directory. Another possibility is to set up a reference to your class library in C# by using the properties on the ScriptScope class (I think) to set an assembly reference to your class library assembly that will be available to the Python code. I don't have a hybrid C#/IronPython project immediately available to test against, but I remember seeing that functionality.

如果这是问题,那么解决方案是确保C#和Python世界在类型上达成一致。一种解决方案是将所有内容放在同一目录中。另一种可能性是通过使用ScriptScope类(我认为)上的属性来设置对C#中类库的引用,以设置可供Python代码使用的类库程序集的程序集引用。我没有立即可用于测试的混合C#/ IronPython项目,但我记得看到了这个功能。

#1


11  

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:

此错误表示您的程序集已加载到多个CLR加载程序上下文中。您可以切换到clr.AddReference,也可以从C#加载程序集,而不是使用clr.AddReferenceToFile添加引用。对于前者,您需要确保程序集在.NET可以正常加载它的位置(GAC或进程的应用程序库)中可用。对于后者你可以这样做:

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.

来自您的C#主机代码。就个人而言,我更喜欢这个第二个解决方案,因为它不仅可以帮助您节省用户从Python进行clr.AddRef调用。

#2


1  

You might try running your program under the debugger and breaking execution prior to the GetVariable call. Go to the "modules" window and see if there are two versions of your C# class library DLL loaded. If that's the case, then that's the explanation.

您可以尝试在调试器下运行程序并在GetVariable调用之前中断执行。转到“模块”窗口,查看是否加载了两个版本的C#类库DLL。如果是这样,那就是解释。

If that's the problem, then the solution is to make sure C# and Python worlds agree on the types. One solution is to put everything in the same directory. Another possibility is to set up a reference to your class library in C# by using the properties on the ScriptScope class (I think) to set an assembly reference to your class library assembly that will be available to the Python code. I don't have a hybrid C#/IronPython project immediately available to test against, but I remember seeing that functionality.

如果这是问题,那么解决方案是确保C#和Python世界在类型上达成一致。一种解决方案是将所有内容放在同一目录中。另一种可能性是通过使用ScriptScope类(我认为)上的属性来设置对C#中类库的引用,以设置可供Python代码使用的类库程序集的程序集引用。我没有立即可用于测试的混合C#/ IronPython项目,但我记得看到了这个功能。