はじめに
Pythonで開発をしている中で一部.Net向けに提供されているDLLを呼び出す必要があり,その方法について調べました.
Pythonと.NETというとIronPythonが思い浮かびますが,今回はふつうにCPythonから使えるPython for .NETを採用しました.
Python for .NET
今回の目的そのままですが,Pythonのコードから.NETのコードを呼び出すことができます.
またその逆に,C#のコードからPythonを呼び出すこともでるようです.(Python for .NETって名前からはこっちのほうがしっくりくる??)
開発環境
今回試した開発環境です.
- Windows 10 Pro
- Python 3.6.5
- Visual Studio Community 2017 15.6.6
Pythonのコードから.NETを呼び出す
まずはもともとの目的の,Pythonのコードから.NETを呼び出す方法をです.
インストール
pipからインストールできます.
> pip install pythonnet
標準のクラスライブラリを呼び出す
試しにFormアプリケーションのエントリーポイントの記述をまねて書いてみます.
clr.AddReference
で必要なアセンブリを読み込み,.NETの名前空間をPythonのパッケージとしてimportして扱うことができます.
import clr
clr.AddReference('System.Windows.Forms')
from System.Windows.Forms import Application, Form
Application.EnableVisualStyles()
Application.SetCompatibleTextRenderingDefault(False)
Application.Run(Form())
ジェネリックスは角括弧を使って書くことができます.以下はListクラスの使用例です.
import clr
clr.AddReference('System.Collections')
from System.Collections.Generic import List
lst = List[int]()
lst.Add(3)
lst.Add(2)
lst.Add(1)
lst.Sort()
for x in lst:
print(x)
1
2
3
自作のコードを呼び出す
次は自作のクラスをPythonコードから呼び出します.C#のコードはサンプルとして以下のコードを使いました.
using System;
namespace MyClassNamespace
{
public class Foo
{
private string text;
public Foo(string text) => this.text = text;
public void DoSomething(int count) => Console.WriteLine(new string('*', count).Replace("*", text));
public void DoSomething(string prefix) => Console.WriteLine($"{prefix}: {text}");
}
}
上記のコードをビルドしたMyClass.dll
をPythonのコードと同じディレクトリにコピーすると,以下のように読み込めます.
オーバーロードされているメソッドはOverloads[type]
で呼び分けることができます.(ただし今回の例だと明示的に指定しなくてもうまく動作しました.)
import clr
clr.AddReference('MyClass')
from MyClassNamespace import Foo
foo = Foo('ABC')
foo.DoSomething.Overloads[int](3)
foo.DoSomething.Overloads[str]('@@@')
ABCABCABC
@@@: ABC
C#のコードからPythonを呼び出す
もともとの目的とは違うのですが,逆にC#側からPythonのコードを呼び出す方法についても簡単にまとめます.
インストール
NuGetからインストールできます.ただPython 3.5までの対応のようです.
Pythonのモジュールを呼び出す
GitHubのREADMEに紹介されていたコードです.
ですが自分の環境ではやはり動きませんでした.またPython 3.5が入った環境で動かす機会があれば追記します.
using System;
using System.Collections.Generic;
using Python.Runtime;
namespace ConsoleApp
{
class Program
{
static void Main(string[] args)
{
using (Py.GIL())
{
dynamic np = Py.Import("numpy");
Console.WriteLine(np.cos(np.pi * 2));
dynamic sin = np.sin;
Console.WriteLine(sin(5));
double c = np.cos(5) + sin(5);
Console.WriteLine(c);
dynamic a = np.array(new List<float> { 1, 2, 3 });
Console.WriteLine(a.dtype);
dynamic b = np.array(new List<float> { 6, 5, 4 }, dtype: np.int32);
Console.WriteLine(b.dtype);
Console.WriteLine(a * b);
Console.ReadKey();
}
}
}
}
ハンドルされていない例外: System.DllNotFoundException: DLL 'python35' を読み込めません:指定されたモジュールが見つかりません。 (HRESULT からの例外:0x8007007E)
場所 Python.Runtime.Runtime.Py_IsInitialized()
場所 Python.Runtime.Runtime.Initialize()
場所 Python.Runtime.PythonEngine.Initialize(IEnumerable`1 args, Boolean setSysArgv)
場所 Python.Runtime.PythonEngine.Initialize(Boolean setSysArgv)
場所 Python.Runtime.PythonEngine.Initialize()
場所 Python.Runtime.Py.GIL()