在 C# 中实例化 python 类

发布于 2024-07-14 13:42:28 字数 651 浏览 7 评论 0原文

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

该类看起来(部分)如下所示:

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

    def __init__(self, cardName):

我用 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();
        }
    }
}

为了在 C# 中实例化此类,我需要做什么?

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?

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:

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#?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

别想她 2024-07-21 13:42:28

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

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

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

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

您可以在 .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)

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

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);

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

Install-Package IronPython

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.

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.

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

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:

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.

C# 4 made this much easier with the new dynamic type.

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.

Install-Package IronPython
清秋悲枫 2024-07-21 13:42:28

现在 .Net 4.0 已发布并具有动态类型,因此应该更新此示例。 使用与 m-sharp 的原始答案中相同的 python 文件:

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

这是使用 .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);          

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

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

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

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:

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

Here is how you would call it using .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.

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.

無心 2024-07-21 13:42:28

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

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

新动态类型的 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);

参考资料:

  1. 使用编译的 Python .NET/CSharp IP 2.6 中的类
  2. IronPython 脚本的静态编译

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

# 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:

// 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
流绪微梦 2024-07-21 13:42:28

我查遍了,恐怕与此相关的信息似乎并不多。 我非常确定没有人能够设计出一种方法来以您希望的干净方式做到这一点。

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

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 PokerCard type 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文