Передача массива NumPy в Delphi DLL - PullRequest
0 голосов
/ 06 мая 2011

Я пытаюсь реализовать алгоритм классификации изображений в Python.Проблема в том, что python очень долго обходится с массивом.Вот почему я решил написать DLL Delphi, которая выполняет обработку массива.Моя проблема в том, что я не знаю, как передать многомерный массив python в мою dll-функцию.

Delphi dll extract: (я использую эту функцию только для тестирования)

type
    TImgArray = array of array of Integer;

function count(a: TImgArray): Integer; cdecl;
begin
    result:= high(a);
end;

соответствующий код Python:

arraydll = cdll.LoadLibrary("C:\\ArrayFunctions.dll")

c_int_p = ctypes.POINTER(ctypes.c_int32)
data = valBD.ReadAsArray()
data = data.astype(np.int32)
data_p = data.ctypes.data_as(c_int_p)

print arraydll.count(data_p)

Значение, возвращаемое функцией dll, не является правильным (это 2816 вместо 7339).Вот почему я думаю, что с преобразованием типов что-то не так :( Заранее спасибо, Марио

Ответы [ 2 ]

1 голос
/ 08 мая 2011

Обычные массивы Python обычно называются «списками». Тип numpy.array в Python - это специальный тип, который более эффективен в отношении памяти, чем обычный список Python обычных объектов Python с плавающей запятой. Numpy.array оборачивает стандартный блок памяти, доступ к которому осуществляется как собственный тип массива Си. Это, в свою очередь, НЕ соответствует чисто типам массивов Delphi.

Как говорит Дэвид, если вы хотите использовать C, все будет проще. Если вы хотите использовать Delphi и получить доступ к Numpy.array, я подозреваю, что самый простой способ сделать это - найти способ экспортировать некоторые простые функции C, которые обращаются к типу Numpy.array. В C я импортировал бы пустые заголовки, а затем написал функции, которые я мог бы вызывать из Pascal. Тогда я бы импортировал эти функции из DLL:

function GetNumpyArrayValue( arrayObj:Pointer;  index:Integer):Double;

Я давно не писал код оболочки CPython. Это было бы проще, если бы вы хотели просто получить доступ к типам CORE PYTHON из Delphi. Существующие оболочки Python-for-delphi помогут вам. Использование numpy с Delphi - это намного больше работы.

Поскольку вы пишете только DLL, а не целое приложение, я бы посоветовал вам забыть о Delphi и написать этого щенка на простом C, что и должно быть в действительности расширение Python (то, что вы пишете) написано в.

Короче говоря, поскольку вы пишете DLL в Pascal, вам потребуется по крайней мере еще одна небольшая DLL в C, просто для того, чтобы соединить типы между типами расширений Python (numpy.array) и плавающим Python точечные значения. И даже тогда вы не сможете легко (быстро) получить значение массива, которое вы можете прочитать в Delphi, как собственный тип массива delphi.

Самый быстрый механизм доступа, о котором я могу подумать, это:

type
   PDouble = ^Double;

function GetNumpyArrayValue( arrayObj:Pointer; var doubleVector:PDouble; var doubleVectorLen:Integer):Boolean;

Затем вы можете использовать математический тип типа doubleVector (указатель) для доступа к базовому типу памяти массива C.

1 голос
/ 06 мая 2011

То, что вы делаете, не сработает и, вероятно, также повредит память.

Динамический массив Delphi реализован в виде структуры данных, которая содержит некоторые метаданные о массиве, включаядлина.Но то, что вы передаете ему, это указатель в виде массива в стиле C, который является указателем, а не структурой данных динамического массива Delphi.Эта структура специфична для Delphi, и вы не можете использовать ее на других языках.(Даже если вам удалось реализовать точно такую ​​же структуру на другом языке, вы все равно не смогли бы передать ее в DLL-библиотеку Delphi и заставить ее работать правильно, потому что диспетчер памяти Delphi задействован под капотом. Для этого нужно просто спроситьдля повреждения кучи и / или исключений, вызываемых диспетчером памяти.)

Если вы хотите передать массив в стиле C в DLL, вы должны сделать способ C, передав второй параметр, который включаетдлина массива.Ваш код Python уже должен знать длину, и для его вычисления не требуется времени.Вы определенно можете использовать Delphi для ускорения обработки изображений.Но размеры массива должны исходить от Python.Здесь нет ярлыка, который вы можете использовать.

Ваше объявление функции Delphi должно выглядеть примерно так:

type
  TImgArray = array[0..MAXINT] of Integer;
  PImgArray = ^TImgArray;

function ProcessSomething(a: PImgArray; size: integer): Integer; cdecl;
...