Как определить между Pointer и динамическим массивом "C ++ to Delphi" - PullRequest
1 голос
/ 10 ноября 2010

Мой вопрос, когда я говорю

char **szWords; IS szWords: PPAnsiChar;
char **szWords; IS szWords: array of array of AnsiChar;

также

pfloat   *pScoreAcc; IS ScoreAcc: PSingle; 
pfloat   *pScoreAcc; IS ScoreAcc: array of Single; 

они одинаковые? В моем случае массив массив AnsiChar; работает над моим проектом, а PPAnsiChar - нет. Я все еще хочу знать причину между "P" и "массивом"

Ответы [ 2 ]

2 голосов
/ 10 ноября 2010

Имейте в виду, что в Delphi динамический массив не совпадает со статическим массивом.

Статический массив определяется так:

type
 TIntegerArray10 = array[0..10] of integer;
 PIntegerArray10 = ^TIntegerArray10;

А динамический массив определяется как:

type
  TIntegerDynamicArray = array of integer;

Но память динамического массива выделяется в куче Delphi, используя функцию SetLength (). Вы можете получить доступ к самой верхней границе с помощью функций Length () или High ().

Затем динамический массив может быть преобразован обратно в статический массив с помощью функции pointer ():

var Dyn: TIntegerDynamicArray;
    i: integer;
begin
  SetLength(Dyn,11); // will create Dyn[0] to Dyn[10]
  for i := 0 to high(Dyn) do begin // same as  for i := 0 to length(Dyn)-1 do
    Dyn[i] := i;
    assert(PIntegerArray(pointer(Dyn))^[i]=i);
  end;
end;

char * (указатели char) в Delphi можно обрабатывать как массив char, но это не самый простой способ сделать это, потому что вам придется получать и освобождать память под рукой. Вы можете использовать тип AnsiString, а затем привести его в качестве указателя: он вернет PAnsiChar.

Таким образом, для массива AnsiString каждый элемент массива (доступный для []) будет PAnsiChar, а указатель на весь массив AnsiString будет PPAnsiChar, то есть char **

var Dyn: array of AnsiString;
begin
  SetLength(Dyn,19);
  for i := 0 to 19 do
    Dyn[i] := IntToStr(i);
  // now pointer(Dyn) can be mapped to PPAnsiChar or char **
end;

Все это полезно для создания некоторого контента из Delphi, а затем использовать его в своем коде C.

Напротив, то есть, используя C, сгенерированный char ** в Delphi, вы должны использовать указатели на статические массивы, а не указатель на динамические массивы. Насколько я помню, структуры char ** обычно заканчиваются на NULL для обозначения конца массива.

Вот что я бы порекомендовал использовать для преобразования массива C char ** в настоящий динамический массив Delphi (для адаптации к вашей цели):

type
  TAnsiStringDynArray = array of AnsiString;
  TPAnsiCharArray = array[0..maxInt div 4-1] of PAnsiChar;
  PPAnsiCharArray = ^TPAnsiCharArray;

procedure ConvertCToDelphi(inArray: PPAnsiCharArray; var outDynArray: TAnsiStringDynArray);
var i, n: integer;
begin
  n := 0;
  if inArray<>nil then
    while inArray[n]<>nil do
      inc(n);
  SetLength(outDynArray,n);
  for i := 0 to n-1 do
    outDynArray[i] := AnsiString(InArray[n]); // explicit typing to make Delphi 2009 happy
end;

Вы можете использовать PPAnsiChar, если вы просто хотите перечислить массив символов **:

procedure Test(FromC: PPAnsiChar);
begin
  if FromC<>nil then
    while FromC^<>nil do begin
      writeln('Item value is ',FromC^); // Delphi will map FromC^ PAnsiChar into a string
      inc(FromC); // this will go to the next PAnsiChar in the array
    end;
end;
0 голосов
/ 10 ноября 2010

Это просто разница между указателем и массивом.

Это более точно:

char **szWords; IS szWords: PPAnsiChar;
char szWords[][]; IS szWords: array of array of AnsiChar;
...