Создание класса Python в C # - PullRequest
42 голосов
/ 23 февраля 2009

Я написал класс на python, который хочу обернуть в сборку .net через IronPython и создать экземпляр в приложении 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 ]

55 голосов
/ 24 февраля 2009

Классы IronPython не .NET. Они являются экземплярами IronPython.Runtime.Types.PythonType, который является метаклассом Python. Это связано с тем, что классы Python являются динамическими и поддерживают добавление и удаление методов во время выполнения, что нельзя делать с классами .NET.

Чтобы использовать классы Python в C #, вам нужно будет использовать класс 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);

Если вы используете Visual Studio 2010 или более позднюю версию с поддержкой NuGet, просто выполните это для загрузки и ссылки на соответствующие библиотеки.

Install-Package IronPython
31 голосов
/ 27 апреля 2010

Теперь, когда .Net 4.0 выпущен и имеет динамический тип, этот пример должен быть обновлен. Используя тот же файл python, что и в исходном ответе m-sharp:

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 становится намного проще благодаря новому ключевому слову "dynamic".

0 голосов
/ 11 июня 2013

Я обновляю приведенный выше пример, предоставленный Clever Human для скомпилированных классов IronPython (dll) вместо исходного кода IronPython в файле .py.

# 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
0 голосов
/ 24 февраля 2009

Я искал все выше и ниже, и я боюсь, что, похоже, не так много информации, касающейся этого. Я почти уверен, что никто не придумал, как сделать это так, как вам хотелось бы.

Основная причина, по которой я считаю эту проблему, заключается в том, что для того, чтобы увидеть тип PokerCard в вашем приложении C #, вам необходимо скомпилировать код Python для IL. Я не верю, что есть какие-либо компиляторы Python -> IL.

...