Python是一种解释型、面向对象、动态数据类型的高级程序设计语言。是一门动态解释型语言,也是一门胶水语言,很方面调用其它编程语言的程序。比如:C/C++,C#等等。这里介绍一下Python和C#的互相调用。
IronPython 是一种在 .NET 及 Mono上的 Python 实现,由微软的 Jim Hugunin 所发起,是一个开源的项目,基于微软的 DLR 引擎。
IronPython是流行的程序设计语言Python通向.NET framework的一个端口。微软公司对于.NET framework的IronPython和动态语言非常关注。微软公司已经在各种项目中提供了对IronPython的支持。
IronPython已经很好的集成到了.NET framework中,Python语言中的字符串对应于.NET的字符串对象,并且Python语言中对应的方法,在IronPython中也都提供了。其它数据类型也是一样。
IronPython-2.7.8经过了一年的制作,终于发布了。这将是第一个支持 .NET Core 的版本。一些详情的更新内容,请点击这里查看。
下载地址:
-
IronPython-2.7.8.msi
-
IronPython.2.7.8.zip
-
IronPython.StdLib.2.7.8.zip
-
Source code (zip)
-
Source code (tar.gz)
1.IronPython 调用 .NET 标准库
在这里我们使用VS2019进行开发,新建一个IronPython项目:
如上图创建一个IronPython 控制台程序,命名为IronPythonTest 。在.NET中,有很多标准库,在IronPython中,就可以使用import来引入这些标准库来直接使用。看一个简单的例子,我们使用.NET中的String和DateTime 。
上面写一个简单的Python脚本,通过 IronPython2.7 .exe 解释器执行。如下图:
2.IronPython调用 .NET 自定义库(DLL)
在.NET开发中,会经常通过References来引用一些.NET库,当然在IronPython项目中,也可以引用并使用.NET库。
例如,现在我们有一个Calc的计算类型,里面有一个Add和Sub方法。通过这个类型,生成了一个CalcLib.dll。R
namespace CalcLib
{
public class Calc
{
public int Add(int a, int b)
{
return a + b;
}
public int Sub(int a, int b)
{
return a - b;
}
}
}
下面看看如何在IronPython项目中使用这个dll,在IronPython中,可以使用"clr"模块来添加.NET引用,将CalLib.dll编译好,放在IronPython 工程目录和执行脚本同一目录下:
python脚本如下:
import clr
clr.AddReference('CalcLib')
#clr.AddReferenceToFile('CalcLib.dll')
from CalcLib import Calc
print dir(Calc)
calcObj = Calc()
print "result of 3+4 is:", calcObj.Add(3,4)
print "result of 10+2 is:", calcObj.Sub(10,2)
raw_input("press Enter to exit!")
IronPython解释执行:
3.C#调用IronPython脚本
在.NET framework中,包含了IronPython的编译器和执行引擎,所以我们可以通过C#代码创建一个引擎实例,然后执行脚本。
先看看我们需要使用的类型:
- ScriptEngine: 动态语言(IronPython)执行类,可于解析和执行动态语言代码。
- ScriptScope:构建一个执行上下文,其中保存了环境及全局变量;宿主(Host)可以通过创建不同的 ScriptScope 来提供多个数据隔离的执行上下文。
- ScriptSource:操控动态语言代码的类型,可以编译(Compile)、运行(Execute)代码。
现在我们有一个简单的打印当前时间的IronPython脚本:
from System import DateTime, String
formatStr = String.Format("{0} {1}", "Hello World! The current date and time is ", DateTime.Now)
print formatStr
#print dir(String)
raw_input("press Enter to exit!")
先进一个C#控制台项目,引入IronPython库:
using IronPython.Hosting;
using Microsoft.Scripting.Hosting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Test
{
class Program
{
static void Main(string[] args)
{
try
{
ScriptEngine engine = Python.CreateEngine();
ScriptScope scope = engine.CreateScope();
ScriptSource script = engine.CreateScriptSourceFromFile(@"IronPythonTest.py");
var result = script.Execute(scope);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
}
}
将控制台exe程序输出到IronPython脚本同一目录:
点击运行,从C#程序调用了IronPython脚本(这里Exe必须和IronPython在同一目录下,才可以成功调用)
4.从C#给IronPython传递参数
在ScriptScope类型中,有一个SetVariable方法,我们可以通过这个方法给脚本传递参数。
public void SetVariable(string name, object value)
这样,我们就可以把一个C#实例传递给IronPython,然后脚本就可以使用C#实例的成员。看一个例子:
using IronPython.Hosting;
using Microsoft.Scripting.Hosting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Test
{
public class Student
{
public int Age { get; set; }
public string Name { get; set; }
public override string ToString()
{
return string.Format("{0} is {1} years old", this.Name, this.Age);
}
}
class Program
{
static void Main(string[] args)
{
try
{
ScriptEngine engine = Python.CreateEngine();
ScriptScope scope = engine.CreateScope();
Student stu = new Student { Name = "deokoo", Age = 28 };
scope.SetVariable("stuObj",stu);
ScriptSource script = engine.CreateScriptSourceFromFile(@"IronPythonTest.py");
var result = script.Execute(scope);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
}
}
在这个例子中,C#代码中创建了一个Student类型的实例,并把这个实例传递给了PrintStuInfo.py脚本:
from System import DateTime, String
formatStr = String.Format("{0} {1}", "Hello World! The current date and time is ", DateTime.Now)
print formatStr
#print dir(String)
print "Student name:", stuObj.Name
print "Student age:", stuObj.Age
print stuObj.ToString()
raw_input("press Enter to exit!")
通过输出可以看到,IronPython脚本可以方便的访问C#实例的成员:
总结
本篇文章通过一些例子演示了IronPython与C#的交互,感觉有几个例子还是很有意思的。
有时候使用C#调用IronPython可以使程序变得更加灵活,通过一个C#类型提供一组封装好的操作,每次构建类型实例然后传递给脚本;这样,用户就可以编写IronPython脚本,然后使用C#类型中提供的操作方法,从而实现不同的自定义操作。