Passing parameters with the AbtRecord class
In addition to the record wrapper (AbtForeignOSObject subclass) technique, you can also use the "generic" record structure class AbtRecord to pass parameters to an external function. You might want to do this if your Smalltalk code needs to interact with an application built using VA Smalltalk. The VA Smalltalk visual External Function parts use the AbtRecord technique instead of the record wrapper technique for external function calls.
If you use AbtRecord record structures instead of record wrappers, you must do several things differently:
1. To create the record structure, you do not have to create a new subclass of AbtForeignOSObject. Instead, you create a single instance of the "generic" AbtRecord, tailored according to the compound type stored in the object table. To do this, use the newRecord method of the AbtCompoundType or AbtType class. Any data type definition stored in the object table responds to the newRecord message.
a. For the C language you would use newRecord as follows:
anAbtRecord :=
(anObjectTable dataStructures at: 'STRUCT_NAME'
asSmalltalkGlobalIdentifier) newRecord.
When a field is added to an AbtCompoundType instance, the field offset will be calculated based upon the field type and the instance's alignmentBoundary attribute. The default alignmentBoundary is 1. You can choose an alignmentBoundary of 1, 2, 4, or 8 depending upon the desired byte alignment.
Note:
The alignmentBoundary must be set prior to adding the field.
You must understand the alignment options used when when building your DLL and adjust alignmentBoundary accordingly, so that VA Smalltalk and the DLL map memory in the same way.
VA Smalltalk will align data in the following manner:
Table 2. VA Smalltalk data alignment using alignmentBoundary:
Data Type | 1 | 2 | 4 | 8 |
char | 1 | 1 | 1 | 1 |
short | 1 | 2 | 2 | 2 |
int, long | 1 | 2 | 4 | 4 |
float, double | 1 | 2 | 4 | 4 |
pointer | 1 | 2 | 4 | 4 |
struct | 1 | 2 | 4 | 8 |
The actual alignment boundary used is the lesser of the alignmentBoundary value and the sizeInBytes of the data item. Structures are always aligned according to the alignmentBoundary value.
This is best seen in an example. Consider the following C structure:
struct abc
{
char x ;
long y ;
}
This structure can be created in VA Smalltalk using the following code:
AbtCompoundType new
alignmentBoundary: b;
addField: AbtCCharField new name: 'x';
addField: AbtCLongField new name: 'y'.
The offset of y will vary with the value of b.
For b = 1 The offset of y is 1.
For b = 2 The offset of y is 2.
For b = 4 The offset of y is 4.
b. For the COBOL language you would use newRecord as follows:
anAbtRecord :=
(anObjectTable cobol01s at: 'STRUCT_NAME'
asSmalltalkGlobalIdentifier) newRecord.
2. To set the values of the fields in the record structure, do one of the following:
a. If the record structure represents a single data item, use the value: method to place the parameter value into the record structure.
anAbtRecord value: 'Input Value'.
b. If the record structure represents a parameter of a compound type, use the at:put: to set the values of the individual fields.
anAbtRecord at: 'inputParm1' put: 'Input Value 1'.
anAbtRecord at: 'inputParm2' put: 'Input Value 2'.
c. If a field is an array, and you want to set the value of an item in the array, you should use the at:subscript:put: message as in the following example:
anItem := anAbtRecord
at: #inputParm
subscript: 3
put: 'Input Value'.
3. When you call the external function using the coroutineCallWith: method, you must explicitly convert the record structure to a byte array that the external function can accept. To do this, use the abtAsExternalPassedPointer message, which extracts the byte array from the record structure.
aPlatformFunction
coroutineCallWith: anAbtRecord abtAsExternalPassedPointer.
If you used prior versions of VA Smalltalk you used asBytes to accomplish what abtAsExternalPassedPointer does in the above example. asBytes is now obsolete. New applications should use abtAsExternalPassedPointer. Existing applications should be modified to use abtAsExternalPassedPointer because asBytes will disappear in a future release.
To try using this technique with the sample, type the following example code in the System Transcript window, select it, and run it. You should get the same results on the System Transcript window that you saw in the earlier examples.
Last modified date: 05/15/2020