C#からIronPythonを呼び出し、Pythonのコードを実行する

C#からIronPythonを呼び出して、Pythonのコードを実行してみようと思います。

Visual Studio 2010 ExpressとIronPythonのインストールはこちら。
Visual Studio 2010 Express をインストールする
Windows 2008 R2 にIronPythonをインストールする

試した環境は、Visual Studio 2010 Express(C# 4.0)とIronPython 2.6.1です。


参照設定の追加



IronPythonを呼び出すため、参照設定の追加を行います。

ソリューションエクスプローラーの「参照設定」を右クリックして
「参照の追加」を選択します。

03_001_20100509200416.png


「参照」タブを選択して、IronPythonをインストールしたパスを開き、
以下2つのDLLを追加します。


IronPython.dll
Microsoft.Scripting.dll



03_002_20100509200416.png





C#のプログラムの書き方




using IronPython.Hosting;
using Microsoft.Scripting.Hosting;



この2つのusingをソースに追加します。

基本的な流れは、
1.スクリプト実行用のScriptEngineを作成する。
2.スクリプトに値を渡すためのScriptScopeを作成する。
3.スクリプトのソースを指定するためのScriptSourceを作成する。
4.ScriptSource.Executeでスクリプト実行。

という感じでしょうか。

Pythonのスクリプトに"Symfo"という文字列を渡して、返信の文字列を
受け取るプログラムを作成してみました。


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using IronPython.Hosting;
using Microsoft.Scripting.Hosting;

namespace Sample
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            //Pythonスクリプト実行エンジン
            ScriptEngine pse = Python.CreateEngine();

            //実行エンジンに渡す値を設定する
            ScriptScope scope = pse.CreateScope();

            //"Csharp_value"という変数名で、"Symfo"という値を渡す
            scope.SetVariable("Csharp_value", "Symfo");

            //Pythonのソースを指定
            ScriptSource source = pse.CreateScriptSourceFromFile(@"C:\sample.py");

            //C:\sample.pyにおいたソースを実行する
            source.Execute(scope);

            //実行した結果を取得
            var python_result1 = scope.GetVariable<string>("python_result");

            MessageBox.Show(python_result1);
        }
    }
}







Pythonのプログラムの書き方



上記のC#プログラムを実行すると、"Csharp_value"という変数に
値が設定された状態で、Pythonのスクリプトが実行されます。

また、C#側ではスクリプト実行後"python_result"という変数に
値が設定されることを期待しています。

これらを踏まえ、以下のソースをC:\sample.pyに保存しておきます。


# Csharp_valueという変数はC#側から渡ってくる
name = Csharp_value

#python_resultという変数につめて、C#に値を返却
python_result = "Hello " + name



C#から渡された変数に"Hello "という文字列を連結して、
呼び出し元に返します。



準備ができたらプログラムを実行してみます。
ちゃんと、こんなメッセージボックスが表示されるはずです。

03_003_20100509200416.png





文字列をPythonのスクリプトとして実行する



画面上にテキストボックスを用意し、Pythonのコードを入力。
入力されたスクリプトを実行するプログラムを作成してみます。

C#側の変更箇所は、CreateScriptSourceFromFileとしているところを
CreateScriptSourceFromStringに変更し、ファイルパスではなく
スクリプト全体の文字列を渡すだけです。

scriptTextというテキストボックスを画面に貼り付け、中に入力した
文字列をCreateScriptSourceFromStringの引数に取るように変更しました。


//Pythonのソースを指定
//ScriptSource source = pse.CreateScriptSourceFromFile(@"C:\sample.py");
//Pythonのソース文字列を設定
ScriptSource source = pse.CreateScriptSourceFromString(scriptText.Text);




実行し、テキストの中身にsample.pyと同様の内容を記載します。

03_004_20100509200416.png


実行してみると、ちゃんとテキストボックスの中身の
スクリプトが実行されていることがわかると思います。

03_005_20100509200416.png





画面上のデータを触る



次は画面上のデータを触ってみます。
サンプルとして、ボタンの名前を取得し、最後に「変更」という
文字列を加えてみます。

ボタンのオブジェクトをそのまま渡そうと思ったのですが、
privateで宣言されているので、そのままではスクリプト側で
さわれません。

指定された名称のオブジェクトを取得するメソッドを作成し、
スクリプトで触れるようにしておきます。


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using IronPython.Hosting;
using Microsoft.Scripting.Hosting;

namespace Sample
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            //Pythonスクリプト実行エンジン
            ScriptEngine pse = Python.CreateEngine();

            //実行エンジンに渡す値を設定する
            ScriptScope scope = pse.CreateScope();

            //"Csharp_value"という変数名で、自分自身を渡す
            scope.SetVariable("Csharp_value", this);

            //Pythonのソース文字列を設定
            ScriptSource source = pse.CreateScriptSourceFromString(scriptText.Text);

            //ソースを実行する
            source.Execute(scope);
        }

        //指定された名称のオブジェクトを返す
        public object getParts(string name)
        {
            foreach (Control c in this.Controls)
            {
                if (c.Name == name)
                {
                    return c;
                }
            }

            return null;
        }
    }
}





テキストボックスに貼り付ける内容は以下の通り。



# 実行ボタンオブジェクトを取得
button = Csharp_value.getParts('button1')

#表示している文字列を取得
name = button.Text

#表示しているボタンの文字列を変更
button.Text = name + '変更'




初期状態ではこうですが、

03_006_20100509200416.png


実行してみると、ボタンの名称が変更されることがわかると思います。

03_007_20100509200423.png



参考URL



以下のサイトを参考にさせていただきました。
C#とIronPythonで変化に強いWindowsアプリケーションを作る
[C#][IronPython]C# - IronPython の連携





関連記事

コメント

非公開コメント

プロフィール

Author:symfo
blog形式だと探しにくいので、まとめサイト作成中です。
Symfoware まとめ

PR




検索フォーム

月別アーカイブ