Pregunta

He escrito una clase en Python que quiero para envolver en un ensamblado de .NET a través de IronPython y cree una instancia en una aplicación de C #. He migrado a la clase IronPython, creado un ensamblado de biblioteca y se hace referencia ella. Ahora, ¿cómo lo consigo realmente una instancia de esa clase?

Las miradas de clase (parcialmente) como este:

class PokerCard:
    "A card for playing poker, immutable and unique."

    def __init__(self, cardName):

El talón de prueba he escrito en C # es:

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

¿Qué tengo que hacer con el fin de crear una instancia de esta clase en C #?

¿Fue útil?

Solución

clases

IronPython son no .NET clases. Son ejemplos de IronPython.Runtime.Types.PythonType que es la metaclase Python. Esto se debe a las clases de Python son dinámicos y apoyar la adición y eliminación de los métodos en tiempo de ejecución, las cosas no se puede hacer con las clases de .NET.

Para utilizar las clases de Python en C # que tendrá que utilizar la clase ObjectOperations. Esta clase le permite operar sobre los tipos de pitón y las instancias en la semántica del lenguaje mismo. p.ej. que utiliza los métodos mágicos en su caso, de auto-promueve a números enteros largos, etc Usted puede encontrar más información acerca ObjectOperations mirando el código fuente o mediante reflector.

Este es un ejemplo. Calculator.py contiene una clase simple:

class Calculator(object):
    def add(self, a, b):
        return a + b

Se puede utilizar desde su pre .NET 4.0 C # código siguiente:

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)

Usted tendrá que hacer referencia a las asambleas IronPython.dll, Microsoft.Scripting y Microsoft.Scripting.Core.

C # 4 hace esto mucho más fácil con el nueva tipo dinámico.

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

Si está utilizando Visual Studio 2010 o posterior con el apoyo NuGet simplemente ejecutar este para descargar y hacer referencia a las bibliotecas apropiadas.

Install-Package IronPython

Otros consejos

Ahora que .Net 4.0 es liberado y tiene el tipo dinámico, este ejemplo debería ser actualizado. Usando el mismo archivo Python como en m-aguda de respuesta original:

class Calculator(object):
    def add(self, a, b):
        return a + b

Así es como ustedes lo llaman usando .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);          

Una vez más, es necesario agregar referencias a IronPython.dll y Microsoft.Scripting.

Como se puede ver, el ajuste inicial y la creación del archivo de origen es el mismo.

Pero una vez que se ejecuta con éxito la fuente, trabajando con las funciones de Python es mucho más fácil gracias a la nueva palabra clave "dinámica".

Estoy actualizando el ejemplo anterior proporcionada por Clever Humano para las clases compiladas IronPython (DLL) en lugar del código fuente IronPython en un archivo .py.

# Compile IronPython calculator class to a dll
clr.CompileModules("calculator.dll", "calculator.py")

C # 4.0 código con el nuevo tipo dinámico es como sigue:

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

Referencias:

  1. Usando clases de Python Compilado de .NET / CSharp IP 2.6
  2. compilación estática de guiones IronPython

He buscado alta y baja y me temo que no parece ser mucho más información relativa a este. Estoy bastante seguro de que nadie ha ideado una manera de hacer esto de la manera limpia que le gustaría.

La razón principal por la que creo que esto es un problema es que con el fin de ver el tipo PokerCard en su aplicación C # que tendría que compilar el código Python a IL. No creo que haya ninguna compiladores Python->IL por ahí.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top