Domanda

Ho scritto una classe in python che voglio avvolgere in un .net assembly via IronPython e creare un'istanza in un'applicazione C#.Ho migrato la classe di IronPython, creato una libreria di montaggio e di riferimento.Ora, come faccio effettivamente ottenere un'istanza di quella classe?

La classe sembra (parzialmente) come questo:

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

    def __init__(self, cardName):

Il test stub ho scritto in 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();
        }
    }
}

Cosa devo fare per creare un'istanza di questa classe in C#?

È stato utile?

Soluzione

IronPython classi sono non .NET classi.Sono istanze di IronPython.Runtime.Tipi di.PythonType che è il Python metaclass.Questo perché le classi Python sono dinamici e supporto per l'aggiunta e la rimozione di metodi in fase di runtime, le cose non si può fare con .NET classi.

Per utilizzare le classi Python in C# è necessario utilizzare il ObjectOperations classe.Questa classe permette di operare su python tipi e istanze della semantica del linguaggio stesso.ad es.utilizza la magia metodi quando appropriato, auto-promuove interi lunghi etc.Si può scoprire di più su ObjectOperations guardando il sorgente o usando il riflettore.

Qui è un esempio.Calculator.py contiene una semplice classe:

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

Si può utilizzare dal tuo pre .NET 4.0 C# codice come questo:

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)

Sarà necessario fare riferimento all'assembly IronPython.dll, Microsoft.Scripting e Microsoft.Scripting.Core.

C# 4 fatto questo molto più facile con l' nuovo di tipo dinamico.

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

Se si utilizza Visual Studio 2010 o versioni successive con NuGet di supporto semplicemente eseguire per il download di riferimento e le librerie appropriate.

Install-Package IronPython

Altri suggerimenti

Ora che .Net 4.0 è rilasciato e ha il tipo dinamico, questo esempio dovrebbe essere aggiornato. Utilizzando lo stesso file Python come nella risposta originale m-sharp di:

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

Ecco come si potrebbe chiamare utilizzando .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);          

Anche in questo caso, è necessario aggiungere i riferimenti a IronPython.dll e Microsoft.Scripting.

Come si può vedere, l'impostazione iniziale e la creazione del file di origine è la stessa.

Ma una volta che la sorgente è successo eseguito, lavorando con le funzioni Python è molto più facile grazie alla nuova parola chiave "dinamico".

sto aggiornando l'esempio precedente fornito da Clever umano per le classi compilate IronPython (DLL) al posto del codice sorgente IronPython in un file .py.

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

codice C # 4.0 con il nuovo tipo di dinamica è la seguente:

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

References:

  1. Utilizzando classi Python compilato da NET / CSharp IP 2.6
  2. Compilation Static di script IronPython

Ho cercato di alta e bassa e temo che non sembra essere molto informazioni relative a questo. Sono praticamente certo che nessuno ha ideato un modo per fare questo in modo pulito che si desidera.

Il motivo principale credo che questo sia un problema è che, al fine di vedere il tipo PokerCard in C # applicazione si dovrà compilare il codice Python a IL. Non credo che ci siano compilatori Python->IL là fuori.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top