Navigation:  Programming Cookbook > External Interfacing > External Field Types >

Pointer Fields

Previous pageReturn to chapter overviewNext page

It is common to find pointers (addresses) embedded in structures where we are not particularly interested in the pointer itself, but the object at which it is pointing. We represent these with PointerField instances. When instantiating pointer fields we generally need to specify the type of object that the pointer is expected to be pointing at, so that the structure can de-reference the pointer and return a Smalltalk object of the correct type (use the scalar field LPVOIDField to avoid having pointer de-referenced automatically). A common example is pointers to C strings; DOCINFO has a few of these:

defineFields

  "Define the fields of the Win32 DOCINFO structure.

  typedef struct {     // di

      int cbSize;

      LPCTSTR lpszDocName;

      LPCTSTR lpszOutput;

      LPCTSTR lpszDatatype; // Windows 95 only; ignored on Windows NT

      DWORD    fwType; // Windows 95 only; ignored on Windows NT

      } DOCINFO;"

  self

      defineField: #cbSize type: DWORDField writeOnly;

      defineField: #lpszDocName type: (PointerField to: String) beWriteOnly;

      defineField: #lpszOutput type: (PointerField to: String) beWriteOnly;

      defineField: #lpszDatatype type: (PointerField to: String) beWriteOnly;

      defineField: #fwType type: DWORDField writeOnly

 

Pointers to Structures

Less commonly we may need to define a pointer field to another structure type, and we can use PointerFields to do this too. An example can be found in the CHOOSEFONT, where the lpLogFont field is described as a PointerField to LOGFONT:

defineFields

  "Define the fields of the Win32 CHOOSEFONT structure.

  This structure is used only for communication with the font dialog,

  so we don't compile it.

      CHOOSEFONT defineTemplate

  typedef struct    {

      DWORD lStructSize;

      HWND hwndOwner;

      HDC hDC;

      LPLOGFONT lpLogFont;

      INT iPointSize;

      ...

  } CHOOSEFONT;"

  self

      defineField: #lStructSize type: DWORDField writeOnly;

      defineField: #hwndOwner type: DWORDField writeOnly;

      defineField: #hDC type: DWORDField writeOnly;

      defineField: #lpLogFont type: (PointerField to: LOGFONT);

      defineField: #iPointSize type: DWORDField readOnly;

      ...

If storing a pointer to a Smalltalk object into a structure one must be careful to ensure that the lifetime of the object corresponds to the time span over which the structure is used, and this may entail maintaining a reference to the Smalltalk object in an instance variable added to the ExternalStructure for that purpose. For example, the TV_ITEM class includes a field, pszText, which is a pointer to string data. When text is set into a TV_ITEM via the #text: message, the pszText pointer field is set to point to the bytes of the String, and the string is saved into the text instance variable of TV_ITEM.

Even more care over storing pointers to Smalltalk objects into structures passed to external functions is necessary if those function capture the pointer for future use (e.g. the binding of columns to buffers in ODBC). The Dolphin object memory may move objects around during garbage collection, so one cannot normally rely on objects having a fixed address. This has no impact on Smalltalk, because it does not rely on direct memory addresses, but it may upset external subsystems.

To simplify interfacing with external systems that capture addresses, the Dolphin VM includes a special memory allocator for byte objects that allocates from a conventional heap. Objects allocated from the "fixed" heap, are guaranteed to maintain the same address for their lifetime (or that of the session if shorter). ExternalStructures are, by default, allocated from the fixed heap, but one can allocate other byte objects, such as ByteArrays, from the heap using the #newFixed: message.

Pointers to Arrays

Structures quite frequently contain pointers to arrays that are held in another area of storage. Dolphin defines 4 field types to represent these, all of which are used in conjuction with External Arrays of one sort or another. These fields can be quite complicated to define, so refer to existing examples in the image for guidance.

ExternalField type

Description

ArrayPointerField

For representing fields which point to fixed length arrays of scalars (value types), for example arrays of integers. Must be used in conjuction with an ExternalArray type such as DWORDArray. For an example see CHOOSECOLOR class>>defineFields

StructureArrayPointerField

For representing fields which point to arrays of structures. Used in conjunction with StructureArray. There are no examples in the base image, but usage is similar to VariableStructureArrayPointerField, except that a fixed length is specified rather than the name of the length field.

PointerArrayPointerField

For representing fields which point to arrays of pointers. Used in conjunction with PointerArray. There are no examples in the base image (but see PointerArrayField, the usage of which is similar).

VariableStructureArrayPointerField

For representing fields which point to variable length arrays of structures, i.e. where one of the other fields in the structure dynamically specifies the size of the array. Used in conjunction with StructureArray. For an example see DISPPARAMS clalss>>defineFields