在C#中实例化python类

时间:2009-02-23 20:47:26

标签: c# .net python ironpython cross-language

我在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#中实例化这个类,我该怎么做?

4 个答案:

答案 0 :(得分:55)

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

要在C#中使用Python类,您需要使用ObjectOperations类。该类允许您在语言本身的语义中操作python类型和实例。例如它在适当时使用魔术方法,自动将整数提升为long等。您可以通过查看源或使用反射器来了解有关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使用 new 动态类型使这更容易。

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

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

Install-Package IronPython

答案 1 :(得分:31)

现在.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的引用。

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

但是一旦源被成功执行,由于新的“动态”关键字,使用python函数要容易得多。

答案 2 :(得分:0)

我正在更新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. Using Compiled Python Classes from .NET/CSharp IP 2.6
  2. Static Compilation of IronPython scripts

答案 3 :(得分:-4)

我搜索过高低,我担心似乎没有太多关于此的信息。我非常确定没有人设计出一种方法,以你想要的干净方式做到这一点。

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