构建Python脚本,并调用从C#方法 [英] Build Python scripts and call methods from C#
问题描述
有什么办法使这种情况下工作?
Is there any way to make this scenario work?
有是一个Python脚本。
There is a Python script. It is built into a DLL by running this script with IronPython:
import clr
clr.CompileModules("CompiledScript.dll", "script.py")
我们的目标是调用从C#代码这个DLL的方法。 .net反射显示有在DLL中一个类 - DLRCashedCode
我们感兴趣的方法是这一类的私有静态方法
The goal is to call this DLL's methods from C# code. .NET Reflector shows there is one class in the DLL - DLRCashedCode
and the methods we are interested in are private static methods of this class.
例如,有一个在脚本中的功能:
For example, there is a function in the script:
def scriptMethod(self, text):
...
其在DLL中表示为:
private static object scriptMethod(Closure closure1, PythonFunction $function, object self, object text)
{
...
}
关闭
和 PythonFunction
是IronPython的类(从Microsoft.Scripting.dll和IronPython.dll)。
Closure
and PythonFunction
are IronPython classes (from Microsoft.Scripting.dll and IronPython.dll).
到目前为止好。是否有可能这种方法用C#代码调用?使用类似
So far so good. Is it possible this method to be called by C# code? The idea of using reflection like
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);
似乎因为设置方法的参数的困难。如果他们(任何如何)正确初始化,可能我们预期该方法工作的顺利开展?
seems harder because of setting the method's parameters. If they are (any how) initialized correctly, could we expect the method to work smoothly?
有没有更好的方法来调用从C#这样的方法呢?由于各种不同的原因,我们希望有脚本建成一个.NET程序集,而不是调用脚本本身。
Is there a better way to call this methods from C#? For various different reasons we prefer to have the script built as a .NET assembly and not to call the script itself.
推荐答案
排序的。不能从C#代码直接访问Python的方法。除非你用C#4.0玩和动态关键字或你是非常,非常特别的)。但是,您可以编译的IronPython类为DLL,然后使用IronPython的在C#托管访问方法(这是IronPython的2.6和.NET 2.0)。
Sort of. You cannot access the Python methods directly from C# code. Unless you are playing with C# 4.0 and the dynamic keyword or you are very, very special ;). However, you can compile an IronPython class to a DLL and then use IronPython hosting in C# to access the methods (this is for IronPython 2.6 and .NET 2.0).
创建C#程序是这样的:
Create a C# program like this:
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类象这样的:
Make a trivial Python class like this:
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#程序的生命并运行它。你应该得到这样的结果:
Compile it (I use SharpDevelop) but the clr.CompileModules
method should also work. Then shove the compiled MyClass.dll
into the directory where the compiled C# program lives and run it. You should get this as the result:
Hello World!
I'm in a compiled class (I hope)
in some method
in some method
True
False
Press any key to continue . . .
这整合了消除了创建和编译一个小的Python存根,也是杰夫的更直接的解决方案演示如何创建访问在Python类中的方法C#函数调用。
This incorporates Jeff's more direct solution that eliminates having to create and compile a small Python 'stub' and also shows how you can create C# function calls that access the methods in the Python class.
这篇关于构建Python脚本,并调用从C#方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!