2013-06-21 22 views
1

我使用Delphi来加载一个dll(我在Delphi XE-3中创建)用于与一些C代码接口的目的。我的问题是搞清楚为什么我的数组没有被传递给c函数 - 他们是唯一没有的。德尔福文件(简体)看起来是这样的:德尔福到C的dll:传递阵列

program CallcCode 
uses 
    SysUtils, Windows, 
    DLLUnit in 'DLLUnit.pas'; // Header conversion 

var 
    DLLHandle: cardinal; 
    n: Integer; 
    A: TArray<Integer>; 
    result1: Integer; 

begin 
    // Initialize each Array 
    SetLength(A,n); 
    A[0] = ...; 

    // Load the DLL (and confirm its loaded) 
    DLLhandle := LoadLibrary('dllname.dll'); 
    if DLLhandle <> 0 then 
     begin 
     result1 := dll_func1(n,A); // A and B are not passed correctly 
    end 
    FreeLibrary(DLLHandle); 
end. 

我成功 “跟踪到” dll_func1首次进入DLLUnit,其中有:

const 
    nameofDLL = 'dllname'; 
function dll_func1(n: Integer; A: TArray<Integer>): Integer; cdecl; external nameofDLL; 

再次 “跟踪-成”,我到达在C文件,它仍然具有正确的n和DLLdefs值,但A(“本地变量”标题下)已经成为:

[-] A  :(Aplha-Numeric) 
    ..[0] 0 (0x00000000) 

我知道我至少访问该DLL(希望)正确的导致其他函数调用正常工作,并且我可以在没有问题的情况下跟踪到dll_func1.c文件。我试图改变功能

function dll_func1(n: Integer; A: PInteger): Integer; cdecl; external nameofDLL; 
... 
result1 := dll_func1(n,PInteger(A)) 

function dll_func1(n: Integer; A: PInteger): Integer; cdecl; external nameofDLL; 
... 
result1 := dll_func1(n,@A[0]) 

(同时使用在tarray和整数数组或A),但没有任何改变,这让我相信这是关系到一个问题,我没有看到。整个事情编译和运行,但由于TArray失败,result1不正确。有什么想法出错?

编辑 C语言中的功能:

int dll_func1(int n, int A []) 
+0

你只需要做我在回答你的上一个问题时告诉你的。密切关注我写的内容。你在这里没有什么喜欢的。那么,问题的后半部分是。我怀疑结构是错误的。你为什么不写一个C函数,它只需要一个数组并且试图通过它。然后变得更加雄心勃勃。 –

+0

我在函数调用(单元文件)中写了'PInteger',在程序文件(我初始化它们的地方)中将它们定义为'TArray ',并使用了'solve(n,PInteger(Ap),PInteger(Ax)) ';只有数组没有传递给函数。你是什​​么意思的结构传递不正确? –

+0

编号PInteger是预定义的类型。不要将它重新定义为别的东西。删除所有的声明。它被声明为PInteger =^Integer –

回答

4

你的问题包含外部函数的两个德尔福声明。其中之一使用TArray<T>作为参数。这是完全错误的。不要这样做。您不能使用Delphi动态数组作为互操作类型。原因是TArray<T>是一个复杂的托管类型,只能由Delphi代码创建和使用。

您需要按照下面的方法来做,正如我在回答您的上一个问题时所解释的,并将数组参数声明为指向元素类型的指针。例如,PInteger,PDouble

这里有相当多的混淆和不必要的复杂性。你需要的是一个最简单的例子,它展示了如何将数组从Delphi代码传递到C代码。

这是。

C代码

//testarray.c 

void printDouble(double d); // linker will resolve this from the Delphi code 

void test(double *arr, int count) 
{ 
    int i; 
    for (i=0; i<count; i++) 
    { 
     printDouble(arr[i]); 
    } 
} 

Delphi代码

program DelphiToC; 

{$APPTYPE CONSOLE} 

uses 
    Crtl; 

procedure _printDouble(d: Double); cdecl; 
begin 
    Writeln(d); 
end; 

procedure test(arr: PDouble; count: Integer); cdecl; external name '_test'; 

{$L testarray.obj} 

var 
    arr: TArray<Double>; 

begin 
    arr := TArray<Double>.Create(1.0, 2.0, 3.0, 42.0, 666.0); 
    test(PDouble(arr), Length(arr)); 
    Readln; 
end. 

编译使用C代码,例如,所述的Borland C编译器是这样的:

 
bcc32 -c testarray.c 

而输出是:

 
1.00000000000000E+0000 
2.00000000000000E+0000 
3.00000000000000E+0000 
4.20000000000000E+0001 
6.66000000000000E+0002 

请注意,我静态链接到C代码,因为这对我来说更容易。如果将C代码放在DLL中,没有太大的改变。

结论是,我在回答您的上一个问题时给出的代码,我在这里重复一遍,是正确的。该方法成功地将Delphi代码中的数组传递给C.它看起来像您的诊断和调试错误。

您只在检查A[0],因此您只能看到一个值并不奇怪。如果您只看到A[1]A[2],...,A[n-1],您会看到所有值都正确传递。或者您的调试可能是错误地声明了使用TArray<T>作为参数的外部函数。

+0

我知道在我这边有什么不对,尝试用delphi代码传递数组的“不同”方式表明,它不是数组本身就是问题(因为它们都不起作用)。问题是我对DLL和接口是新手,不知道接下来要测试什么,这就是为什么我要求解决一些其他问题。最小的例子(这一个和我所做的)都工作(真的没有意外)。至于结构,这是一个错误的问题(我固定它);它一直在我的代码中工作,它仍然只是数组。 –

+1

那么,你在这里找什么?我已经向您展示了如何传递一个数组,现在两次。我在这里猜测,但我的猜测是你的数组传递的很好,但你不知道如何在栅栏的C端显示它。你忽略了显示你的界面的C端。你的数组参数是什么类型?他们是“int *”吗?当然,如果你看'* A',说,那么你只能看到一个值。但是'A [0]','A [1]'等等。再次,请删除复杂性。你的问题中的代码应该与单个数组一起工作。摆脱结构,它只是分散注意力。简化。 –