歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> IronPython和C#交互

IronPython和C#交互

日期:2017/3/1 9:27:43   编辑:Linux編程

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#類型中提供的操作方法,從而實現不同的自定義操��。

Copyright © Linux教程網 All Rights Reserved