https://wiki.tdcommunity.net/index.ph ... Ex_library
When implementing external function definitions, it is important to adopt the correct datatypes for return values and parameters.
The datatype definition instructs TD to handle the data according to the intended bit/byte sizes and sign.
Incorrect definitions can lead to datatype casting which transforms/cast the data in unexpected ways.
The general rule is that you try to match the datatype definition exactly to the intended definition.
For example, when a parameter expects an
INTdatatype, the TD definition should be set to
Number: INT, obviously.
Though you might come into doubt what to choose when the datatype is not explicitly one of the base datatypes, like
For example, Windows API functions could define other types, which are aliases or placeholders for the really underlying datatypes.
HBITMAP, which is a Windows API datatype. Team Developer does not have the option to set
HBITMAPfor exported functions.
Reading the documentation of the function should indicate which base type it represents.
Even then, in most cases it is searching all kinds of docs to find out which TD datatype to take.
Personally, I still struggle to get the correct datatype, which takes time and in some cases, I accidentally use the wrong one.
Therefore, I decided to make it a bit easier. I tried to get all base types and related Windows API datatypes into a list for future reference.
The list offers this info per datatype:
- The TD datatype(s) to use
- The size in bits/bytes of the type
- The maximum value range of the type (e.g. 0..255)
- The sign (+/-)
The way to use it is: look up the API datatype in the list and determine which TD external function datatype to use.
In addition, which CStruct functions to use to read/write the datatypes from/to buffers.
Here you can access the external function datatype reference (PDF and Excel format):
https://samples.tdcommunity.net/index ... Reference/
Extended CStruct functions (CStructEx library)
Developers in TD are able to access (memory) buffers to read or write data directly.
This is done using the CStruct library (cstructl.apl) which contains several functions for a limited set of API datatypes.
For instance, using
CStructGetWord, we can read a WORD value from a buffer. Using
CStructPutWordwe can write a WORD value to a buffer.
However, looking closely at the CStruct library, it is striking that not all base datatypes have corresponding Get and Put functions.
CStructGetWord, is defined to get only UNSIGNED values. This means that it only supports types having a maximum value range of 0 to 65535.
A SIGNED value has a different maximum range, in this case -32768 to 32767.
Most of the CStruct functions have this limitation. They are designed to handle UNSIGNED values only.
When an UNSIGNED value is handled using these functions, the values will be truncated at certain values and result in strange values.
To help out with these issues, I created an extension to the CStruct library, called CStructEx library.
It offers many more functions for a wide range of different datatypes.
All extended functions have the function name CStructEx... or CStructExPtr...
The CStructExPtr*functions are using memory pointers (number) instead of string buffers.
The API reference list shows which CStruct function to use for the particular datatypes.
The CStructEx library consist of 3 libraries:
- Library to use in ANSI TD versions
- Library to use in UNICODE TD versions
- Library to use in TD70 and up (both 32 and 64 bit versions).
https://samples.tdcommunity.net/index ... cStructEx/