Using external functions
External functions are functions that are written in languages
other than PowerScript and stored in dynamic libraries.
On Windows On Windows, external functions are stored in dynamic link libraries
(DLLs).
On UNIX On UNIX, external functions are stored in shared (archive)
libraries with the extension .a, .so, or .sl depending on the platform.
You can use external functions written in any language that
supports the standard calling sequence for 32-bit platforms.
If you call external functions in PowerBuilder for Unicode,
the functions must be defined and compiled with Unicode support.
All strings must be passed as Unicode strings.
If you’re calling functions in libraries that you
have written yourself, remember that you need to export the functions.
Depending on your compiler, you can do this in the function prototype
or in a linker definition (.DEF) file.
Most of the information in this section applies
on all platforms. For additional information about using external
functions on UNIX, see “Calling external functions
and programs on UNIX”.
Declaring externalfunctions
Before you can use an external function in a script, you must
declare it.
Two types
You can declare two types of external functions:
- Global
external functions, which are available anywhere in
the application. - Local external functions,
which are defined for a particular type of window, menu, user object,
or user-defined function. These functions are part of the object’s
definition and can always be used in scripts for the object itself.
You can also choose to make these functions accessible to other
scripts as well.
Data types for external function arguments
When you declare an external function, the data types of the
arguments must correspond with the data types as declared in the
function’s source definition.
For a comparison of data types in external
functions and data types in PowerBuilder, see the section on declaring
and calling external functions in the PowerScript Reference
.
To declare an external function:
-
If you are declaring a local external function,
open the object for which you want to declare it. -
In the Script view, select Declare in the first
dropdown listbox and either Global External Functions or Local External
Functions from the second listbox. -
Enter the function declaration in the Script view.
For the syntax to use, see the PowerScript
Reference
or the examples below. -
Save the object.
PowerBuilder compiles the declaration. If there are syntax errors,
an error window opens, and you must correct the errors before PowerBuilder will save
the declaration.
Modifying existing functions You can also modify existing external function declarations
in the Script view.
Sample declarations
Suppose you have created a C DLL, SIMPLE.DLL, that contains
a function called SimpleFunc that accepts two parameters: a character
string and a structure. The following statement declares the function
in PowerBuilder, passing the arguments by reference:
1 |
FUNCTION int SimpleFunc(REF string lastname, & |
1 |
REF my_str pbstr) LIBRARY "simple.dll" |
Declaring Windows API functions
The Windows API includes over a thousand functions that you
can call from PowerBuilder. The following examples show sample declarations
for functions in the 32-bit Windows API libraries KERNEL32.DLL,
GDI32.DLL, and USER32.DLL.
Windows API calls Some 32-bit function names end with A (for ANSI) or W (for
wide). Use wide function names in PowerBuilder for Unicode.
For a complete list of Windows API functions,
see the Microsoft Windows SDK documentation. For examples of PowerBuilder declaration
syntax and scripts, search for Windows API calls in the Technical
Information Library on the Sybase website.
The following statements declare a function that gets the
handle of any window that is called by name and a function that
releases the open object handle:
1 |
FUNCTION ulong FindWindowA(ulong classname, & |
1 |
string windowname) LIBRARY "User32.dll" |
1 |
FUNCTION boolean CloseHandle(ulong w_handle) & |
1 |
LIBRARY "Kernel32.dll" |
In PowerBuilder for Unicode, use FindWindowW instead of FindWindowA.
The following statement declares a function that draws a pie
chart based on the coordinates received:
1 |
FUNCTION boolean Pie(ulong hwnd,long x1,long y1, & |
1 |
long x2,long y2,long x3,long y3,long x4, & |
1 |
long y4) LIBRARY "Gdi32.dll" |
The following statement declares an external C function named
IsZoomed:
1 |
FUNCTION boolean IsZoomed(Ulong handle) & |
1 |
LIBRARY "User32.DLL" |
A script that uses IsZoomed is included as an example in “Using utility functions
to manage information”.
For more information about these functions,
see the Microsoft Windows Software Developer’s Kit (SDK)
documentation.
Declaring Windows API functions on UNIX
The Wind/U layer of PowerBuilder provides UNIX shared
library versions of the Windows DLLs used in the preceding examples.
On Solaris, the declarations look like this:
1 |
FUNCTION ulong FindWindowA(ulong classname, & |
1 |
string windowname) LIBRARY "libuser42.so" |
1 |
FUNCTION boolean CloseHandle(ulong w_handle) & |
1 |
LIBRARY "libkernel42.so" |
1 |
FUNCTION boolean Pie(ulong hwnd,long x1,long y1, & |
1 |
long x2,long y2,long x3,long y3,long x4, & |
1 |
long y4) LIBRARY "libgdi42.so" |
1 |
FUNCTION boolean IsZoomed(Ulong handle) & |
1 |
LIBRARY "libuser42.so" |
On HP-UX and AIX, the UNIX libraries have the extension .sl
or .a instead of .so.
For more information about support for Windows
API calls on UNIX, see “Calling external functions
and programs on UNIX”.
Passing arguments
In PowerBuilder, you can define external functions that expect arguments
to be passed by reference or by value. When you pass an argument
by reference, the external function receives a pointer to the argument
and can change the contents of the argument and return the changed
contents to PowerBuilder. When you pass the argument by value, the
external function receives a copy of the argument and can change
the contents of the copy of the argument. The changes affect only
the local copy; the contents of the original argument are unchanged.
The syntax for an argument that is passed by reference is:
1 |
REF <i>datatype arg</i> |
The syntax for an argument that is passed by value is:
1 |
<i>datatype arg</i> |
Passing numeric data types
The following statement declares the external function TEMP
in PowerBuilder. This function returns an integer and expects an integer argument
to be passed by reference:
1 |
FUNCTION int TEMP(ref int degree) LIBRARY "LibName.DLL" |
The same statement in C would be:
1 |
int _stdcall TEMP(int * degree) |
Since the argument is passed by reference, the function can
change the contents of the argument, and changes made to the argument
within the function will directly affect the value of the original
variable in PowerBuilder. For example, the C statement *degree = 75 would
change the argument named degree to 75 and return 75 to PowerBuilder.
The following statement declares the external function TEMP2
in PowerBuilder. This function returns an integer and expects an integer argument
to be passed by value:
1 |
FUNCTION int TEMP2(int degree) LIBRARY "LibName.DLL" |
The same statement in C would be:
1 |
int _stdcall TEMP2(int degree) |
Since the argument is passed by value, the function can change
the contents of the argument. All changes are made to the local
copy of the argument; the variable in PowerBuilder is not affected.
On UNIX External functions that pass or return doubles by value are
not supported on UNIX.
Passing strings
Passing by value The following statement declares the external C function NAME
in PowerBuilder. This function expects a string argument to be passed by
value:
1 |
FUNCTION string NAME(string CODE) LIBRARY "LibName.DLL" |
The same statement in C would point to a buffer containing
the string:
1 |
char * _stdcall NAME(char * CODE) |
Since the string is passed by value, the C function can change
the contents of its local copy of CODE, but the original variable
in PowerBuilder is not affected.
Passing by reference PowerBuilder has access only to its own memory. Therefore, an
external function cannot return PowerBuilder a pointer to a string (it
cannot return a memory address).
When you pass a string to an external function, either by
value or by reference, PowerBuilder passes a pointer to the string.
If you pass by value, any changes the function makes to the string
are not accessible to PowerBuilder. If you pass by reference, they
are.
The following statement declares the external C function NAME2
in PowerBuilder. This function returns a string and expects a string
argument to be passed by reference:
1 |
FUNCTION string NAME2(<i>ref</i> string CODE) & |
1 |
LIBRARY "LibName.DLL" |
In C, the statement would be the same as when the argument
is passed by value, shown above:
1 |
char * _stdcall NAME2(char * CODE) |
The string argument is passed by reference, and the C function
can change the contents of the argument and the original variable
in PowerBuilder. For example, Strcpy(CODE,STUMP) would
change the contents of CODE to STUMP and change the variable in
the calling PowerBuilder script to the contents of variable STUMP.
If the function NAME2 in the preceding example takes a user
ID and replaces it with the user’s name, the PowerScript
string variable CODE must be long enough to hold the returned value.
To ensure that this is true, declare the string and then use the
Space function to fill the string with blanks equal to the maximum
number of characters you expect the function to return.
If the maximum number of characters allowed for a user’s
name is 40 and the ID is always five characters, you would fill
the string CODE with 35 blanks before calling the external function:
1 |
String CODE |
1 |
CODE = ID + Space(35) |
1 |
. . . |
1 |
NAME2(CODE) |
For information about the Space function,
see the PowerScript Reference
.
Passing chars to C functions Char variables passed to external C functions are converted
to the C char type before passing. Arrays of chars are converted to
the equivalent C array of chars.
An array of chars Embedded in a structure produces an Embedded
array in the C structure. This is different from an Embedded string,
which results in an Embedded pointer to a string in the C structure.
Recommendation Whenever possible, pass string variables back to PowerBuilder as
a return value from the function.