c# - 从 C# 构建 Python 脚本和调用方法

标签 c# python ironpython

有什么方法可以让这个场景发挥作用吗?

有一个 Python 脚本。通过使用 IronPython 运行此脚本将其构建到 DLL 中:

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

目标是从 C# 代码调用此 DLL 的方法。 .NET Reflector显示 DLL 中有一个类 - DLRCashedCode,我们感兴趣的方法是该类的私有(private)静态方法。

比如脚本中有一个函数:

def scriptMethod(self, text):
...

它在DLL中的表示是:

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

ClosurePythonFunction 是 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 程序集,而不是调用脚本本身。

最佳答案

有点。您不能直接从 C# 代码访问 Python 方法。除非您正在使用 C# 4.0 和动态关键字,否则您非常非常特别;)。但是,您可以将 IronPython 类编译为 DLL,然后使用 C# 中的 IronPython 托管来访问这些方法(这适用于 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 . . .

这结合了 Jeff 更直接的解决方案,无需创建和编译小型 Python“ stub ”,还展示了如何创建 C# 函数调用来访问 Python 类中的方法。

关于c# - 从 C# 构建 Python 脚本和调用方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2139202/

相关文章:

类似于 C++ 中的 C# 方法指针

c# - 无法加载 7-zip 库或内部 COM 错误。库无效

c# - 报告框架背后的基本原理

python - 如何在 OpenERP 上创建动态 View

python - 在 setup.py 中构建之前运行 .py 文件

c# - 如何在 Visual Studio 2015 中更改语言版本

python - 是否有正则表达式模式可以返回相同字符的所有完全匹配?

.net - Microsoft.Scripting.Core.dll 在哪里?

python - 在 IronPython 中使用函数工具

exception - 从 IronPython 异常获取回溯信息