这种C类型的等效Delphi结构是什么?

时间:2014-12-18 19:43:04

标签: delphi

我正在尝试在Delphi中使用基于c的DLL。在我介入所有其他功能之前,我以为我会尝试让其中一个功能正常工作,而且我受到了阻碍。这是C调用:

int FindCityCounty(char *zip, char cityname[28], char state[2], char countyname[25],
    char countynum[3]);

我对char cityname[25]的概念感到困惑。那是:

array[0..24] of Char/AnsiChar;

翻译这些结构的正确方法是什么?我所有的尝试都以乱七八糟的方式结束了。

更新

这是一个被调用函数的例子:

#include <stdio.h>
#include <Windows.h>
#include <srv.h>        /* for CALLBACK, HINSTANCE */
#include <direct.h>     /* for _getdrive and _getdcwd */

#define cpy_blank(word,len) memset(word,' ',len)
#define cpy_word strncpy

typedef int (CALLBACK* FindCityCounty)(
        char ZIP[5],char cityname[28],char state[2],char countyname[25],char countynum[3]);


void runCA(FindCityCounty pCA)
{
    char ZIP[5], cityname[28], state[2], countyname[25], countynum[3];
    int rc;

    printf("CorrectAddress C API Demonstration\n\n");
    printf("FindCityCounty() function call\n");
    printf("==================================\n");

    /* set input parameters */  
    cpy_word(ZIP,"10601",5);

    printf("Input ZIP code: %.5s\n", ZIP);

    /* call function */
    rc = pCA(ZIP, cityname, state, countyname, countynum);


    /*** Now output results ***/
    printf("Output city: %.28s\n",cityname);
    printf("Output state: %.2s\n",state);
    printf("Output county name: %.25s\n",countyname);
    printf("Output county number: %.3s\n",countynum);

    printf("\n\n");
    printf("=====================================\n");
    printf("(c) Intelligent Search Technology Ltd\n");
    printf("=====================================\n");
}

int main() 
{                 
    HINSTANCE hDLL;
    FindCityCounty pCA;

    /* Load DLL and get function location */
    hDLL = LoadLibrary("CorrectA.dll");
    pCA = (FindCityCounty)GetProcAddress(hDLL,"FindCityCounty");

    runCA(pCA);

    getch();
    return 0;
}

德尔福代码:

   unit CorrectAdressAPI;

interface

type
  TZip        = array[0..4] of AnsiChar;
  TCityName   = array[0..27] of AnsiChar;
  TState      = array[0..1] of AnsiChar;
  TCountyName = array[0..24] of AnsiChar;
  TCountyNum  = array[0..2] of AnsiChar;

  PCityName   = ^TCityName;
  PState      = ^TState;
  PCountyName = ^TCountyName;
  PCountyNum  = ^TCountyNum;


type
  TFindCityCounty = function(aZip: PAnsiChar;
                         var aCity: TCityName;
                         var aState: TState;
                         var aCounty: TCountyName;
                         var aCountyNum: TCountyNum): Integer; stdcall;

  function Load(const AFileName : string) : Boolean;
  function Unload : Boolean;

   function FindCityCounty(aZip: PANSIChar;
                         var aCity: TCityName;
                         var aState: TState;
                         var aCounty: TCountyName;
                         var aCountyNum: TCountyNum): Integer;


implementation

uses
  Winapi.Windows, dialogs, SysUtils;

var
  hDll : THandle;
  PFindCityCounty: TFindCityCounty;

function Load(const AFileName : string) : Boolean;
begin
  hDll := LoadLibrary(PChar(AFileName));
  Result := hDll <> 0;
  if Result then
  begin
    PFindCityCounty := GetProcAddress(hDLL, PAnsiChar('FindCityCounty'));
    Assert(Assigned(PFindCityCounty));

  end;
end;

function Unload : Boolean;
begin
  Result := (hDll <> 0) and FreeLibrary(hDll);
end;


function  FindCityCounty(aZip: PANSIChar;
                         var aCity: TCityName;
                         var aState: TState;
                         var aCounty: TCountyName;
                         var aCountyNum: TCountyNum): Integer;
begin
  Result := PFindCityCounty(aZip, aCity, aState, aCounty, aCountyNum);
end;



end.

2 个答案:

答案 0 :(得分:5)

正如梅森所说,数组作为参数传递给了C&#39;始终作为指向声明的数组类型的指针传递。但是,固定大小的字符数组不一定是空终止数组,因此使用 PChar PWideChar PANSIChar 可能是错。

要回答有关数组维度的具体问题,您似乎在示例中混淆了您的城市和县名,但基本上您是正确的。 C数组从0开始,因此C声明:

char name[N]

相当于Pascal:

name: array[0..N-1] of Char;

但是在数组中获取正确数量的元素并不是故事的结尾。您还需要小心确保正确声明了数组元素类型。

如果是char类型,您需要注意“Char&#39;是转换任何C代码时相应C环境的正确类型。在Delphi 1-2007&#39; Char&#39;是单字节ANSIChar。在德尔福2009年起,Char&#39;是一个2字节的WideChar。

在大多数(如果不是全部)C实现中,当然对于Windows,char是一个8位/ 1字节的值,因此 ANSIChar 最有可能是适当的Pascal类型,并确保任何Delphi版本上的1字节字符。

回到你的具体例子,涉及显式标注数组的事实,而不是显式(或隐式)空终止字符串,我认为在这个特定情况下为每个所需的数组类型声明类型可能是明智的,使用相应的指针类型:

type
  TCityName   = array[0..27] of ANSIChar;
  TState      = array[0..1] of ANSIChar;
  TCountyName = array[0..24] of ANSIChar;
  TCountyNum  = array[0..2] of ANSIChar;

  PCityName   = ^TCityName;
  PState      = ^TState;
  PCountyName = ^TCountyName;
  PCountyNum  = ^TCountyNum;

然后,您在C函数声明的Pascal版本中有两个选择。您可以明确地使用C代码生成的隐式指针类型&#39;:

 function FindCityCounty(aZip: PANSIChar; 
                         aCity: PCityName; 
                         aState: PState; 
                         aCounty: PCountyName; 
                         aCountyNum: PCountyNum): Integer; cdecl;

或者你可以自己使用数组类型,但是将它们声明为 var 参数,以使Pascal编译器通过引用传递它们,从而根据{{1}生成隐含指针代码:

C

在两种情况下效果基本相同,但我个人倾向于使用显式指针,因为使用 var 参数明显表明参数值可能/将会由函数调用修改,几乎肯定不是这样。

请注意, zip 参数已作为指向 function FindCityCounty(aZip: PANSIChar; var aCity: TCityName; var aState: TState; var aCounty: TCountyName; var aCountyNum: TCountyNum): Integer; cdecl; 代码中char的指针显式传递,因此在此处使用 PANSIChar 指针类型是在任何一种情况下都适用于此参数。

答案 1 :(得分:2)

如果这是一个结构,那你就是对的。但在C中,作为函数参数的数组总是指针。根据{{​​3}},即使在给定显式大小的数组参数中,情况仍然如此。因此,应根据需要将其翻译为PCharPAnsiChar