Создавать скрипты Python и вызывать методы из C # - PullRequest
10 голосов
/ 26 января 2010

Есть ли способ заставить этот сценарий работать?

Существует скрипт Python. Он встроен в DLL путем запуска этого сценария с IronPython:

import clr
clr.CompileModules("CompiledScript.dll", "script.py")

Цель - вызвать методы этой DLL из кода C #. .NET Reflector показывает, что в DLL есть один класс - DLRCashedCode, а интересующие нас методы являются частными статическими методами этого класса.

Например, в скрипте есть функция:

def scriptMethod(self, text):
...

Его представление в DLL:

private static object scriptMethod(Closure closure1, PythonFunction $function, object self, object text)
{
...
}

Closure и PythonFunction являются классами IronPython (от Microsoft.Scripting.dll и IronPython.dll).

Пока все хорошо. Возможно ли, чтобы этот метод вызывался кодом C #? Идея использования отражения вроде

Type t = typeof(DLRCachedCode);

string methodName = "scriptMethod";
MethodInfo method = t.GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Static);

object[] parameters = new object[] { "param1", "param2" };  // the "params problem"
method.Invoke(null, parameters);

кажется сложнее из-за установки параметров метода. Если они (каким-либо образом) инициализированы правильно, можем ли мы ожидать, что метод будет работать гладко?

Есть ли лучший способ вызывать эти методы из C #? По разным причинам мы предпочитаем, чтобы скрипт был построен как сборка .NET, а не вызывал сам скрипт.

Ответы [ 2 ]

8 голосов
/ 26 января 2010

Вроде. Вы не можете получить доступ к методам Python непосредственно из кода C #. Если вы не играете с C # 4.0 и динамическим ключевым словом или вы очень, очень особенный;). Однако вы можете скомпилировать класс IronPython в DLL, а затем использовать хостинг IronPython в C # для доступа к методам (это для IronPython 2.6 и .NET 2.0).

Создайте программу на C # следующим образом:

using System;
using System.IO;
using System.Reflection;
using IronPython.Hosting;
using Microsoft.Scripting.Hosting;
// we get access to Action and Func on .Net 2.0 through Microsoft.Scripting.Utils
using Microsoft.Scripting.Utils;


namespace TestCallIronPython
{
    class Program
    {
        public static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
            ScriptEngine pyEngine = Python.CreateEngine();

            Assembly myclass = Assembly.LoadFile(Path.GetFullPath("MyClass.dll"));
            pyEngine.Runtime.LoadAssembly(myclass);
            ScriptScope pyScope = pyEngine.Runtime.ImportModule("MyClass");

            // Get the Python Class
            object MyClass = pyEngine.Operations.Invoke(pyScope.GetVariable("MyClass"));

            // Invoke a method of the class
            pyEngine.Operations.InvokeMember(MyClass, "somemethod", new object[0]);

            // create a callable function to 'somemethod'
            Action SomeMethod2 = pyEngine.Operations.GetMember<Action>(MyClass, "somemethod");
            SomeMethod2();

            // create a callable function to 'isodd'
            Func<int, bool> IsOdd = pyEngine.Operations.GetMember<Func<int, bool>>(MyClass, "isodd");
            Console.WriteLine(IsOdd(1).ToString());
            Console.WriteLine(IsOdd(2).ToString());

            Console.Write("Press any key to continue . . . ");
            Console.ReadKey(true);
        }
    }
}

Создайте тривиальный класс Python следующим образом:

class MyClass:
    def __init__(self):
        print "I'm in a compiled class (I hope)"

    def somemethod(self):
        print "in some method"

    def isodd(self, n):
        return 1 == n % 2

Скомпилируйте его (я использую SharpDevelop ), но метод clr.CompileModules также должен работать. Затем поместите скомпилированный файл MyClass.dll в каталог, где находится скомпилированная программа C #, и запустите его. Вы должны получить это в результате:

Hello World!
I'm in a compiled class (I hope)
in some method
in some method
True
False
Press any key to continue . . .

Это включает более прямое решение Джеффа, которое устраняет необходимость создавать и компилировать небольшую заглушку Python, а также показывает, как можно создавать вызовы функций C #, которые обращаются к методам в классе Python.

6 голосов
/ 26 января 2010

clr.CompileModules - это просто оптимизация времени загрузки - он не делает скрипты напрямую доступными для статического языка, такого как C #. Вам нужно будет разместить среду выполнения IronPython, а затем вы можете загрузить DLL в среду выполнения и использовать хостинговые интерфейсы IronPython для доступа к ней.

...