小弟对Delphi不熟悉,但是现在有一个用Delphi写的DLL,现在需要用C来调用这个DLL。在此DLL中有一个export函数的声明是这样的:
type  // Type of plugin's functions
  TFT0Command      = function (const Header : array of byte;
                               const rwData : byte;
                                 var DATA   : array of byte;
                                     wasRW  : PWord) : LongInt;
                                                       stdcall;我用C语言来调用这函数的时候,函数中获得Header的长度不正确。
我想知道,在Delphi中是如何来确定数组的长度。
不要告诉我用SizeOf(array),Low(array),High(array)这些函数,我需要知道这些函数实现的原理。例如,在C语言中,如果要将一个数组作为参数来传递到一个函数中,需要同时将数组的长度也送到函数中去。但是在Delphi中并没有将数组的长度送过去,在函数中它是怎么获得数组的长度呢?

解决方案 »

  1.   

    Returns the number of bytes occupied by a variable or type.function SizeOf(X): Integer;DescriptionPass a Delphi variable reference to SizeOf to determine the number of bytes used to represent the variable. Pass a type identifier to SizeOf to determine the number of bytes used to represent instances of that type. SizeOf is useful for determining the amount of memory to specify for the FillChar, Move, or GetMem procedures.
      

  2.   

    楼上的兄弟,这是Delphi的Help中的解释,我已经看过了。
    这段说明中并没有解释SizeOf(array)是如何获得数组的长度的呀!
    我觉得,在动态数组或者开放数组中,应该有一部分内存用来保存数组的长度才行。
      

  3.   

    应该有一部分内存用来保存数组的长度才行  
     这种说法是不对的!这并不名Delphi中的String,而在别的语言当中string也是没有这种功能的!
    我想一个数组应该有一个结束的标志
      

  4.   

    var a:array of char;
        p:pinteger;
    begin
      setlength(a,100);
      p:= pinteger(a);
      dec(p);
      edit1.text:=IntToStr(p^);end;
      

  5.   

    谢谢楼上的兄弟。
    如果我没有理解错的话,楼上兄弟的意思是,在这个数组的第一个元素的储存空间之前有4byte的内存空间,这4byte的内存空间中保存的就是数组长度。对吗?
    如果是这样,我还有一个问题:一个function的参数是开放数组,并没有setlength(a,100);这样的一个语句,那么这个开放数组的长度又是如何设定的呢?能在调用这个函数的程序中设定这个值吗?
      

  6.   

    “delphi精要“里有这方面的介绍
      

  7.   

    楼上的兄弟,这是Delphi的Help中的解释,我已经看过了。
    这段说明中并没有解释SizeOf(array)是如何获得数组的长度的呀!
    我觉得,在动态数组或者开放数组中,应该有一部分内存用来保存数组的长度才行。是有的 不然内存怎么能管理好呢 这就是所谓的 memory cookie.
      

  8.   

    楼主可能说错了吧?你其实是想知道
    length(array) 而不是sizeof(array)吧?后者编译器在编译时候,就判断变量类型,将结果,也就是立即数4编译进指令。前者是调用了SYSTEM。PAS单元的
    procedure _DynArrayLength;
    asm
    {       FUNCTION _DynArrayLength(const a: array of ...): Longint; }
    {     ->EAX     Pointer to array or nil                           }
    {     <-EAX     High bound of array + 1 or 0                      }        TEST    EAX,EAX
            JZ      @@skip
            MOV     EAX,[EAX-4]
    @@skip:
    end;
      

  9.   

    楼上的兄弟,我对Delphi不熟悉,我不知道length(array)和sizeof(array)有什么区别。
    我现在最想知道的一件是就是:
    Delphi中,如果一个函数的参数是开放数组,编译器最终生成的代码中是如何确定这个开放数组的长度的?
    因为我现在是用C来调用一个用Delphi写的DLL,这个Dll中有一个export函数的参数是开放数组,我如果直接将数组的首地址从C中传到Delphi函数中的话,Delphi函数不能正确的判断出数组的长度。
    所以我现在就想知道,在Delphi中开放数组的长度是如何确定的。
      

  10.   

    zjqyb(风清扬)不是已经回答过了吗?
    我列出来的代码也不是PASCAL,呵呵。。几句很简单的汇编而已。procedure _DynArrayLength;
    asm
            TEST    EAX,EAX           //EAX是传入参数
            JZ      @@skip
            MOV     EAX,[EAX-4]       //这儿EAX是RETURN值。
    end;它翻译成C语言差不多就是。。
    int _DynArrayLength(void * p)
    {
       if(p)
       {
          int* r=(int*)p;      //为了容易看,加了一个中间变量。
          return *(r-1);       //一个整型四字节,r-1意味着指针指向之前四个字节。
       }
       else
         return 0;}
      

  11.   

    TO: halfdream(哈欠) 
    zjqyb(风清扬)的回答我也大概看明白了。
    但是他的回答并没有完全消除我的疑惑。
    他举了一个动态数组的例子,在他的例子中,通过setlength(a,100);对这个动态数组进行了内存分配的任务。
    我现在想知道的是作为函数参数的开放数组。在使用开放数组的时候并没有setlength这样一个明显的内存分配的动作,而且如果在声明函数的参数时加上了var或者const关键字,函数和调用函数的程序对这个数组的操作是指向同一块内存区域的,在这种情况下,在函数中根本就没有再次为这个数组进行分配内存的动作。在这种情况下,Delphi是如何确定数组大小的呢?
      

  12.   

    动态数组必须使用SETLENGTH来分配内存的。
    为动态数组重分配内存也是用它。
    确定数组大小,就靠那开头四字节唯一确定,这是不用怀疑的。
      

  13.   

    如果参数是CONST,则调用方必须先SETLENGTH分配内存,被调用方不可再SETLENGTH改变它。
    如果参数是VAR,则调用方可先SETLENGTH分配内存,被调用方也可再SETLENGTH。。
    尽管都是传的指针,这是调用上一些约定,
    在C++语言编译器本身没有作这样的区分。。所以容易迷糊。
    -----------------------------------------------------------
    还有一点,DELPHI中动态数组是引用计数维护呵呵不过好象你这个DLL调用
    可以回避这些。。
      

  14.   

    我的问题已经解决了。
    在使用C来调用Delphi写的以开放数组为参数的Dll中的导出函数的时候,需要在数组之后再加一个整形的参数,将数组中最大的索引送过去。而这种方式是典型的C/C++中函数参数为数组的调用方式。例如,我这个Delphi的函数
    type  // Type of plugin's functions
      TFT0Command      = function (const Header : array of byte;
                                   const rwData : byte;
                                     var DATA   : array of byte;
                                         wasRW  : PWord) : LongInt;
                                                           stdcall;
    如果用C来调用的话,要这么写:
    typedef LONG (__stdcall *TFT0Command)(const BYTE[],
    INT,
    const BYTE, 
    BYTE[],
    INT,
    PWORD);我猜想在Delphi中,如果定义函数的时候加上了stdcall关键字,会使编译器生成的代码与C/C++生成代码保持结构上的一致。