Unfortunately, there is no documentation on how to create buffers - just what you can get from the examples.
In general, after memory is allocated you are responsible for realeasing it. There are many exceptions to this, but for most "buffers", you need to explicitly release the memory. The safest way to accomplish that is to use a try..finally block.
Overview
Most of the time you either pass the buffer (actually, its address) and its size, or you pass a buffer of a known (specified) size.
Many buffers are coded as records, arrays, or arrays of records others are just pointers to a memory block.
PChar
This is adapted from the Delphi GetMem example
procedure GetMem(var P: Pointer; Size: Integer); procedure FreeMem(var P: Pointer[; Size: Integer]); var Buffer: PChar; begin Size := WindowsAPI_Cmd(); // many of these commands return the needed value GetMem(Buffer, Size); try WindowsAPI_Cmd(Buffer, Size); finally FreeMem(Buffer); end; end;
Example 2
// This is the declaration for a method that needs three buffers // Interestingly, the help does NOT say how large the buffers should be // or that they need to be allocated before the method is called procedure GetPrinter (ADevice, ADriver, APort: PChar; var ADeviceMode: THandle); var Device : array[0..255] of char; Driver : array[0..255] of char; Port : array[0..255] of char; hDMode : THandle; PDMode : PDEVMODE; begin Printer.GetPrinter(Device, Driver, Port, hDMode);In this case, data is returned via
StrCopy(ADevice, PChar(Device));which copies one null terminated PChar string to another buffer without performing any length checking. The destination buffer must have room for at least StrLen(Source)+1 characters.
Example 3
var Device, Driver, Port : array[0..255] of char; hDMode : THandle; PDMode : PDEVMODE; begin Printer.GetPrinter(Device, Driver, Port, hDMode);
GlobalAlloc
var buffer4 : pchar; PageBuff: array[0..64] of char; // 1 larger than necessary hBuffer : THandle; begin hBuffer := GlobalAlloc(GMEM_MOVEABLE and GMEM_ZEROINIT, 64 * cnt); buffer4 := GlobalLock (hBuffer); GlobalUnlock(hBuffer); GlobalFree(hBuffer); end;
AllocMem
This example is based on code in Forms.pas
function AllocMem(Size: Cardinal): Pointer; procedure FreeMem(var P: Pointer[; Size: Integer]); var Info : PBitmapInfo; InfoSize : DWORD; Image : Pointer; ImageSize : DWORD; Bits : HBITMAP; begin Bits := bmp.Handle; GetDIBSizes(Bits, InfoSize, ImageSize); Info := AllocMem(InfoSize); try Image := AllocMem(ImageSize); try GetDIB(Bits, 0, Info^, Image^); StretchDIBits(Printer.Canvas.Handle, 20, 30, bmp.Width, bmp.Height, 0, 0, bmp.Width, bmp.Height, Image, Info^, DIB_RGB_COLORS, SRCCOPY); finally FreeMem(Image, ImageSize); end; finally FreeMem(Info, InfoSize); end; end;
Summary
procedure New(var P: Pointer); procedure GetMem(var P: Pointer; Size: Integer); function AllocMem(Size: Cardinal): Pointer; procedure FreeMem(var P: Pointer[; Size: Integer]);These are Windows API calls - they work with handles
HGLOBAL GlobalAlloc( UINT uFlags, // object allocation attributes DWORD dwBytes // number of bytes to allocate ); HGLOBAL GlobalFree( HGLOBAL hMem // handle to the global memory object );When uFlags contains GMEM_MOVEABLE, use GlobalLock to convert the handle to an address. Be sure to call GlobalUnlock before calling GlobalFree.
LPVOID GlobalLock( HGLOBAL hMem // address of the global memory object ); BOOL GlobalUnlock( HGLOBAL hMem // handle to the global memory object );Author: Robert Clemenzi - clemenzi@cpcug.org