2025年3月26日 星期三 甲辰(龙)年 月廿五 设为首页 加入收藏
rss
您当前的位置:首页 > 计算机 > 编程开发 > Python

Python 和C#的交互

时间:12-01来源:作者:点击数:24

IronPython是一个.NET平台上的Python实现,包括了完整的编译器、执行引擎与运行时支持,能够与.NET已有的库无缝整合到一起。

IronPython已经很好的集成到了.NET framework中,所以Ironpython和C#的交互也就变得很简单了。下面就通过一些简单的例子来看看IronPython和C#之间的交互。

环境设置

工欲善其事,必先利其器,所以在开始IronPython的开发之前,我们先找到一个方便的开发环境。

PTVS(Python tools for Visual Studio)是一个免费开源的VisualStudio的插件,支持 VisualStudio 2010/2012/2013,安装好这个插件之后,我们就可以直接通过VS进行IronPython的开发了。

下面一个截图显示了我们可以新建的项目模板:

IronPython调用C#

首先我们看下如何在IronPython中使用C#的简单例子。

使用标准.NET库

在.NET中,有很多标准库,在IronPython中,就可以使用import来引入这些标准库来直接使用。看一个简单的例子,我们使用.NET中的String和DateTime

  • 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!")

代码输出如下,可以看到在IronPython代码中,可以通过String的Format方法进行字符串格式化的输出。

引入.NET库

在.NET开发中,会经常通过References来引用一些.NET库,当然在IronPython项目中,也可以引用并使用.NET库。

例如,现在我们有一个Calc的计算类型,里面有一个Add和Sub方法。通过这个类型,生成了一个CalcLib.dll。

  • 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引用:

  • 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!")

代码输出如下,当引用了CalcLib.dll之后,我们就可以使用Calc类型创建实例,并且使用实例的C#方法。

IronPython创建WPF应用

在IronPython项目中,也可以引入WPF相关的.NET库,这样就可以方便的创建图形界面应用。

安装过PTVS之后,里面有个"IronPython WPF Application"的模板,通过这个模板,可以直接创建WPF应用。

在新建的项目中,VS会帮我们自动引用WPF相关的库,同时会有一个.py和.xaml文件。

下面看一个简单的例子,通过IrpnPython实现的一个简单计算器,界面的代码如下:

  • <Grid>
  • <Grid.RowDefinitions>
  • <RowDefinition></RowDefinition>
  • <RowDefinition></RowDefinition>
  • <RowDefinition></RowDefinition>
  • <RowDefinition></RowDefinition>
  • <RowDefinition></RowDefinition>
  • <RowDefinition></RowDefinition>
  • </Grid.RowDefinitions>
  • <Grid.ColumnDefinitions>
  • <ColumnDefinition></ColumnDefinition>
  • <ColumnDefinition></ColumnDefinition>
  • <ColumnDefinition></ColumnDefinition>
  • <ColumnDefinition></ColumnDefinition>
  • </Grid.ColumnDefinitions>
  • <TextBlock Name="InputTb" Grid.Row="0" Grid.ColumnSpan="4"/>
  • <TextBlock Name="ResultTb" Grid.Row="1" Grid.ColumnSpan="3"/>
  • <Button Content="1" Grid.Row="2" Grid.Column="0" Click="Input_Button_Click"/>
  • <Button Content="2" Grid.Row="2" Grid.Column="1" Click="Input_Button_Click"/>
  • <Button Content="3" Grid.Row="2" Grid.Column="2" Click="Input_Button_Click"/>
  • <Button Content="4" Grid.Row="3" Grid.Column="0" Click="Input_Button_Click"/>
  • <Button Content="5" Grid.Row="3" Grid.Column="1" Click="Input_Button_Click"/>
  • <Button Content="6" Grid.Row="3" Grid.Column="2" Click="Input_Button_Click"/>
  • <Button Content="7" Grid.Row="4" Grid.Column="0" Click="Input_Button_Click"/>
  • <Button Content="8" Grid.Row="4" Grid.Column="1" Click="Input_Button_Click"/>
  • <Button Content="9" Grid.Row="4" Grid.Column="2" Click="Input_Button_Click"/>
  • <Button Content="0" Grid.Row="5" Grid.Column="0" Click="Input_Button_Click"/>
  • <Button Content="+" Grid.Row="2" Grid.Column="3" Click="Input_Button_Click"/>
  • <Button Content="-" Grid.Row="3" Grid.Column="3" Click="Input_Button_Click"/>
  • <Button Content="*" Grid.Row="4" Grid.Column="3" Click="Input_Button_Click"/>
  • <Button Content="/" Grid.Row="5" Grid.Column="3" Click="Input_Button_Click"/>
  • <Button Content="." Grid.Row="5" Grid.Column="1" Click="Input_Button_Click"/>
  • <Button Content="C" Grid.Row="5" Grid.Column="2" Click="Clear_Button_Click"/>
  • <Button Content="=" Grid.Row="1" Grid.Column="3" Click="Calc_Button_Click"/>
  • </Grid>

对应的IronPython代码如下:

  • from __future__ import division
  • import traceback
  • import wpf
  • from System.Windows import Application, Window, MessageBox
  • class MyWindow(Window):
  • def __init__(self):
  • wpf.LoadComponent(self, 'IronPythonWPF.xaml')
  • def Calc_Button_Click(self, sender, e):
  • try:
  • result = eval(self.InputTb.Text)
  • self.ResultTb.Text = str(result)
  • except Exception, e:
  • tracelog = traceback.format_exc()
  • MessageBox.Show(str(e))
  • pass
  • def Clear_Button_Click(self, sender, e):
  • self.InputTb.Text = ""
  • self.ResultTb.Text = ""
  • pass
  • def Input_Button_Click(self, sender, e):
  • self.InputTb.Text += sender.Content
  • pass
  • if __name__ == '__main__':
  • Application().Run(MyWindow())

代码运行效果如下:

C#调用IronPython

前面介绍了在IronPython中如何使用.NET库,下面看看通过C#代码执行IronPython脚本。在.NET framework中,包含了IronPython的编译器和执行引擎,所以我们可以通过C#代码创建一个引擎实例,然后执行脚本。

先看看我们需要使用的类型:

  • ScriptEngine: 动态语言(IronPython)执行类,可于解析和执行动态语言代码。
  • ScriptScope:构建一个执行上下文,其中保存了环境及全局变量;宿主(Host)可以通过创建不同的 ScriptScope 来提供多个数据隔离的执行上下文。
  • ScriptSource:操控动态语言代码的类型,可以编译(Compile)、运行(Execute)代码。

现在我们有一个简单的打印当前时间的IronPython脚本:

  • import datetime
  • print "current datetiem is:", datetime.datetime.now()

然后就可以使用下面的方式执行脚本:

  • static void Main(string[] args)
  • {
  • try
  • {
  • ScriptEngine engine = Python.CreateEngine();
  • ScriptScope scope = engine.CreateScope();
  • ScriptSource script = engine.CreateScriptSourceFromFile(@"Script.py");
  • var result = script.Execute(scope);
  • }
  • catch (Exception e)
  • {
  • Console.WriteLine(e.Message);
  • }
  • Console.Read();
  • }

给IronPython传递参数

在ScriptScope类型中,有一个SetVariable方法,我们可以通过这个方法给脚本传递参数。

public void SetVariable(string name, object value)

这样,我们就可以把一个C#实例传递给IronPython,然后脚本就可以使用C#实例的成员。看一个例子:

  • 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 = "Wilber", Age = 28 };
  • scope.SetVariable("stuObj", stu);
  • ScriptSource script = engine.CreateScriptSourceFromFile(@"PrintStuInfo.py");
  • var result = script.Execute(scope);
  • }
  • catch (Exception e)
  • {
  • Console.WriteLine(e.Message);
  • }
  • Console.Read();
  • }
  • }

在这个例子中,C#代码中创建了一个Student类型的实例,并把这个实例传递给了PrintStuInfo.py脚本。

  • print "Student name:", stuObj.Name
  • print "Student age:", stuObj.Age
  • print stuObj.ToString()

通过输出可以看到,IronPython脚本可以方便的访问C#实例的成员。

总结

本篇文章通过一些例子演示了IronPython与C#的交互,感觉有几个例子还是很有意思的。

有时候使用C#调用IronPython可以使程序变得更加灵活,通过一个C#类型提供一组封装好的操作,每次构建类型实例然后传递给脚本;这样,用户就可以编写IronPython脚本,然后使用C#类型中提供的操作方法,从而实现不同的自定义操作。

方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门