德尔福到C DLL:传递数组 [英] Delphi-to-C dll: Passing Arrays

查看:123
本文介绍了德尔福到C DLL:传递数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

 程序CALLC code
用途
  SysUtils单元时,Windows,
  在DLLUnit.pas'DLLUnit; //头转换VAR
  DLLHandle:基数;
  n:整数;
  答:在tarray<整数取代;
  RESULT1:整数;开始
  //初始化每个阵列
  SetLength函数(A,N);
  A [0] = ...;  //加载DLL(并确认其加载)
  DLLhandle:=的LoadLibrary('dllname.dll');
    如果DLLhandle<> 0,则
      开始
       RESULT1:= dll_func1(N,A); // A和B不正确传递
    结束
  FreeLibrary则(DLLHandle);
结束。

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

 常量
  nameofDLL ='的Dllname';
功能dll_func1(n:整数; A:在tarray<整数GT):整数; CDECL;外部nameofDLL;

跟踪-变成再说一次,我到达C文件,仍然有正确的n和DLLdefs值,但A(根据局部变量标题)已经成为:

  [ - ]答:(APLHA数字)
    .. [0] 0(00000000)

我知道我至少访问该DLL(希望)正确,因为其他函数调用的工作,因为他们应该和我能够追查到dll_func1.c文件没有问题。我试图改变功能

 函数dll_func1(n:整数; A:PInteger):整数; CDECL;外部nameofDLL;
...
RESULT1:= dll_func1(N,PInteger(A))

 函数dll_func1(n:整数; A:PInteger):整数; CDECL;外部nameofDLL;
...
RESULT1:= dll_func1(N,@ A [0])

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

修改 C语言中的功能:

  INT dll_func1(INT N,INT A [])


解决方案

您的问题包含外部函数的两个德尔福声明。其中一人使用在tarray< T> 作为参数。这是完全错误的。不要那样做。您不能使用一个Delphi动态数组作为互操作类型。原因是,在tarray< T> 是只能被创建和德尔福code消耗了复杂的托管类型

您需要做的,因为我做以下,正如我在回答解释你的previous问题,声明数组参数作为指针元素类型。例如, PInteger PDouble

有相当大量的混乱在这里,和不必要的复杂性。你需要的是一个最简单的例子,说明如何从你的Delphi code数组传递到C code。

下面则是

C $ C $ç

  // testarray.c无效printDouble(双D); //连接器就会根据德尔福code解决此无效试验(双*改编,诠释计数)
{
    INT I;
    对于(i = 0; I<计数;我++)
    {
        (ARR [I])printDouble;
    }
}

德尔福code

 程序DelphiToC;{$ APPTYPE CONSOLE}用途
  CRTL;程序_printDouble(D:双人间); CDECL;
开始
  Writeln(四);
结束;程序测试(ARR:PDouble;计数:整数); CDECL;外部名称'_test';{$ L testarray.obj}VAR
  ARR:在tarray<双取代;开始
  ARR:=在tarray<双> .Create(1.0,2.0,3.0,42.0,666.0);
  测试(PDou​​ble(ARR),长度(ARR));
  Readln;
结束。

编译使用C code,例如,Borland的C编译器是这样的:


bcc32 -c testarray.c

和输出是:


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

请注意,我联系到C code静态,因为这对我来说更容易。没有什么太大的变化,如果你把C code下的DLL。

结论是,code我给你在我回答你的previous,而且我在这里重复,是正确的。这种方法成功地通过德尔福code到C数组它看起来像你的诊断和调试是错误的。

您只检查 A [0] 所以这并不奇怪,你只能看到一个值。如果只有你会看 A [1] A [2] ... A [N-1] 你会看到,所有的值都被正确传递。或者,也许你的调试于所使用的外部函数的错误声明进行了在tarray< T> 作为参数

I'm using Delphi to load a dll (that I created in Delphi XE-3) for the purposes of interfacing with some C code. My problem is figuring out why my arrays aren't being passed to the c functions - they're the only ones not to. The delphi file (simplified) looks like this:

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.

I successfully "Trace into" dll_func1 the first time, entering DLLUnit, which has:

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

"Tracing-into" again, I arrive at the c file, which still has the correct n and DLLdefs values, but A (under the "Local Variables" heading) has become:

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

I know that I'm at least accessing the DLL (hopefully) correctly because other function calls work as they should and I am able to trace into the dll_func1.c file without a problem. I tried changing the function to

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

or

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

(using both TArray and array of Integer or A) but there is no change, which leaves me to believe this is related to a problem I'm not seeing. The whole thing compiles and runs, but result1 is incorrect because of the TArray failures. Any ideas on what is going wrong?

EDIT The function in C as:

int dll_func1(int n, int A [])

解决方案

Your question contains two Delphi declarations for the external function. One of them uses TArray<T> as a parameter. That is completely wrong. Don't do that. You cannot use a Delphi dynamic array as an interop type. The reason being that TArray<T> is a complex managed type that can only be created and consumed by Delphi code.

You need to do as I do below, and as I explained in my answer to your previous question, and declare the array parameter as pointer to element type. For example, PInteger, PDouble, etc.

There's quite a lot of confusion here, and needless complexity. What you need is the simplest possible example that shows how to pass an array from your Delphi code to C code.

Here is is.

C code

//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 code

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.

Compile the C code using, for example, the Borland C compiler like this:

bcc32 -c testarray.c

And the output is:

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

Note that I linked to the C code statically because that was easier for me. Nothing much changes if you put the C code in a DLL.

The conclusion is that the code I gave you in my answer to your previous, and that I repeat here, is correct. That approach succeeds in passing an array from Delphi code to C. It looks like your diagnostics and debugging is in error.

You are only inspecting A[0] so it's hardly surprising that you only see one value. If only you would look at A[1], A[2], ... , A[n-1] you would see that that all the values are being passed correctly. Or perhaps your debugging was carried out on the erroneous declaration of the external function that used TArray<T> as a parameter.

这篇关于德尔福到C DLL:传递数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆