2009-02-23 3 views
40

Я написал класс на python, который я хочу связать с .NET-сборкой через IronPython и создать экземпляр в приложении C#. Я перенесла класс в IronPython, создал сборку библиотеки и ссылался на нее. Теперь, как мне получить экземпляр этого класса?Создание экземпляра класса python в C#

Класс выглядит (частично), как это:

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

ответ

51

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

Чтобы использовать классы Python в C#, вам нужно будет использовать класс ObjectOperations. Этот класс позволяет работать с типами и экземплярами python в семантике самого языка. например он использует магические методы, когда это необходимо, автоматически продвигает целые числа в longs и т. д. Вы можете узнать больше об 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. Скрипты и 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 
+1

Я не имею rep редактировать это , но в примере Calculator.py первый «def» должен быть отступом. Отличный пример, хотя! Очень полезно. Теперь, когда .NET 4.0 отсутствует, было бы неплохо увидеть обновленный пример. –

+5

Добавлен пример. Net 4.0, используя тот же класс образца калькулятора. –

+0

Спасибо, я добавил отступ. –

-4

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

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

31

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

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

+0

Спасибо за добавление примера! –

+0

Это действительно помогло! –

0

Я обновляю приведенный выше пример, предоставленный 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. Using Compiled Python Classes from .NET/CSharp IP 2.6
  2. Static Compilation of IronPython scripts
Смежные вопросы