Вызов библиотеки C# из python

Кто-нибудь может поделиться рабочим примером того, как вызвать простую библиотеку C# (фактически ее WPF) из кода Python? (Я пытался использовать IronPython, и у меня было слишком много проблем с неподдерживаемой библиотекой CPython, которую использует мой код на python, поэтому я подумал о том, чтобы попробовать другой способ и вызвать мой код C# из Python).

Вот пример, с которым я играл:

using System.Runtime.InteropServices;
using System.EnterpriseServices;

namespace DataViewerLibrary
{
    public interface ISimpleProvider
    {
       [DispIdAttribute(0)]
       void Start();
    }

    [ComVisible(true)]
    [ClassInterface(ClassInterfaceType.None)]
    public class PlotData : ServicedComponent, ISimpleProvider
    {
       public void Start()
       {
          Plot plotter = new Plot();
          plotter.ShowDialog();
       }
    }
}

Плоттер - это окна WPF, которые строят эллипс

Я не знаю, как вызвать этот код из моего питона все. Какие-либо предложения?

6 ответов

Это на самом деле довольно легко. Просто используйте NuGet, чтобы добавить пакет "UnmanagedExports" в ваш.Net проект. Подробнее см. https://sites.google.com/site/robertgiesecke/Home/uploads/unmanagedexports.

Затем вы можете экспортировать напрямую, без необходимости делать слой COM. Вот пример кода C#:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using RGiesecke.DllExport;

class Test
{
    [DllExport("add", CallingConvention = CallingConvention.Cdecl)]
    public static int TestExport(int left, int right)
    {
        return left + right;
    }
}

Затем вы можете загрузить dll и вызвать открытые методы в Python (работает для 2.7)

import ctypes
a = ctypes.cdll.LoadLibrary(source)
a.add(3, 5)

Поскольку ваш пост помечен IronPython, если вы хотите использовать пример C#, должно работать следующее.

import clr
clr.AddReference('assembly name here')
from DataViewerLibrary import PlotData 

p = PlotData()
p.Start()

Python для.Net (pythonnet) может быть разумной альтернативой IronPython в вашей ситуации. https://github.com/pythonnet/pythonnet/blob/master/README.md

С сайта:

Обратите внимание, что этот пакет не реализует Python как первоклассный язык CLR - он не создает управляемый код (IL) из кода Python. Скорее, это интеграция движка CPython со средой исполнения.NET. Этот подход позволяет использовать службы CLR и продолжать использовать существующий код Python и расширения на основе C, сохраняя при этом собственные скорости выполнения кода Python.

Также

Python для.NET использует PYTHONPATH (sys.path) для поиска загружаемых сборок в дополнение к обычной базе приложений и GAC. Чтобы гарантировать возможность неявного импорта сборки, поместите каталог, содержащий эту сборку, в sys.path.

Этот пакет по-прежнему требует наличия локальной среды выполнения CPython на вашем компьютере. См. Полный файл Readme для получения дополнительной информации http://pythonnet.github.io/readme.html

Этот проект был разработан именно для этой цели - используйте классы C# в обычном Python

https://bitbucket.org/pydotnet/pydotnet/wiki/Home

Все, что вам нужно сделать, это установить MSI или EGG в ваш CPython. PyDotnet - это модуль Python, поэтому исполняемый файл остается обычным python.exe из вашей установки Python или Anaconda. Поддерживаются как 32-битные, так и 64-битные.

Неограниченный доступ ко всем классам C#, методам с параметрами output и ref, универсальным классам и универсальным методам, методам расширения, закрытым членам.

Перегруженный сборочный загрузчик с настраиваемой механикой для поиска сборок.

Информация о типе среды выполнения.NET, преобразуемая в объект класса, который может быть создан как любой другой класс.

Специальный режим импорта, разработанный специально для интерактивной оболочки Python, который позволяет обнаруживать доступные сборки, пространства имен, классы, методы и т. Д.

Жду отзывов:)

Майкл Бейкер уже дал правильный ответ.

Вот рабочий пример:

Код C# ClassLibrary:
(не забудьте ключевое слово public и обратите внимание на пространство имен, оно станет именем модуля Python)

          namespace MyDotNetClassLib
    {
        public class Adder
        {
            public static int StaticAdd(int left, int right)
            {
                return left + right;
            }
            public int Add(int left, int right)
            {
                return left + right;
            }
        }
    }

Вывод создается как ".\MyDotNetClassLib\bin\Debug\net7.0\MyDotNetClassLib.dll"

Файл Python : ".\PythonApplication\PythonApplication.py"
добавляет путь к файлу dll.
AddReference имя сборки (обычно имя файла dll без .dll)
. Импортирует модуль (который является пространством имен C#).

          import clr
    from System import Console
    #from System import String
    #from System.Collections import *
    
    import sys
    sys.path.append('../MyDotNetClassLib/bin/Debug/net7.0/')
    clr.AddReference("MyDotNetClassLib")
    from MyDotNetClassLib import Adder 
    
    
    print()
    print("hello from python")
    Console.WriteLine("hello from C#")
    
    print(f"My C# Adder static: {Adder.StaticAdd(1,2)}")
    
    adder = Adder()
    print(f"My C# Adder method: {adder.Add(3,4)}")

Вывод консоли при вызове:

          PS PythonApplication> python .\PythonApplication.py

    hello from python
    hello from C#
    My C# Adder static: 3
    My C# Adder method: 7

Скомпилировано и запущено с помощью:

  • ПРОТИВ 2022/.NET 7.0
  • Python 3.10.11 (и не забудьте «pip install pythonnet»)

Я не эксперт.NET, но ваш код выглядит так, как будто ваш метод представлен как объект COM. Таким образом, вы можете попробовать пакет http://starship.python.net/crew/mhammond/win32/, чтобы получить к нему доступ.

Другие вопросы по тегам