在C#中实例化一个python类
我已经写了一个python类,我想通过IronPython包装到.net程序集中,并在C#应用程序中实例化。 我已经将类迁移到IronPython,创build了一个库程序集并引用它。 现在,我怎样才能真正得到这个类的一个实例呢?
class级看起来(部分)如下:
class PokerCard: "A card for playing poker, immutable and unique." def __init__(self, cardName):
我在C#中编写的testing存根是:
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#中实例化这个类,我需要做些什么?
IronPython类不是 .NET类。 它们是Python元类IronPython.Runtime.Types.PythonType的实例。 这是因为Python类是dynamic的,支持在运行时添加和删除方法,这是.NET类无法做到的。
要在C#中使用Python类,您将需要使用ObjectOperations类。 这个类允许你在语言本身的语义上对pythontypes和实例进行操作。 例如它在适当时使用魔术方法,自动将整数提升为长整型等。通过查看源代码或使用reflection器,可以了解关于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。
使用新的dynamictypes,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);
如果您使用Visual Studio 2010或更高版本的NuGet支持,只需执行此操作即可下载并引用相应的库。
Install-Package IronPython
现在.NET 4.0已经发布并且具有dynamictypes,这个例子应该被更新。 使用与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的引用。
如您所见,源文件的初始设置和创build是相同的。
但是一旦源码成功执行,由于新的“dynamic”关键字,使用python函数更容易。
我正在更新上面的Clever Human提供的编译IronPython类(dll)而不是.py文件中的IronPython源代码的例子。
# Compile IronPython calculator class to a dll clr.CompileModules("calculator.dll", "calculator.py")
新的dynamictypes的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);
参考文献:
- 使用.NET / CSharp IP 2.6编译的Python类
- 静态编译IronPython脚本
我search了高低,恐怕似乎没有太多有关这方面的信息。 我非常肯定,没有人devise出一种你想要的干净方式来做到这一点。
我认为这是一个问题的主要原因是,为了在你的C#应用程序中看到PokerCard
types,你必须将你的Python代码编译成IL。 我不相信在那里有任何Python ->
IL编译器。