dt_Handle reaction, container, molecule1, moleculeX;
  dt_String csmi, asmi;
  dt_Integer clen, alen;

  /* Read SMILES in. */
  reaction = dt_smilin(13, "O>>[OH-].[H+]");

  /* Write canonical form. */ 
  csmi = dt_cansmiles(&clen, reaction, 0);
  /* Write abitrary form. */ 
  asmi = dt_arbsmiles(&alen, reaction, 0);

  printf("Canonical form is %.*s and arbitrary form is %.*s.\n",
         clen, csmi, alen, asmi);

  /* Stream the reaction. */
  container = dt_stream(reaction, TYP_MOLECULE);  

  /* The next item gives the first molecule. */
  molecule1 = dt_next(container);
  if (dt_getrole(molecule1, reaction) == DX_ROLE_REACTANT)
    printf("The molecule role is reactant.\n");

  /* The next item gives the second molecule */
  moleculeX = dt_next(container);
  if (dt_getrole(moleculeX, reaction) == DX_ROLE_PRODUCT)
    printf("The molecule role is product.\n");

  /* The next item is the NULL object. */
  moleculeX = dt_next(container);
  if (NULL_OB == moleculeX)
    printf("The NULL object is next.\n");

  /* A reset and next operation gives the first molecule again. */
  moleculeX = dt_next(container);
  if (moleculeX == molecule1)
    printf("Reset is like rewind.\n");

  /* Each molecule refers to the reaction as its parent. */
  if (dt_parent(molecule1) == reaction)
    printf("You can access the reaction through the molecule.\n");
  /* The atom stream is invalid when an atom is added to the reaction. */
dt_addcomponent(reaction, molecule1, DX_ROLE_AGENT);
if (dt_invalid(container) == 1)
printf("The container is invalid.\n");

Canonical form is O>>[H+].[OH-] and arbitrary form is O>>[OH-].[H+].
The molecule role is reactant.
The molecule role is product.
The NULL object is next.
Reset is like rewind.
You can access the reaction through the molecule.
The container is invalid.