Python からC# DLL を呼ぶ

DLL を作る

VS2022, C# Class Library (.Net Framework) project name PyDLL

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace PyDLL
{
    public class Class1
    {
        // New
        public unsafe void TestPy(String strPair, int nCols, IntPtr data, int size)
        {
            float* array = (float*)data.ToPointer();

            for (int i = 0; i < size; i++)
            {
                for (int c = 0; c < nCols; c++)
                {
                    array[nCols * i + c] = nCols * i + nCols;
                }
            }
        }
    }
}

Python からC# DLL の関数を呼ぶ。

Pythonnet を使う

# pip install pythonnet

PyDLL.py

import sys
import clr
import numpy as np
import pandas as pd
from System import IntPtr

# For pythonnet .Net DLL 
sys.path.insert(0, 'D:/dai_work/C#/PyDLL/PyDLL/bin/Debug')
# D:\dai_work\C#\PyDLL\PyDLL\bin\Debug\PyDLL.dll

clr.AddReference('PyDLL')
from PyDLL import Class1

class1 = Class1()

steps = 1000
cols = 5
data = np.zeros((steps, cols), dtype=np.float32)

class1.TestPy('Test', cols, IntPtr.op_Explicit(data.ctypes.data), len(data))

# Array => Pandas DataFrame
columns = [f'col_{c}' for c in range(cols)]
df = pd.DataFrame(data, columns=columns)

print(df)

String やInt はそのまま渡せる。シンプルなClassやList もReturn できる。ただしReturn 渡しはマーシャリング(プロセス間コピー)が発生するため、大容量データには向かない。Python 側でメモリ確保し、ポインタ渡しすると速い。