Дизайн API - выделяет вывод?

Действительно ли это - хорошая идея для API-функций C, чтобы выделить их вывод или сделать, чтобы пользователь указал буфер вывода? Например:

BOOL GetString(
    PWSTR *String
    );
...
PWSTR string;
GetString(&string);
Free(string);

по сравнению с

BOOL GetString(
    PWSTR Buffer,
    ULONG BufferSize,
    PULONG RequiredBufferSize
    );
...
// A lot more code than in the first case

Более конкретно я задаюсь вопросом, почему API Win32, прежде всего, использует второй случай (например, GetWindowText, LookupAccountSid). Если API-функция знает, насколько большой вывод, почему сделал пользователь, пытаются предположить выходной размер? Я не могу найти информацию о том, почему второй случай использовался бы.

Также: пример LookupAccountSid особенно плох. Внутренне это использует API LSA, который выделяет вывод для вызывающей стороны. Затем LookupAccountSid заставляет пользователя выделять буфер (и предположить корректный размер буфера), когда он мог просто возвратить вывод из LSA! Почему?

6
задан JaredPar 19 January 2010 в 01:02
поделиться

2 ответа

Вот что работает для меня:

<ContentControl Content="{Binding SomeBool}">
  <ContentControl.Resources>
    <DataTemplate x:Key="PinkTemplate">
      <TextBlock Text="{Binding}" Background="Pink" />
    </DataTemplate>
    <DataTemplate x:Key="LimeTemplate">
      <TextBlock Text="{Binding}" Background="Lime" />
    </DataTemplate>
  </ContentControl.Resources>
  <ContentControl.ContentTemplate>
    <DataTemplate>
      <ContentControl Name="cc"
                      Content="{Binding}"
                      ContentTemplate="{StaticResource PinkTemplate}" />
      <DataTemplate.Triggers>
        <DataTrigger Binding="{Binding}" Value="True">
          <Setter TargetName="cc" 
                  Property="ContentTemplate"
                  Value="{StaticResource LimeTemplate}" />
        </DataTrigger>
      </DataTemplate.Triggers>
    </DataTemplate>
  </ContentControl.ContentTemplate>
</ContentControl>

Обратите внимание, что мой DataTemplate является другим ContentControl, который позволяет моим DataTemplate.Triggers работать с ContentTemplate этого (вложенного) ContentControl.

-121--3787322-

В JavaScript результат метода может зависеть от размещения фигурных скобок стиля. Это стиль K & R , где фигурные скобки помещаются сразу после подписи метода и после оператора возврата:

var foo = function() {
  return {
    key: 'value'
  };
}

foo() // returns an object here

Теперь, если я форматирую этот код в стиль Оллмана , где фигурные скобки всегда размещаются на новой строке, результат отличается:

var foo = function()
{
  return
  {
    key: 'value'
  };
}

foo() // returns undefined here

Как? В JavaScript язык автоматически помещает точку с запятой в конце каждой строки, если вы не сделаете это самостоятельно. Итак, в последнем фрагменте кода произошло следующее:

var foo = function()
{
  return; // here's actually a semicolon, automatically set by JavaScript!
  {
    key: 'value'
  };
}

Так что если вызвать foo () , первым оператором в методе будет оператор return, который вернет undefined и не будет выполнять другие следующие операторы.

-121--1760481-

API-интерфейс Win32 не выполняет предварительное выделение буферов, поскольку он хочет предоставить вызывающему коду выбор способа предоставления буфера. Это позволяет им предоставлять стеки и различные буферы на основе кучи. Есть несколько мест, где максимальный размер буфера известен раньше времени и разработчики хотят простоты использования буфера на основе стека.

Файловая система является лучшим примером, поскольку пути не будут превышать MAX _ PATH . Поэтому вместо того, чтобы выделять + бесплатно. Разработчик просто объявляет буфер на основе стека.

Преимущество выделения памяти C API заключается в том, что это упрощает образец вызова. Недостатком образца Win32 является то, что в большинстве случаев вызов API выполняется дважды. Первый раз для определения размера буфера, затем второй раз с буфером соответствующего размера. С выделенным буфером API необходим только один вызов.

Однако недостатком является то, что вы отбираете выбор распределения у вызывающего абонента. Кроме того, вы должны сообщить свой выбор, чтобы они правильно освободили API (например, окна могут распределяться из нескольких различных мест).

6
ответ дан 17 December 2019 в 00:09
поделиться

Второй подход имеет некоторые преимущества, такие как

  • , он позволяет звонящим управлять сроком службы памяти
  • , он позволяет азатукам повторно использовать выделенную память для разных вызовов, которые следуют на той же модели
  • , он позволяет абоненты решать, какие Буфер для обеспечения E.G. стек или куча.
1
ответ дан 17 December 2019 в 00:09
поделиться
Другие вопросы по тегам:

Похожие вопросы: