C#のクラスをIronPython側で使うのは、非常に簡単だ。
(CPythonだと、結構、面倒だったような...)
---- コード(C#側) ----
using System;
using IronPython;
using IronPython.Hosting;
using Microsoft.Scripting;
using Microsoft.Scripting.Hosting;
namespace python_test001
{
class Program
{
public static void Main(string[] args)
{
try
{
ScriptEngine engine = Python.CreateEngine();
ScriptScope scope = engine.CreateScope();
// C#と変数のやり取りをするPythonのファイルを設定
ScriptSource source =
engine.CreateScriptSourceFromFile("test.py");
TestNumber test = new TestNumber();
// Python側の変数をTestDataとする
scope.SetVariable("num", test);
// 実行
source.Execute(scope);
int i = test.Number;
// 実行後のPython側の変数値を取得
// 結果を出力 ==> 15
System.Console.WriteLine(test.Number);
}
catch (Exception ex)
{
System.Console.WriteLine("Error:"
+ ex.Message.ToString());
}
}
}
}
// Python側に渡すクラス
class TestNumber {
int number = 0;
public void Plus(int i) {
number += i;
}
public int GetNumber() {
return this.number;
}
public void SetNumber(int i) {
this.number = i;
}
public int Number {
get {
return this.number;
}
set {
this.number = value;
}
}
}
---- コード(Python側) ----
num.Number = 10
print 'py_number:', num.GetNumber()
#プロパティのgetがprotectedメンバだとかでエラー
#print 'py_number:', num.Number
num.Plus(5)
================================
■参考
貧脚レーサーのサボり日記 - C#でIronPython2.0をホスティングする
Embedding the Dynamic Language Runtime
The IronPython Calculator and the Evaluator
プログラミングなど
2009年5月22日金曜日
2009年5月20日水曜日
boost spirit ファイル解析エラー時情報
boost spirit でファイルを解析したときのエラー時情報出力の仕方について簡単な例があまりないようなので、調べたことを記述します。
下記のコードでは、1行にINT, REAL というキーワードと値の組み合わせを含んだファイルを読み込み、文法にエラーが存在した場合には、該当個所を出力します。
(正常な文法のファイルの例)
INT 100
REAL 10.0
INT 5
REAL 7.5
---- コード ----
#include <boost/spirit.hpp>
#include <iostream>
#include <iomanip>
#include <string>
// エラー出力のためのパーサ
struct error_parser {
typedef boost::spirit::nil_t result_t;
std::string msg_;
error_parser(const char* msg) : msg_(msg) {}
template <typename ScannerT>
int operator()(const ScannerT& scan,
result_t& result) const {
if (!scan.at_end()) { // 入力が最後でない場合
// スキャナの first には、ポジションイテレータが
// 保持される
boost::spirit::file_position fpos
= scan.first.get_position();
std::cout
<< "Error: " << fpos.file << " "
<< "Line(" << fpos.line << ") "
<< "Column(" << fpos.column << ") "
<< msg_
<< std::endl;
}
return (-1);
}
};
typedef boost::spirit::functor_parser<error_parser> error_p;
error_p syntax_error_p("Syntax is wrong.");
error_p keyword_error_p("Invalid Keyword.");
error_p value_error_p("Invalid Value.");
// 文法定義
struct test_grammar : boost::spirit::grammar<test_grammar> {
template <typename ScannerT>
struct definition {
typedef boost::spirit::rule<ScannerT> rule_t;
rule_t top_, line_,
integer_statement_, real_statement_, other_statement_;
definition(const test_grammar& self) {
using namespace boost::spirit;
top_ =
+line_ | syntax_error_p;
line_ =
*blank_p >> (integer_statement_ |
real_statement_ |
other_statement_) >>
((*blank_p >> eol_p) |
((anychar_p - blank_p - eol_p) >> value_error_p) |
(+blank_p >> ((anychar_p - eol_p) >> syntax_error_p)));
// "INT (整数)"
integer_statement_ =
str_p("INT") >>
+blank_p >>
(int_p | (anychar_p >> value_error_p));
// "REAL (実数)"
real_statement_ =
(str_p("REAL") | keyword_error_p) >>
+blank_p >>
(real_p | (anychar_p >> value_error_p));
// "それ以外"
other_statement_ =
anychar_p >> syntax_error_p;
}
const rule_t& start() const { return top_; }
};
};
int main(int argc, char** argv) {
std::string file = "sample.txt";
// ファイルイテレータ
typedef boost::spirit::file_iterator<> file_iterator_t;
file_iterator_t file_first(file);
if (!file_first) {
std::cout << "cannot open file: " << file << std::endl;
return (1);
}
// ポジションイテレータ
typedef boost::spirit::position_iterator<file_iterator_t> position_iterator_t;
position_iterator_t position_first(file_first,
file_first.make_end(),
file);
position_iterator_t position_last;
boost::spirit::parse_info<position_iterator_t> info =
boost::spirit::parse(position_first,
position_last,
test_grammar());
std::cout << std::boolalpha << info.full << std::endl;
return (0);
}
================================
parse()関数の前に、ファイルイテレータ、位置情報イテレータを作成します。
ポジションイテレータは、 error_parser 内の operator()()関数内のscanで利用できます。
error_parserは、functor_parser<>によって、他の定義済パーサと同様にエラーパーサとして利用できるようにします。
definition()内にルールを記述する際、文法エラーの発生させたい個所に、エラーパーサを使用します。
尚、上記のコードでは、エラーの種類に応じて、出力メッセージを変更できるようにしています。
■参考
Spirit v1.6.0 - ファンクタパーサ
Spirit v1.6.0 - 詳細:スキャナ
boost ライブラリを使ってみる - エラー処理
下記のコードでは、1行にINT, REAL というキーワードと値の組み合わせを含んだファイルを読み込み、文法にエラーが存在した場合には、該当個所を出力します。
(正常な文法のファイルの例)
INT 100
REAL 10.0
INT 5
REAL 7.5
---- コード ----
#include <boost/spirit.hpp>
#include <iostream>
#include <iomanip>
#include <string>
// エラー出力のためのパーサ
struct error_parser {
typedef boost::spirit::nil_t result_t;
std::string msg_;
error_parser(const char* msg) : msg_(msg) {}
template <typename ScannerT>
int operator()(const ScannerT& scan,
result_t& result) const {
if (!scan.at_end()) { // 入力が最後でない場合
// スキャナの first には、ポジションイテレータが
// 保持される
boost::spirit::file_position fpos
= scan.first.get_position();
std::cout
<< "Error: " << fpos.file << " "
<< "Line(" << fpos.line << ") "
<< "Column(" << fpos.column << ") "
<< msg_
<< std::endl;
}
return (-1);
}
};
typedef boost::spirit::functor_parser<error_parser> error_p;
error_p syntax_error_p("Syntax is wrong.");
error_p keyword_error_p("Invalid Keyword.");
error_p value_error_p("Invalid Value.");
// 文法定義
struct test_grammar : boost::spirit::grammar<test_grammar> {
template <typename ScannerT>
struct definition {
typedef boost::spirit::rule<ScannerT> rule_t;
rule_t top_, line_,
integer_statement_, real_statement_, other_statement_;
definition(const test_grammar& self) {
using namespace boost::spirit;
top_ =
+line_ | syntax_error_p;
line_ =
*blank_p >> (integer_statement_ |
real_statement_ |
other_statement_) >>
((*blank_p >> eol_p) |
((anychar_p - blank_p - eol_p) >> value_error_p) |
(+blank_p >> ((anychar_p - eol_p) >> syntax_error_p)));
// "INT (整数)"
integer_statement_ =
str_p("INT") >>
+blank_p >>
(int_p | (anychar_p >> value_error_p));
// "REAL (実数)"
real_statement_ =
(str_p("REAL") | keyword_error_p) >>
+blank_p >>
(real_p | (anychar_p >> value_error_p));
// "それ以外"
other_statement_ =
anychar_p >> syntax_error_p;
}
const rule_t& start() const { return top_; }
};
};
int main(int argc, char** argv) {
std::string file = "sample.txt";
// ファイルイテレータ
typedef boost::spirit::file_iterator<> file_iterator_t;
file_iterator_t file_first(file);
if (!file_first) {
std::cout << "cannot open file: " << file << std::endl;
return (1);
}
// ポジションイテレータ
typedef boost::spirit::position_iterator<file_iterator_t> position_iterator_t;
position_iterator_t position_first(file_first,
file_first.make_end(),
file);
position_iterator_t position_last;
boost::spirit::parse_info<position_iterator_t> info =
boost::spirit::parse(position_first,
position_last,
test_grammar());
std::cout << std::boolalpha << info.full << std::endl;
return (0);
}
================================
parse()関数の前に、ファイルイテレータ、位置情報イテレータを作成します。
ポジションイテレータは、 error_parser 内の operator()()関数内のscanで利用できます。
error_parserは、functor_parser<>によって、他の定義済パーサと同様にエラーパーサとして利用できるようにします。
definition()内にルールを記述する際、文法エラーの発生させたい個所に、エラーパーサを使用します。
尚、上記のコードでは、エラーの種類に応じて、出力メッセージを変更できるようにしています。
■参考
Spirit v1.6.0 - ファンクタパーサ
Spirit v1.6.0 - 詳細:スキャナ
2009年5月17日日曜日
C# + Python embedding ファイルの変数のやりとり
Pythonファイルとのやりとりの例
■.NET Framework2.0 sp1
■IronPython 2.0
---- コード(Python側) ----
result = param1 + param2
---- コード(C#側) ----
using System;
using IronPython;
using IronPython.Hosting;
using Microsoft.Scripting;
using Microsoft.Scripting.Hosting;
...
public static void Main(string[] args)
{
try
{
ScriptEngine engine = Python.CreateEngine();
ScriptScope scope = engine.CreateScope();
// C#と変数のやり取りをするPythonのファイルを設定
ScriptSource source =
engine.CreateScriptSourceFromFile("test.py");
// Python側の変数に値を設定
scope.SetVariable("param1", 1);
scope.SetVariable("param2", 10);
// 実行
source.Execute(scope);
// 実行後のPython側の変数値を取得
// 結果を出力 ==> 1
object arg1 = scope.GetVariable("param1");
System.Console.WriteLine(arg1);
// 結果を出力 ==> 10
object arg2 = scope.GetVariable("param2");
System.Console.WriteLine(arg2);
// 結果を出力 ==> 11
object res = scope.GetVariable("result");
System.Console.WriteLine(res);
}
catch (Exception ex)
{
System.Console.WriteLine("Error:"
+ ex.Message.ToString());
}
}
================================
C#で Pythonファイル(test.py)内の変数の値の設定、取得を行います。
Python側では、あらかじめ変数に値が設定されている必要はありません。
C#で Python側の変数param1, param2 に、それぞれ値を設定し、Python側が実行された後、ython側の計算結果のresult変数をC#で取得しています。
■.NET Framework2.0 sp1
■IronPython 2.0
---- コード(Python側) ----
result = param1 + param2
---- コード(C#側) ----
using System;
using IronPython;
using IronPython.Hosting;
using Microsoft.Scripting;
using Microsoft.Scripting.Hosting;
...
public static void Main(string[] args)
{
try
{
ScriptEngine engine = Python.CreateEngine();
ScriptScope scope = engine.CreateScope();
// C#と変数のやり取りをするPythonのファイルを設定
ScriptSource source =
engine.CreateScriptSourceFromFile("test.py");
// Python側の変数に値を設定
scope.SetVariable("param1", 1);
scope.SetVariable("param2", 10);
// 実行
source.Execute(scope);
// 実行後のPython側の変数値を取得
// 結果を出力 ==> 1
object arg1 = scope.GetVariable("param1");
System.Console.WriteLine(arg1);
// 結果を出力 ==> 10
object arg2 = scope.GetVariable("param2");
System.Console.WriteLine(arg2);
// 結果を出力 ==> 11
object res = scope.GetVariable("result");
System.Console.WriteLine(res);
}
catch (Exception ex)
{
System.Console.WriteLine("Error:"
+ ex.Message.ToString());
}
}
================================
C#で Pythonファイル(test.py)内の変数の値の設定、取得を行います。
Python側では、あらかじめ変数に値が設定されている必要はありません。
C#で Python側の変数param1, param2 に、それぞれ値を設定し、Python側が実行された後、ython側の計算結果のresult変数をC#で取得しています。
C# + Python embedding 簡単な計算
CC#からIronPythonに計算させる簡単な例。
■.NET Framework2.0 sp1で実行
sp1でないと動かない点に注意
■IronPython 2.0
以下からIronPython-2.0.1-Bin.zipをダウンロード
http://www.codeplex.com/IronPython → Downloads
以下を参照設定で追加
IronPython.dll
IronPython.Modules.dll
Microsoft.Scripting.Core.dll
Microsoft.Scripting.dll
Microsoft.Scripting.ExtensionAttribute.dll
---- コード ----
using System;
using IronPython;
using IronPython.Hosting;
using Microsoft.Scripting;
using Microsoft.Scripting.Hosting;
...
public static void Main(string[] args)
{
try
{
ScriptEngine engine = Python.CreateEngine();
ScriptScope scope = engine.CreateScope();
// 1 + 2 を Python に計算させる
ScriptSource source =
engine.CreateScriptSourceFromString(
"1 + 2", SourceCodeKind.Expression);
object res = source.Execute();
// 結果を出力 ==> 3
System.Console.WriteLine(res);
}
catch (Exception ex)
{
System.Console.WriteLine("Error:" +
ex.Message.ToString());
}
}
■.NET Framework2.0 sp1で実行
sp1でないと動かない点に注意
■IronPython 2.0
以下からIronPython-2.0.1-Bin.zipをダウンロード
http://www.codeplex.com/IronPython → Downloads
以下を参照設定で追加
IronPython.dll
IronPython.Modules.dll
Microsoft.Scripting.Core.dll
Microsoft.Scripting.dll
Microsoft.Scripting.ExtensionAttribute.dll
---- コード ----
using System;
using IronPython;
using IronPython.Hosting;
using Microsoft.Scripting;
using Microsoft.Scripting.Hosting;
...
public static void Main(string[] args)
{
try
{
ScriptEngine engine = Python.CreateEngine();
ScriptScope scope = engine.CreateScope();
// 1 + 2 を Python に計算させる
ScriptSource source =
engine.CreateScriptSourceFromString(
"1 + 2", SourceCodeKind.Expression);
object res = source.Execute();
// 結果を出力 ==> 3
System.Console.WriteLine(res);
}
catch (Exception ex)
{
System.Console.WriteLine("Error:" +
ex.Message.ToString());
}
}
登録:
投稿 (Atom)