2011-05-06 93 views
0

我想在Python中实现图像分类算法。问题是python在循环数组时需要很长的时间。这就是为什么我决定写一个执行数组处理的Delphi dll。我的问题是,我不知道如何将多维python数组传递给我的dll函数。传递一个numpy数组到Delphi dll

德尔福DLL提取物:(我使用此功能仅用于测试)

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)。这就是为什么我想这有事端错了我的类型转换:( 由于提前, 马里奥

+3

numpy数据将是一个值的单个数组。形状由其他元数据决定。试图将其直接映射到Delphi动态数组注定会失败。 我认为在你的位置,我会考虑使用Cython,它可以让你以自然的方式使用numpy数组。 – 2011-05-06 14:57:13

+1

简而言之,我同意戴维的观点,那就是用C写出来。我在答案中对David的观点进行了扩展。 – 2011-05-07 23:54:08

回答

1

你在做什么都不行,而且很可能会破坏内存了。

德尔福动态数组是在数据结构下面实现的,它包含一些关于数组的元数据,包括长度,但是传递给它的是一个C型指针 - 数组,它是一个指针,而不是一个Delphi动态数组数据结构,这个结构是Delphi特有的,你不能在其他语言中使用它(即使你设法用另一种语言实现了完全相同的结构,你仍然不能将它传递给Delphi DLL,它的工作是正确的,因为德尔福的内存管理器涉及unde引擎盖。这样做只是要求内存管理器引发堆损坏和/或异常。)

如果要将C风格的数组传递给DLL,必须通过传递第二个参数包含数组的长度。你的Python代码应该已经知道了它的长度,并且不需要任何时间来计算它。您绝对可以使用Delphi来加速图像处理。但数组维度必须来自Python方面。你可以在这里没有捷径。

你的Delphi函数声明应该是这个样子:

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

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

坦克很多。现在我对Delphi和Arrays有了更多的了解。不过,我会根据您的建议采用C/C++进行尝试。这就是为什么我在我的系统上安装了gcc。也许有人想给我一个提示如何以正确的方式做到这一点(哪种c变量......) – 2011-05-08 17:16:58

+0

@martwig:我不是故意要在C中实际做到这一点;只需要在Delphi代码中遵循C数组传递约定。 :P – 2011-05-08 17:31:58

1

普通的Python阵列通常被称为 “列表”。 Python中的numpy.array类型是一种特殊类型,比普通的Python浮点对象的Python列表更具有内存效率。 Numpy.array包装作为本机C数组类型访问的标准内存块。这反过来,不会干净地映射到Delphi数组类型。

正如大卫所说,如果你愿意使用C,这将会更容易。如果你想使用Delphi并访问Numpy.array,我怀疑最简单的方法是找到一种方法来导出一些访问Numpy.array类型的简单C函数。在C中,我会导入numpy头文件,然后编写可以从Pascal调用的函数。然后,我将从一个DLL中导入这些函数:

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

我还没有在一段时间内编写任何CPython包装代码。如果你想简单地访问Delphi的CORE PYTHON类型,这会更容易。现有的Python-for-delphi包装将帮助你。在Delphi中使用numpy只是更多的工作。

因为你只写了一个DLL而不是一个完整的应用程序,所以我会认真地建议你忘掉Delphi并用纯C编写这个小狗,这就是Python扩展(这就是你正在写的)真的应该写入。

总之,由于您正在编写一个DLL,在Pascal中,您将需要C语言中至少另一个小型DLL,以桥接Python扩展类型(numpy.array)和Python之间的类型浮点值。即使如此,你也不会轻易(快速)获得一个你可以在Delphi中读取的数组值作为本地的delphi数组类型。

的我能想到的最快非常准入机制是这样的:

type 
    PDouble = ^Double; 

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

然后,您可以使用doubleVector(指针)类型的数学来访问底层的C数组的内存类型。