web-dev-qa-db-ja.com

C#でpythonクラスをインスタンス化する

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#でインスタンス化するには、何をする必要がありますか?

44

IronPythonクラスはnot。NETクラスです。これらは、PythonメタクラスであるIronPython.Runtime.Types.PythonTypeのインスタンスです。これは、Pythonクラスが動的であり、メソッドの追加と削除をサポートしているためです。ランタイム、.NETクラスではできないこと。

C#でPythonクラスを使用するには、ObjectOperationsクラスを使用する必要があります。このクラスを使用すると、言語のセマンティクスでpythonタイプとインスタンスを操作できます。たとえば、必要に応じてマジックメソッドを使用し、整数をlongに自動昇格します。ソースを確認するか、リフレクターを使用することで、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では、new動的型を使用してこれをはるかに簡単にしました。

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

NuGetサポートを備えたVisualStudio 2010以降を使用している場合は、これを実行するだけで、適切なライブラリをダウンロードして参照できます。

Install-Package IronPython
55
m-sharp

.Net 4.0がリリースされ、動的タイプになっているので、この例を更新する必要があります。 m-sharpの元の回答と同じpythonファイルを使用する:

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

.Net4.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への参照を追加する必要があります。

ご覧のとおり、ソースファイルの初期設定と作成は同じです。

ただし、ソースが正常に実行されると、新しい「dynamic」キーワードのおかげで、python関数の操作がはるかに簡単になります。

31
CleverPatrick

.pyファイルのIronPythonソースコードではなく、コンパイルされたIronPythonクラス(dll)用にCleverHumanによって提供された上記の例を更新しています。

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