Previous Up Next Guide

Low Level Access to TWAIN

You may require access to a TWAIN API function which is not implemented as a method in the SourceManager or the Source modules. When this occurs, you have the option of using the low-level interface to the twainmodule.

The TWAIN interface is a set of calls on a single method in both the SourceManager and the Source objects (called DSM_Entry). You can perform any of the TWAIN functions using this method.

The format of this call is:
   SourceManager.DSM_Entry(DataGroup, DataItemId, MessageId, Data)

DataGroup This indicates the data group, within which the data item id is defined. It is one of the twain.DG_ constants.
DataItemId This defines the type of the data passed. It is one of the twain.DAT_ constants.
MessageId This defines the operation to be performed. It is one of the twain.MSG_ constants
Data This is the data for the operation. It is a python string, which must be preallocated to the correct length.

Operation Triplets

The DataGroup, DataItemId and MessageId are defined in the TWAIN specification for each operation. These are known as the operation triplets, and are documented in chapter 7. For example, see page 182 for the DG_CONTROL/DAT_IDENTITY/MSG_GETFIRST triplet. This operation returns the identity structure for the first available TWAIN source, in a structure of format TW_IDENTITY. Our Python call is as follows:

		 from twain import *
		 SM = SourceManager(0L)
		 ...
		 SM.DSM_Entry(DG_CONTROL, DAT_IDENTITY, MSG_GETFIRST, Identity)

Native C Structures

Python provides a module called struct, for manipulating C language data structures. We must use this module for creating the structures to be passed into and interpreting the structures returned from the DSM_Entry routine. All of the structures passed to DSM_Entry are defined in the twain.h C header file, which is part of the TWAIN Toolkit, and can be downloaded from www.twain.org.

The Identity object in the code snippet above is of type TW_IDENTITY. This structure is defined as follows:

 typedef unsigned short TW_UINT16;
 typedef unsigned long  TW_UINT32;
 typedef char    TW_STR32[34];

 typedef struct {
   TW_UINT16  MajorNum;  /* Major revision number of the software. */
   TW_UINT16  MinorNum;  /* Incremental revision number of the software. */
   TW_UINT16  Language;  /* e.g. TWLG_SWISSFRENCH */
   TW_UINT16  Country;   /* e.g. TWCY_SWITZERLAND */
   TW_STR32   Info;      /* e.g. "1.0b3 Beta release" */
 } TW_VERSION;

 typedef struct {
    TW_UINT32  Id;              /* Unique number.  In Windows, application hWnd      */
    TW_VERSION Version;         /* Identifies the piece of code              */
    TW_UINT16  ProtocolMajor;   /* Application and DS must set to TWON_PROTOCOLMAJOR */
    TW_UINT16  ProtocolMinor;   /* Application and DS must set to TWON_PROTOCOLMINOR */
    TW_UINT32  SupportedGroups; /* Bit field OR combination of DG_ constants */
    TW_STR32   Manufacturer;    /* Manufacturer name, e.g. "Hewlett-Packard" */
    TW_STR32   ProductFamily;   /* Product family name, e.g. "ScanJet"       */
    TW_STR32   ProductName;     /* Product name, e.g. "ScanJet Plus"         */
 } TW_IDENTITY;

The TW_VERSION structure is of size 42 bytes (2 + 2 + 2 + 2 + 34). The TW_IDENTITY structure is of size 156 bytes(4 + 42 + 2 + 2 + 4 + 34 + 34 + 34).

Note: The TWAIN standard pack values to two byte boundaries. In normal C structures there is a padding of two bytes before SupportedGroups. However, in the TWAIN interface there is none.

To create a string of the correct length to be passed into the DSM_Entry method, we use the struct.pack() method.

		 Identity = struct.pack("156s", "")
To extract data out of the result, we can use the struct module. However, just to extract a simple string, when we know the offset, it is easy to use Python standard functionality.

		 ProductName = Identity[122:]
The ProductName is a 'C' language string. This string is, by convention, terminated by a NULL character. We have to truncate the C language string at this NULL character to get a Python Native format string.

		 iOffset = ProductName.find('\0')
		 if iOffset != -1:
		     ProductName = ProductName[:iOffset]
Our simple example is complete as follows:
		 from twain import *
		 SM = SourceManager(0L)
		 Identity = struct.pack("156s", "")
		 SM.DSM_Entry(DG_CONTROL, DAT_IDENTITY, MSG_GETFIRST, Identity)
		 ProductName = Identity[122:]
		 iOffset = ProductName.find('\0')
		 if iOffset != -1:
		     ProductName = ProductName[:iOffset]
		 print "The data source name is: ", ProductName


Previous Up Next Guide