我试图使用一个用C语言编写的.dll(尽管它包含了一个matlab .ddl)
我尝试使用的函数在C中定义为:
__declspec(dllexport) int ss_scaling_subtraction(double* time, double** signals, double* amplitudes, int nSamples, int nChannels, double* intensities);
除其他外,.dll需要一个二维数组 - 当我尝试使用时:
Array of array of double
在声明中,编译器发出错误,因此我定义了自己的数据类型:
T2DArray = Array of array of double;
我在一个单元中初始化.dll函数:
function ss_scaling_subtraction(const time: array of double; const signals: T2DArray; const amplituides : array of double; const nSamples: integer;const nChannels: integer; var intensities: array of double) : integer ; cdecl; external 'StirScanDLL.dll';
但是,当调用此函数时,我从.dll获取访问冲突
创建新数据类型
T1DArray = array of double
和改变
Array of double
至
T1DArray
在声明似乎使事情运行但结果仍然不正确.
我在这里读到,将delphi数据类型传递给.dll以不同语言编码可能很危险,所以我认为这可能会导致问题.
但是当我必须首先使用它来正确地声明函数时,我怎么不使用delphi数据类型?!
额外的信息,我已经打开了matlab运行时编译器的lib并打开了StirScanDLL.dll的入口点
这里的基本问题是二进制互操作不匹配之一.简单地说,指向数组的指针在二进制级别与Delphi开放数组参数不同.虽然它们在语义上都表示数组,但二进制表示不同.
C函数声明如下:
__declspec(dllexport) int ss_scaling_subtraction( double* time, double** signals, double* amplitudes, int nSamples, int nChannels, double* intensities );
在Delphi中声明你的函数:
function ss_scaling_subtraction( time: PDouble; signals: PPDouble; amplitudes: PDouble; nSamples: Integer; nChannels: Integer; intensities: PDouble ): Integer; cdecl; external 'StirScanDLL.dll';
如果您发现PPDouble
未声明,请按以下方式对其进行定义:
type PPDouble = ^PDouble;
也就是指针指向double的指针.
现在剩下的就是调用这些函数.在Delphi中将您的数组声明为动态数组.像这样:
var time, amplitudes, intensities: TArray<Double>; signals: TArray<TArray<Double>>;
如果你有一个较旧的pre-generics Delphi,那么声明一些类型:
type TDoubleArray = array of Double; T2DDoubleArray = array of TDoubleArray;
然后使用适当的类型声明变量.
接下来,您需要分配数组,并填充从调用者传递给被调用者的任何数据.
SetLength(time, nSamples); // I'm guessing here as to the length SetLength(signals, nSamples, nChannels); // again, guessing
最后是时候调用这个函数了.现在事实证明,Delphi的优秀设计师安排将动态数组存储为第一个元素的指针.这意味着它们不会被用作参数.
retval := ss_scaling_subtraction( PDouble(time), PPDouble(signals), PDouble(amplitudes), nSamples, nChannels, PDouble(intensities) );
请注意,此处显示的动态数组的强制转换依赖于实现细节.因此,有些人可能会争辩说,对于@time[0]
一维数组,例如等等会更好.并创建一个PDouble
振幅数组并复制内部数组的第一个元素的地址.就个人而言,我很依赖这个实现细节.它确实使编码更加简单.
最后一条建议.Interop可能很棘手.这很容易出错.当你弄错了,代码编译,但在运行时死亡可怕.带有神秘的错误消息.导致头部刮伤.
所以,从最简单的接口开始.接收标量参数的函数.比如说,接收一个整数,并返回一个整数.证明你可以做到这一点.然后转到浮点标量.然后是一维数组.最后是二维数组.沿途的每一步,都会增加复杂性.当您遇到问题时,您会知道它已归结为最近添加的参数.
你没有采取这种方法.你已经直接杀死并在你的第一次尝试中实现了一切.当它失败时,你不知道在哪里看.将问题分解成小块,并从那些较小的块中构建更复杂的问题.