Pascal Object: как сделать типизированное предварительное объявление?

Я перевожу великолепный заголовок fmod C на Pascal и застрял из-за предварительного объявления. Если я объявляю функцию перед типом, возникает ошибка "FMOD_CODEC_STATE: неизвестно", а если я объявляю FMOD_CODEC_STATE перед функцией, возникает ошибка "FMOD_CODEC_METADATACALLBACK: неизвестно" Любая идея, как я могу решить эту проблему? Большое спасибо !

type
  FMOD_CODEC_STATE = Record
    numsubsounds: Integer;
    waveformat: array[0..0] of FMOD_CODEC_WAVEFORMAT;
    plugindata: Pointer;

    filehandle: Pointer;
    filesize: Cardinal;
    fileread: FMOD_FILE_READCALLBACK;
    fileseek: FMOD_FILE_SEEKCALLBACK;
    metadata: FMOD_CODEC_METADATACALLBACK;
  end;
  FMOD_CODEC_METADATACALLBACK    = function (codec_state: FMOD_CODEC_STATE; tagtype: FMOD_TAGTYPE; name: PChar; data: Pointer; datalen: Cardinal; datatype: FMOD_TAGDATATYPE; unique: Integer):FMOD_RESULT;

person Olivier Pons    schedule 16.05.2011    source источник
comment
Плохой пример кода - здесь нет необходимости в предварительном объявлении, проблема где-то раньше.   -  person kludg    schedule 16.05.2011
comment
Ты прав. Функция была неправильной. Я исправил свой вопрос. Спасибо за комментарий.   -  person Olivier Pons    schedule 16.05.2011
comment
Кстати, я не уверен, что array[0..0] делает то, что вы думаете.   -  person Blindy    schedule 17.05.2011
comment
@ Блинди прав. Код C объявляет waveformat как указатель на FMOD_CODEC_WAVEFORMAT, и вы должны сделать то же самое. Я обновил свой ответ, чтобы отразить это.   -  person Rob Kennedy    schedule 17.05.2011


Ответы (2)


Запись не нужно передавать по значению. На самом деле исходный код на языке C все равно не передает его по значению. Он передается по ссылке с указателем. Объявите указатель, затем функцию, а затем запись:

type
  PFMOD_CODEC_STATE = ^FMOD_CODEC_STATE;
  FMOD_CODEC_METADATACALLBACK = function (codec_state: PFMOD_CODEC_STATE; tagtype: FMOD_TAGTYPE; name: PChar; data: Pointer; datalen: Cardinal; datatype: FMOD_TAGDATATYPE; unique: Integer):FMOD_RESULT;
  FMOD_CODEC_STATE = Record
    numsubsounds: Integer;
    waveformat: PFMOD_CODEC_WAVEFORMAT;
    plugindata: Pointer;

    filehandle: Pointer;
    filesize: Cardinal;
    fileread: FMOD_FILE_READCALLBACK;
    fileseek: FMOD_FILE_SEEKCALLBACK;
    metadata: FMOD_CODEC_METADATACALLBACK;
  end;

Да, вам разрешено объявить указатель на что-то до того, как вы объявите то, на что он указывает. Однако вам не разрешено пересылать и объявлять записи, поэтому приведенный выше порядок является единственно возможным порядком для этих трех объявлений.

person Rob Kennedy    schedule 16.05.2011
comment
Я обнаружил странное поведение: если я копирую/вставляю ваш код, он работает. Если я снова добавлю тип ключевого слова непосредственно перед FMOD_CODEC_STATE = Record, возникнет ошибка: идентификатор не объявлен: FMOD_CODEC_STATE (Delphi 2007). Такое поведение нормально? - person Olivier Pons; 16.05.2011
comment
Да, это нормально. Все предварительно объявленные типы должны быть разрешены до конца раздела текущего типа. Вы также увидите это, если вы предварительно объявите класс с TFoo = class; — вам нужно полностью объявить TFoo, прежде чем объявлять любые идентификаторы, не относящиеся к типу (например, функции, переменные или константы). - person Rob Kennedy; 16.05.2011
comment
Большое спасибо за ваш ответ. - person Olivier Pons; 17.05.2011

Паскаль имеет автоматическое объявление прямого типа для классов указателей, и я предполагаю, что эта функция действительно принимает. Таким образом, простое изменение ваших объявлений на что-то вроде этого (предупреждение, я не использовал паскаль более 12 лет) должно работать:

type
  PFMOD_CODEC_STATE=^FMOD_CODEC_STATE;
  FMOD_CODEC_METADATACALLBACK    = function (codec_state: PFMOD_CODEC_STATE; tagtype: FMOD_TAGTYPE; name: PChar; data: Pointer; datalen: Cardinal; datatype: FMOD_TAGDATATYPE; unique: Integer):FMOD_RESULT;

  FMOD_CODEC_STATE = Record
    numsubsounds: Integer;
    waveformat: array[0..0] of FMOD_CODEC_WAVEFORMAT;
    plugindata: Pointer;

    filehandle: Pointer;
    filesize: Cardinal;
    fileread: FMOD_FILE_READCALLBACK;
    fileseek: FMOD_FILE_SEEKCALLBACK;
    metadata: FMOD_CODEC_METADATACALLBACK;
  end;
person Blindy    schedule 16.05.2011
comment
Большое спасибо за ваш ответ, вы ответили как Роб Кеннеди... но он был быстрее ;) Все равно спасибо! - person Olivier Pons; 17.05.2011