プログラミング素人のはてなブログ

プログラミングも電気回路も専門外の技術屋の末端が勉強したことや作品をアウトプットするブログ。コードに間違いなど見つけられたら、気軽にコメントください。 C#、Python3、ラズパイなど。

C#からPythonを呼び出し外部APIとして利用する

C#GUIPythonの幅広いライブラリを協業したい

Windows向けのデスクトップアプリを作るにはC#がとても安定していて使いやすいのですが、Pythonの幅広いライブラリの便利さも手放せません。
そこで、この二つの良いとこどりが出来ないか、検討しました。

C#ではおもにGUIの部分を作成し、Pythonで作成したAPIを呼び出すことでこれを実現できるのではないかと考えました。
C#Pythonの連携は検索するといくつか出てきますが、それらはいずれもpython.exeを呼び出すものです。
これでは、Pythonの実行環境が必要となってしまうので、アプリケーションの核の部分をPythonで作成して、これをexeファイル化しこれをC#で呼び出すようにします。

まず、簡単なPythonによるAPIを作成します。
ここでは、引数としてテキストと数値を2つ受け取って、テキストをそのまま返し、掛け算を行うものを作ってみます。

import sys

arg = sys.argv  # 引数を取得

print(arg[1])
ans = int(arg[2])*int(arg[3])
print("ans = ", ans)

このPythonスクリプトの実行結果は以下のようになります。

これをexeファイル化します。

$ pyinstaller apisample.py --onefile

onefileオプションは必要なバイナリを一つのexeにまとめるものです。ポータビリティ的に、このようにするほうが良いです。

次にこれを呼び出すC#を作成します。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Diagnostics;

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

        private void button1_Click(object sender, EventArgs e)
        {
            string parameters = "てすと3 5 8";

            Process process = new Process();
            process.StartInfo.FileName = "apisample.exe";
            process.StartInfo.Arguments = parameters;
            process.StartInfo.UseShellExecute = false;
            process.StartInfo.RedirectStandardOutput = true;
            process.StartInfo.RedirectStandardInput = false;
            process.StartInfo.CreateNoWindow = true;
            process.Start();
            string output = process.StandardOutput.ReadToEnd();

            process.WaitForExit();
            process.Close();
            textBox1.AppendText(output);
        }
    }
}

ボタンクリックで実行され、C#からPythpnで作成したapisample.exeを呼び出します。apisample.exeは先のPythonスクリプトをexe化したものです。
apisample.exeC#で作成したexeと同じフォルダにあるものとします。
pythonコマンドライン引数でパラメータを受け取って、print()で値を返すようになっています。
これで、C#からパラメータを渡し、応答を受け取ることが出来ます。

まとめ

C#Pythonの間でパラメータを受け渡しすることができました。
PythonはAIやその他充実したライブラリがあります。
PythonにもGUIはありますが、今一つ使い勝手が悪く、何か方法はないか?と考えていました。
今回、あらためてC#Pythonの連携を検討し上手くできたと思います。
このようにして、テキストや数値(バイナリ)を受け渡しする方法は通信で使われる一般的な考え方に近いのではないかと思います。