137
Help us understand the problem. What are the problem?

More than 3 years have passed since last update.

posted at

updated at

Organization

Pythonから.NETを呼び出す方法とついでにその逆も

はじめに

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())

image.png

ジェネリックスは角括弧を使って書くことができます.以下は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までの対応のようです.

image.png

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()
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
137
Help us understand the problem. What are the problem?