本稿では,OpenRCFからPythonで書かれたコードを実行する方法について紹介します.後述する方法では,PythonのコードはPython用の一般的な実行エンジンで動かしつつ,OpenRCF側で入出力の差し替えとPythonコードを実行するタイミングの制御を行います.つまり,(内部的には)OpenRCFとPythonはそれぞれ独立して動作しているため,依存関係のバグが起こりにくい(or 起こらない)はずです.
1 準備
1.1 Pythonのインストール
普通にPythonをインストールします.ChatGPTなどに聞きながらやれば,問題なく完了するはずです.
https://www.python.org/downloads/
コマンドプロンプトで「python --version」と入力したときに,バージョンが表示されていればOKです.

1.2 Python用のフォルダとスクリプト(コード)を用意
まず,OpenRCFの「program」フォルダ内に「PythonScripts」というフォルダを新規作成します.フォルダの名前(PythonScripts)は重要なので,変更しないでください.

さらに,「PythonScripts」フォルダの中に「test_scripts.py」というファイルを作成します.

適当なエディタ(VS Codeなど)を用いて,test_scripts.pyに以下のようなサンプルコードを書きます.
import sys
a = int(sys.argv[1])
b = int(sys.argv[2])
print(a + b)
sys.argv[1], sys.argv[2]...がOpenRCF(C#)から受け取る値になります(不要な場合は無くてもOK).ここではint型としていますが,float型やdouble型にすることも可能です.また,python側でprintした文字列(ここでは a+b の値)は,OpenRCF(C#)側で読み込めるようになります.
1.3 OpenRCF側にPython用のクラス(C#)を用意
右クリック→「追加」→「新しい項目」で,「Python.cs」ファイルを作ります.

さらに,「Python.cs」ファイルに下記のコードを書きます(内容は理解せずに丸々コピペしてもOK).
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
namespace OpenRCF
{
class Python
{
private ProcessStartInfo processInfo = new ProcessStartInfo();
public Python()
{
processInfo.UseShellExecute = false;
processInfo.RedirectStandardOutput = true;
processInfo.RedirectStandardError = true;
processInfo.CreateNoWindow = true;
string pathToPythonFolder = @"..\..\PythonScripts\";
if (Directory.Exists(pathToPythonFolder)) processInfo.WorkingDirectory = pathToPythonFolder;
else Console.WriteLine("Error : PythonScripts folder not found. Please create it.");
string pathToPythonExe = @SearchPathToPythonExe();
if(pathToPythonExe != null) processInfo.FileName = pathToPythonExe;
else Console.WriteLine("Error : python.exe not found. Please install Python.");
}
private static string SearchPathToPythonExe()
{
string defaultPythonPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Programs", "Python");
if (!Directory.Exists(defaultPythonPath)) return null;
var basePathDirs = Directory.GetDirectories(defaultPythonPath);
var pythonPathList = basePathDirs.Select(dir => Path.Combine(dir, "python.exe")).Where(File.Exists).ToList();
if (pythonPathList.Any()) return pythonPathList[pythonPathList.Count - 1];
else return null;
}
private static string ToString(object obj)
{
if (obj is Array innerArray && !(obj is string))
{
return string.Join(" ", innerArray.Cast<object>().Select(x => x.ToString()));
}
return obj.ToString();
}
public string Execute(string fileName, params object[] sysArgv)
{
if (!fileName.EndsWith(".py")) fileName += ".py";
if(!File.Exists(processInfo.WorkingDirectory + fileName))
{
Console.WriteLine("Error : {0} not found in the {1} directory.", fileName, processInfo.WorkingDirectory);
return "";
}
processInfo.Arguments = fileName;
if (0 < sysArgv.Length) processInfo.Arguments += " " + string.Join(" ", sysArgv.Select(obj => ToString(obj)));
Process process = Process.Start(processInfo);
string printedData = process.StandardOutput.ReadToEnd();
string errorMsg = process.StandardError.ReadToEnd();
process.WaitForExit();
if (!string.IsNullOrWhiteSpace(errorMsg)) Console.WriteLine("Error : " + errorMsg);
return printedData.Replace("\r\n", "");
}
}
}
以上で準備完了!
2 OpenRCFからPythonのコードを実行し,結果を取得する
2.1 Pythonクラスの使用例
OpenRCFの「MainWindow.xaml.cs」ファイルでの使用例は以下の通りです.
Python Python = new Python();
void Button1_Click(object sender, RoutedEventArgs e)
{
string output = Python.Execute("test_script.py", 1, 2);
Console.WriteLine(output);
}
ボタン1を押すと,test_script.pyファイルに引数(1, 2)を送り,その引数に対するPythonコードの実行結果(Pythonの中でprintしたもの)を受け取ることができます.つまり,python側で「sys.argv[1]=1」,「sys.argv[2]=2」としてコードを実行し,そのときにprint関数で出力したもの(3)がoutputに格納されてます.
2.2 補足
Python側に送るデータが多くなる場合は,以下のように配列で渡すこともできます.
Python Python = new Python();
void Button1_Click(object sender, RoutedEventArgs e)
{
int[] input = new int[2] { 1, 2 };
string output = Python.Execute("test_script.py", input);
Console.WriteLine(output);
}
注意点としては,Python側(test_script.pyファイル)で引数(sys.argv[1], sys.argv[2]など)をfloat型やdouble型にしている場合は,OpenRCF(C#)もそれらの型に合わせて引数を与えてあげる必要があります.
また,もしpython側で引数(sys.argv[1], sys.argv[2]など)を使用していなかった場合は,以下のようにして実行できます.
Python Python = new Python();
void Button1_Click(object sender, RoutedEventArgs e)
{
string output = Python.Execute("test_script.py");
Console.WriteLine(output);
}
Pythonのコードを実行しているのはOpenRCFではなく,一般的なPythonの実行エンジンなので,何かPythonのライブラリを使用したい場合は,コマンドプロンプトの方で pip install すると使えるようになります.