在 C# 中实例化 python 类
-
06-09-2019 - |
题
我已经用 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# 中实例化此类,我需要做什么?
解决方案
IronPython的类不的.NET类。他们是IronPython.Runtime.Types.PythonType这是Python元类的实例。这是因为Python类是动态的,支持在运行时的方法添加和删除,事情你不能与.NET类的事情。
要使用C#Python类,您将需要使用ObjectOperations类。这个类可以让你在语言本身的语义上的蟒蛇类型和实例进行操作。例如它使用魔术方法在适当的时候,自动促进整数多头等你可以通过查看源或使用反射器找到更多关于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);
如果您正在使用Visual Studio 2010或更高版本的NuGet支持只能执行该下载和引用相应的库。
Install-Package IronPython
其他提示
现在该.NET 4.0被释放,并且具有动态型,本实施例应被更新。使用相同的蟒文件作为米锋利的原来的答案:
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函数工作被更容易由于新的“动态”的关键字。
我正在更新 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);
参考:
我查遍了,恐怕与此相关的信息似乎并不多。我非常确定没有人能够设计出一种方法来以您希望的干净方式做到这一点。
我认为这是一个问题的主要原因是为了看到 PokerCard
输入 C# 应用程序后,您必须将 Python 代码编译为 IL。我不相信有Python->
IL 编译器就在那里。