Использование ctypes в python для доступа к методам C # dll - PullRequest
9 голосов
/ 16 июля 2011

Я хотел бы внедрить код C # в критически важную часть моей программы на Python, чтобы сделать его быстрее. Он говорит (в документации по Python и на этом сайте ), что вы можете загрузить библиотеку динамических ссылок (и, скажем, PyDocs) следующим образом:

cdll.LoadLibrary("your-dll-goes-here.dll")

Это часть моего кода, которая заботится об этой функции:

from ctypes import *
z = [0.0,0.0]
c = [LEFT+x*(RIGHT-LEFT)/self.size, UP+y*(DOWN-UP)/self.size]
M = 2.0

iterator = cdll.LoadLibrary("RECERCATOOLS.dll")

array_result = iterator.Program.ITERATE(z[0],z[1],c[0],c[1],self.iterations,M)

z = complex(array_result[0],array_result[1])
c = complex(array_result[2],array_result[3])
last_iteration = int(round(array_result[4]))

И RECERCATOOLS.dll, который я использую, это (код C #, а не C или C ++):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using KarlsTools;

public class Program
{
    public static Array ITERATE(double z_r,double z_i,double c_r,
                        double c_i, int iterations, 
                        double limit)
    {
        Complex z = new Complex(z_r, z_i);
        Complex c = new Complex(c_r, c_i);

        for (double i = 1; Math.Round(i) <= iterations; i++)
        {
            z = Complex.Pow(z, 2) + c;
            if (Complex.Abs(z) < limit)
            {
                double[] numbers = new double[] { Complex.Real(z),
                                                  Complex.Imag(z),
                                                  Complex.Real(c),
                                                  Complex.Imag(c),
                                                  i};
                return numbers;
            }
        }
        double iter = iterations;
        double[] result = new double[]        { Complex.Real(z),
                                                  Complex.Imag(z),
                                                  Complex.Real(c),
                                                  Complex.Imag(c),
                                                  iter};
        return result;
    }
}

Для создания этой библиотеки DLL я использую команду «Build» над проектом Visual Studio 2010, который содержит только этот файл и ссылку на «Karlstools», модуль, который позволяет мне использовать комплексные числа.

Я не знаю почему, но когда я пытаюсь запустить мой код Python, он просто выдает исключение:

    [...]
    array_result = iterator.Program.ITERATE(z[0],z[1],c[0],c[1],self.iterations,M)
  File "C:\Python32\lib\ctypes\__init__.py", line 353, in __getattr__
    func = self.__getitem__(name)
  File "C:\Python32\lib\ctypes\__init__.py", line 358, in __getitem__
    func = self._FuncPtr((name_or_ordinal, self))
AttributeError: function 'Program' not found

Мне нужна помощь с этим, поскольку он продолжает выдавать исключения, даже когда все установлено на public, а функция - static, или даже если я пытаюсь получить доступ к функции напрямую, без указания класса "Program" ... Понятия не имею, где может быть проблема.

Ответы [ 5 ]

11 голосов
/ 24 апреля 2015

Это на самом деле довольно легко.Просто используйте 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)
7 голосов
/ 17 июля 2011

Советы, которые вы найдете в отношении вызова DLL из Python с использованием ctypes, в большинстве случаев полагаются на то, что DLL пишется на C или C ++, а не на C #.С C # вы задействуете весь механизм CLR, и символы, скорее всего, искажены, а не того, чего ожидают ctypes, и вы получите всевозможные проблемы из сборки мусора вашего выходного массива.

У меня был очень хороший успех при взаимодействии Python и C # кода с использованием Python для точечной сети (http://pythonnet.sf.net),, вы можете попробовать это.

С другой стороны, еслиВы заинтересованы в чистой производительности, подумайте о том, чтобы переписать свой код как собственное расширение C для Python с использованием API Python / C (http://docs.python.org/c-api/).

3 голосов
/ 17 июля 2011

Другие отметили, что C # DLL не может обрабатываться так же, как нативная DLL.

Один из вариантов, который у вас есть, - это экспорт вашей функциональности C # в виде COM-объекта, который может легко использоваться Python.

Лично я бы рассмотрел решение с собственным кодом, но вы, возможно, слишком преданы C #, чтобы изменить курс на этом этапе.

1 голос
/ 28 ноября 2013

AC # DLL на самом деле называется сборкой, поэтому она совершенно другая.Если нет очень важной причины, я предлагаю вам использовать C ++

1 голос
/ 17 июля 2011

ctypes предназначен для загрузки разделяемых библиотек, написанных на C (или, по крайней мере, разделяемых библиотек, которые непосредственно исполняются процессором и экспортируют их символы и аргументы функций в соответствии со стандартными соглашениями C.) DLL C # не являются "обычными" DLL,но скорее предназначен для работы в среде .NET.

Ваши варианты:

  1. Использовать какой-то мост между Python и .NET.
  2. Записать DLL вC и используйте ctypes для вызова функции и обработки преобразований данных.
  3. Используйте API Python / C и создайте загружаемый модуль Python.

Я не могу говорить сВариант № 1, я этого не сделал.Вариант № 2 обычно проще, чем вариант № 3, поскольку вы пишете чистый код C и склеиваете его с помощью ctypes.Вариант № 3 обеспечит наилучшую производительность из всех трех вариантов, поскольку он имеет минимальные накладные расходы и выполняет собственный код на процессоре.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...