понедельник, 9 мая 2011 г.

Вызов функции - это нечто большее, чем просто заставить типы параметров совпасть

Это перевод There's more to calling a function than just getting the types to match. Автор: Реймонд Чен.

Вот классическая ошибка новичка. Предположим, вы хотите вызвать функцию, скажем CreateFontIndirectEx, прототип которой:
function CreateFontIndirectEx(const p1: PEnumLogFontExDV): HFONT; stdcall;
Вы пишите:
procedure Sample;
begin
  Font := CreateFontIndirectEx(???);
  ...
end;
А что же нам написать вместо вопросительных знаков? Ну, компилятор говорит, что он там хочет видеть PEnumLogFontExDVW - так что давайте дадим ему, что он хочет.
procedure Sample;
begin
  Font := CreateFontIndirectEx(PEnumLogFontExDVW(nil));
  ...
end;

Хм, но так - вылетает. О, постойте-ка, может нам удасться передать его так:
procedure Sample;
var
  P: PEnumLogFontExDVW; 
begin
  Font := CreateFontIndirectEx(P);
  ...
end;
Хм, всё равно вылетает. А, я понял: ведь переменная неинициализирована.
procedure Sample;
var
  P: PEnumLogFontExDVW; 
begin
  P := nil;
  Font := CreateFontIndirectEx(P);
  ...
end;
Нет, всё ещё вылетает. Постойте-ка, я знаю, где можно взять PEnumLogFontExDVW.
procedure Sample;
var
  P: PEnumLogFontExDVW; 
begin
  New(P);
  Font := CreateFontIndirectEx(P);
  ...
end;
Ну наконец-то работает! OK, переходим к следующей проблеме...

Конечно же, просто потому, что прототип функции говорит вам, что параметр должен иметь тип PEnumLogFontExDVW - вовсе не означает, что вам нужно использовать переменную этого типа. Вам нужно только выражение типа PEnumLogFontExDVW:
procedure Sample;
var
  P: TEnumLogFontExDV; 
begin
  // ... <- заполнение P
  Font := CreateFontIndirectEx(@P);
  ...
end;
Зачем я это говорю?

Нет, я не пытаюсь над вами насмехаться. Я пытаюсь заставить думать вас как новичок. Иногда при чтении куска чужого кода вы можете находить совершенно странное, вроде фрагмента выше с выделением памяти под запись (иногда - под простой Integer!). Когда вы видите это (к примеру, в поисках утечки памяти в этом коде), то не вырывайте из головы волосы, пытаясь увидеть какой-то скрытый смысл в таком окружном пути выполненния простейшей задачи. Если вы сможете думать как новичок, то вы просто распознаете код как классическую ошибку новичка, исправите её, и продолжите спокойно жить дальше.

Комментариев нет:

Отправить комментарий

Можно использовать некоторые HTML-теги, например:

<b>Жирный</b>
<i>Курсив</i>
<a href="http://www.example.com/">Ссылка</a>

Вам необязательно регистрироваться для комментирования - для этого просто выберите из списка "Анонимный" (для анонимного комментария) или "Имя/URL" (для указания вашего имени и ссылки на сайт). Все прочие варианты потребуют от вас входа в вашу учётку (поддерживается OpenID).

Пожалуйста, по возможности используйте "Имя/URL" вместо "Анонимный". URL можно просто не указывать.

Ваше сообщение может быть помечено как спам спам-фильтром - не волнуйтесь, оно появится после проверки администратором.