Using the platformFunctions: method
In the previous example you created the platform function object manually. You can also use the file parser to create pool dictionaries of function prototypes. You do this by sending the platformFunctions: message to an object table. This method takes the library name where the functions reside as input and returns a dictionary containing the function prototypes.
Using the platformFunctions: method with C
To parse the C sample header and create the platform function dictionary for the header file's contents, type the following code in a workspace, select it, and execute it.
"Parse the C header file creating a pool dictionary for constants
and a pool dictionary for function prototypes"
| anObjectTable CATMConstants CATMPrototypes |
anObjectTable := AbtCLangParser parseFile: 'catm.h'.
AbtRecordGenerator new
generateAllFieldsFrom: (anObjectTable dataStructures
at: 'ATM_CUSTOMER' asSmalltalkGlobalIdentifier)
inClass: SampleCATMStruct.
CATMConstants := anObjectTable constants.
Smalltalk at: #SampleCATMConstants put: CATMConstants.
CATMPrototypes := anObjectTable platformFunctions: 'catm'.
Smalltalk at: #SampleCATMPrototypes put: CATMPrototypes
 
Tip icon
By default, the parser assumes a 32-bit DLL. If you are working with a 16-bit DLL, the make16Bit method can be used as follows:
CATMPrototypes : = anObjectTable make16Bit platformFunctions: 'catm'.
Smalltalk at: #SampleCATMPrototypes put: CATMPrototypes
Add the following method to your application to call the function using the prototype pool dictionary you just created:
invokeCATMUsingPrototype
"This method calls the C ATM function in the CATM DLL,
The method assumes the record wrapper has already been
created and that the constants and function prototypes
in the CATM sample have been placed in pool dictionaries"
| atmStruct platformFunction |
atmStruct := SampleCATMStruct new.
atmStruct pinNumber: '12345'.
platformFunction := Atm.
platformFunction
coroutineCallWithArray:
(Array with: AtmQuery
with: (atmStruct abtAsExternalPassedPointer))
threadKey: nil.
Transcript
show: (atmStruct firstName); cr;
show: (atmStruct lastName); cr;
show: (atmStruct checkingBalance); cr.
Note the expression atmStruct abtAsExternalPassedPointer in the example above. The abtAsExternalPassedPointer method causes the second parameter to be passed as a pointer regardless of its type in the platform function.
Tip icon
#struct and #pointer are equivalent when passing ByteArray on a function call. #pointer provides the added flexibility of allowing an address or a byte array to be passed.
To test your new method, type the following on the System Transcript window, select it, and run it:
MjkStExtFunc new invokeCATMUsingPrototype
You should see the following in your System Transcript window:
John
Smith
7890.03
Using the platformFunctions: method with COBOL
To parse the COBOL copybook file and create the platform function dictionary for it, type the following code in a workspace, select it, and run it.
"Parse the COBOL program file creating a pool dictionary for
constants and a pool dictionary for function prototypes"
| anObjectTable COBOLATMConstants COBOLATMPrototypes |
anObjectTable := AbtCOBOLLangParser parseFile: 'atm.cbl'.
AbtRecordGenerator new
generateAllFieldsFrom: (anObjectTable cobol01s
at: 'ATM-CUSTOMER' asSmalltalkGlobalIdentifier)
inClass: SampleCOBOLATMStruct.
COBOLATMConstants := anObjectTable constants.
Smalltalk at: #SampleCOBOLATMConstants put: COBOLATMConstants.
COBOLATMPrototypes := (anObjectTable
platformFunctions: 'ATM') make16Bit.
Smalltalk at: #SampleCOBOLATMPrototypes put: COBOLATMPrototypes
Add the following method to your application to call the function using the prototype pool dictionary you just created:
invokeCOBOLATMUsingPrototype
"This method calls the COBOL ATM function in the ATM DLL,
The method assumes the record wrapper has already been
created and that the constants and function prototypes
in the ATM sample have been placed in pool dictionaries"
| atmStruct platformFunction |
atmStruct := SampleCOBOLATMStruct new.
atmStruct pinNumber: '12345'.
platformFunction := Atm.
platformFunction
coroutineCallWithArray:
(Array with: AtmQuery with: (atmStruct abtAsExternalPassedPointer))
threadKey: nil.
Transcript
show: (atmStruct firstName); cr;
show: (atmStruct lastName); cr;
show: (atmStruct checkingBalance); cr.
Note the expression atmStruct abtAsExternalPassedPointer in the example above. The parser builds the prototype dictionary using struct for the second parameter instead of using a pointer. The abtAsExternalPassedPointer method causes the second parameter to be passed as a pointer regardless of its type in the platform function.
To test your new method, type the following un the System Transcript window, select it, and run it:
MjkStExtFunc new invokeCOBOLATMUsingPrototype
You should see the following in your System Transcript window:
John
Smith
7890.03
Last modified date: 05/15/2020