To call an external function from a script, you must first create an instance of the PlatformFunction class.
You can build up the platform function manually as follows:
| drawGraph | drawGraph := PlatformFunction language: 'c' function: 'drawGraph' library: 'CGRAPH' parameterTypes: #(uint32 uint32 pointer) returnType: #void.
For more detailed information on parameter and return types, such as uint32 and pointer, refer to IBM Smalltalk Programmer's Reference.
The following table shows the supported calling conventions, their meaning,
and the platforms supported.
Calling Convention | OS/2 | Windows 95/98 | Windows NT | UNIX |
'c' | __stdcall | __stdcall | __stdcall | (none) |
'pascal16' | _Far16 _Pascal | __far __pascal |
|
|
'pascal' | _Pascal |
|
|
|
'cdecl16' | _Far16 _Cdecl | __far __cdecl |
|
|
|
Similarly, the following script segment uses the C language parser to build up the platform function automatically:
| drawGraph | drawGraph := ((AbtCLangParser parseFile: 'cgraph.h') platformFunctions: 'cgraph.dll') at: 'drawGraph' asSmalltalkGlobalIdentifier.
Similarly, you can use AbtCOBOLLangParser for COBOL.
Although this method might be easier for you, keep in mind that creating the platform function manually is generally faster because no parsing is necessary. In either case, you should design your scripts so that the platform function is only created once initially and not every time it is called
By default, the parser assumes a 32-bit DLL. If you are working with a 16-bit DLL, the make16Bit method can be used (for C only) as follows:
| drawGraph | drawGraph := ((AbtCLangParser parseFile: 'cgraph.h') make16Bit platformFunctions: 'cgraph.dll') at: 'drawGraph' asSmalltalkGlobalIdentifier.
After you have created the platform function, you can easily call it as follows:
drawGraph callWith: (ps asInteger) with: 8 with: (pointArray abtAsExternalPassedPointer).
where ps is a presentation space handle and pointArray is the array of points as defined in the previous section.
When using platform functions, the most common errors are that the dynamic link library cannot be loaded or that the function you are calling does not exist. You can perform an error check on the drawGraph platform function, for example, as follows:
(drawGraph abtValidAddress) ifFalse: [^CwMessagePrompter errorMessage: 'The function was not created successfully.'].
Other errors resulting from incorrect parameters should be handled by the function being called.
| buffer | buffer := String new: 255. ( PlatformFunctions at: 'FormatMessage' ) callWith: 4096 "FORMAT_MESSAGE_FROM_SYSTEM" with: nil "No message source" with: 4 "Error number here"
with: 0 "Language Identifier" with: buffer "Message Buffer" with: 255 "Message Buffer Maximum Size" with: nil. "Message Inserts" ^buffer trimNull