2010-01-19 9 views
5

Ist es eine gute Idee für C-API-Funktionen, ihre Ausgabe zuzuordnen, oder den Benutzer den Ausgabepuffer anzugeben? Zum Beispiel:API-Design - Ausgabe zuweisen?

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

vs

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

Insbesondere frage ich mich, warum in erster Linie des Win32-API, um den zweiten Fall verwendet (z GetWindowText, LookupAccountSid). Wenn eine API-Funktion weiß, wie groß die Ausgabe ist, warum versucht der Benutzer, die Ausgabegröße zu erraten? Ich kann keine Informationen darüber finden, warum der zweite Fall verwendet wird.

Auch: das Beispiel LookupAccountSid ist besonders schlecht. Intern verwendet es die LSA-API, die die Ausgabe für den Aufrufer zuweist. Dann ruft LookupAccountSid den Benutzer auf, um einen Puffer zuzuweisen (und die richtige Puffergröße zu erraten), wenn er nur die Ausgabe von LSA zurückgeben könnte! Warum?

+0

Kommt drauf an. Beide Idiome werden verwendet. Beide haben Vor- und Nachteile. –

+0

Was sind die Vorteile des zweiten Falles, neben der Möglichkeit, einen Stack-basierten Puffer zu verwenden? – wj32

+0

Es ermöglicht dem Anrufer, seine Wahl der Zuweisungsliste zu verwenden. Wenn Sie Speicher reservieren und es dem Anrufer überlassen, ihn freizugeben, muss der Anrufer den entsprechenden Deallocater verwenden - was möglicherweise nicht seine Präferenz ist. Durch das Füllen eines vom Aufrufer bereitgestellten Puffers können sie einen geeigneten Allokierer für ihre Zwecke auswählen, anstatt sich auf den zu verlassen, den die API ausgewählt hat. –

Antwort

5

Die Win32-API reserviert Puffer nicht vorab, da sie dem aufrufenden Code die Möglichkeit geben möchte, den Puffer bereitzustellen. Es ermöglicht ihnen, Stapel und eine Vielzahl von Heap-basierten Puffern bereitzustellen. Es gibt mehrere Stellen, an denen die maximale Größe des Puffers im Voraus bekannt ist, und Entwickler möchten die Einfachheit der Verwendung eines stackbasierten Puffers. Das Dateisystem ist das beste Beispiel, da die Pfade MAX_PATH nicht überschreiten. Also anstatt zuzuteilen + frei. Der Entwickler deklariert einfach einen stackbasierten Puffer.

Der Vorteil der Speicherzuweisung durch die C-API ist, dass das Aufrufmuster vereinfacht wird. Der Nachteil des Win32-Pattern besteht darin, dass Sie die API am häufigsten zweimal aufrufen. Das erste Mal, um die Größe des Puffers zu bestimmen, dann das zweite Mal mit einem Puffer von geeigneter Größe. Mit einem API-zugewiesenen Puffer wird nur ein Anruf benötigt.

Der Nachteil ist, dass Sie die Auswahl der Zuweisung vom Anrufer wegnehmen. Zusätzlich müssen Sie Ihre Wahl mitteilen, damit sie die API richtig freigeben können (Fenster können z. B. von mehreren verschiedenen Orten aus zugeordnet werden).

+3

Ich würde anmerken, dass es so einfach ist, die zwei Anrufe plus Zuteilung in Ihrer eigenen Funktion zu verpacken, dass das Vereinfachen des Anrufmusters eine sehr geringe Sorge ist. Wenn Sie nur eine Version der API anbieten, muss diese flexibler sein. –

1

Der zweite Ansatz hat einige Vorteile wie

  • Damit können Anrufer die Lebensdauer von Speicherzuordnungen verwalten
  • Es Anrufer für verschiedene Anrufe zugewiesenen Speicher wieder verwenden können, die folgen, dass gleiche Muster
  • Es Anrufer können zu entscheiden, welcher Puffer z Stapel oder Haufen.