在 C# 中实例化一个 python 类

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/579272/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 09:04:50  来源:igfitidea点击:

Instantiating a python class in C#

c#.netpythonironpythoncross-language

提问by Yes - that Jake.

I've written a class in python that I want to wrap into a .net assembly via IronPython and instantiate in a C# application. I've migrated the class to IronPython, created a library assembly and referenced it. Now, how do I actually get an instance of that class?

我已经在 python 中编写了一个类,我想通过 IronPython 将其包装到 .net 程序集中并在 C# 应用程序中实例化。我已将该类迁移到 IronPython,创建了一个库程序集并引用了它。现在,我如何实际获得该类的实例?

The class looks (partially) like this:

这个类看起来(部分)是这样的:

class PokerCard:
    "A card for playing poker, immutable and unique."

    def __init__(self, cardName):

The test stub I wrote in C# is:

我用 C# 编写的测试存根是:

using System;

namespace pokerapp
{
    class Program
    {
        static void Main(string[] args)
        {
            var card = new PokerCard(); // I also tried new PokerCard("Ah")
            Console.WriteLine(card.ToString());
            Console.ReadLine();
        }
    }
}

What do I have to do in order to instantiate this class in C#?

为了在 C# 中实例化这个类,我必须做什么?

采纳答案by m-sharp

IronPython classes are not.NET classes. They are instances of IronPython.Runtime.Types.PythonType which is the Python metaclass. This is because Python classes are dynamic and support addition and removal of methods at runtime, things you cannot do with .NET classes.

IronPython 类不是.NET 类。它们是 IronPython.Runtime.Types.PythonType 的实例,它是 Python 元类。这是因为 Python 类是动态的,并且支持在运行时添加和删除方法,这是 .NET 类无法做到的。

To use Python classes in C# you will need to use the ObjectOperations class. This class allows you to operate on python types and instances in the semantics of the language itself. e.g. it uses the magic methods when appropriate, auto-promotes integers to longs etc. You can find out more about ObjectOperations by looking at the source or using reflector.

要在 C# 中使用 Python 类,您需要使用 ObjectOperations 类。此类允许您在语言本身的语义中对 python 类型和实例进行操作。例如,它在适当的时候使用魔法方法,将整数自动提升为长整数等。您可以通过查看源或使用反射器来了解有关 ObjectOperations 的更多信息。

Here is an example. Calculator.py contains a simple class:

这是一个例子。Calculator.py 包含一个简单的类:

class Calculator(object):
    def add(self, a, b):
        return a + b

You can use it from your pre .NET 4.0 C# code like this:

您可以在 .NET 4.0 之前的 C# 代码中使用它,如下所示:

ScriptEngine engine = Python.CreateEngine();
ScriptSource source = engine.CreateScriptSourceFromFile("Calculator.py");
ScriptScope scope = engine.CreateScope();

ObjectOperations op = engine.Operations;

source.Execute(scope); // class object created
object klaz = scope.GetVariable("Calculator"); // get the class object
object instance = op.Call(klaz); // create the instance
object method = op.GetMember(instance, "add"); // get a method
int result = (int)op.Call(method, 4, 5); // call method and get result (9)

You will need to reference the assemblies IronPython.dll, Microsoft.Scripting and Microsoft.Scripting.Core.

您将需要引用程序集 IronPython.dll、Microsoft.Scripting 和 Microsoft.Scripting.Core。

C# 4 made this much easier with the newdynamic type.

C# 4 使用新的动态类型使这变得更加容易。

ScriptEngine engine = Python.CreateEngine();
ScriptSource source = engine.CreateScriptSourceFromFile("Calculator.py");
ScriptScope scope = engine.CreateScope();
source.Execute(scope);

dynamic Calculator = scope.GetVariable("Calculator");
dynamic calc = Calculator();
int result = calc.add(4, 5);

If you are using Visual Studio 2010 or later with NuGet support simply execute this to download and reference the appropriate libraries.

如果您使用的是带有 NuGet 支持的 Visual Studio 2010 或更高版本,只需执行此操作即可下载并引用相应的库。

Install-Package IronPython

回答by Andrew Hare

I have searched high and low and I am afraid that there does not seem to be much information pertaining to this. I am pretty much certain that no one has devised a way to do this in the clean manner that you would like.

我搜索了高低,恐怕与此相关的信息似乎并不多。我几乎可以肯定,没有人设计出一种您想要的干净方式来做到这一点。

The main reason I think this is a problem is that in order to see the PokerCardtype in your C# application you would have to compile your Python code to IL. I don't believe that there are any Python->IL compilers out there.

我认为这是一个问题的主要原因是,为了查看PokerCardC# 应用程序中的类型,您必须将 Python 代码编译为 IL。我不相信那里有任何 Python ->IL 编译器。

回答by CleverPatrick

Now that .Net 4.0 is released and has the dynamic type, this example should be updated. Using the same python file as in m-sharp's original answer:

现在 .Net 4.0 已经发布并且具有动态类型,这个例子应该被更新。使用与 m-sharp 的原始答案相同的 python 文件:

class Calculator(object):
    def add(self, a, b):
        return a + b

Here is how you would call it using .Net 4.0:

以下是您如何使用 .Net 4.0 调用它:

string scriptPath = "Calculator.py";
ScriptEngine engine = Python.CreateEngine();
engine.SetSearchPaths(new string[] {"Path to your lib's here. EG:", "C:\Program Files (x86)\IronPython 2.7.1\Lib"});
ScriptSource source = engine.CreateScriptSourceFromFile(scriptPath);
ScriptScope scope = engine.CreateScope();
ObjectOperations op = engine.Operations;
source.Execute(scope);

dynamic Calculator = scope.GetVariable("Calculator");
dynamic calc = Calculator();
return calc.add(x,y);          

Again, you need to add references to IronPython.dll and Microsoft.Scripting.

同样,您需要添加对 IronPython.dll 和 Microsoft.Scripting 的引用。

As you can see, the initial setting up and creating of the source file is the same.

如您所见,源文件的初始设置和创建是相同的。

But once the source is succesfully executed, working with the python functions is far easier thanks to the new "dynamic" keyword.

但是一旦源代码成功执行,由于新的“dynamic”关键字,使用 python 函数会容易得多。

回答by bhadra

I am updating the above example provided by Clever Human for compiled IronPython classes (dll) instead of IronPython source code in a .py file.

我正在更新 Clever Human 为编译的 IronPython 类 (dll) 而不是 .py 文件中的 IronPython 源代码提供的上述示例。

# Compile IronPython calculator class to a dll
clr.CompileModules("calculator.dll", "calculator.py")

C# 4.0 code with the new dynamic type is as follows:

带有新动态类型的 C# 4.0 代码如下:

// IRONPYTHONPATH environment variable is not required. Core ironpython dll paths should be part of operating system path.
ScriptEngine pyEngine = Python.CreateEngine();
Assembly myclass = Assembly.LoadFile(Path.GetFullPath("calculator.dll"));
pyEngine.Runtime.LoadAssembly(myclass);
ScriptScope pyScope = pyEngine.Runtime.ImportModule("calculator");
dynamic Calculator = pyScope.GetVariable("Calculator");
dynamic calc = Calculator();
int result = calc.add(4, 5);

References:

参考:

  1. Using Compiled Python Classes from .NET/CSharp IP 2.6
  2. Static Compilation of IronPython scripts
  1. 使用来自 .NET/CSharp IP 2.6 的编译 Python 类
  2. IronPython 脚本的静态编译