Home > Language Reference > Statements

Declare Statement

Declares an external procedure or function.

Syntax

To declare an external procedure:

{ Public | Private } Declare Sub Name ( [ ArgList ] ) Trap Trap [ { , | StdSel | HostSel | StackSel } Selector ]

To declare an external function:

{ Public | Private } Declare Function Name ( [ ArgList ] ) As Type Trap Trap [ { , | StdSel | HostSel | StackSel } Selector ]

ParameterDescription
NameProcedure or function name.
ArgListList of the arguments the external procedure accepts.
TypeReturn type of the external function.
TrapTrap number (see below).
SelectorSelector number (see below).

Remarks

The Declare statement allows the declaration of an external function written in C, located in a shared library or in the operating system itself. It is then possible to call this function like any other function with the Call statement.

This functionality can be used to call native Palm OS® functions that are not encapsulated by the HB++ execution library, but also, when your application requires particular performance, to call low level functions written in C.

Using this statement requires good knowledge of how to pass parameters to C functions, and should only be used by experienced programmers.

The Name parameter indicates the name of the procedure or function declared. It is this identifier that will be used to call the external function from your program, and does not have to be identical to the original name of the C function: in fact, HB++ does not have any means of knowing its original name, and uses only the trap and selector numbers to find the correct library function.

It is also possible to declare the same function several times under different names, which can prove useful when your C function is expecting generic parameters of type void * for example: you can declare the relevant function as many times as necessary, under different names and with different argument lists. For example, the Palm OS® function StrLen expects a pointer to a character string. You can declare it:

Public Declare Function StrLenChar(ByRef s As String) As Integer Trap &HA0C7
Public Declare Function StrLenAddr(ByVal a As Long) As Integer Trap &HA0C7

The first function could be called directly with a parameter of type String whilst the second could be called with a parameter of type Long corresponding to the address of a character string. In both cases, the same external function is called, the trap number being identical.

The Trap parameter should be a constant expression whose value is between 40960 and 65535 inclusive. It indicates the function number to call in the external library. Some functions also require a selector number, which can be either passed through the D2 register or either on the stack. This selector number as well as its type can be specified using the optional Selector parameter, preceded by a comma or by one of the following keywords :

KeywordDescription
StdSelSame as a comma. Indicates that the selector number should be passed to the function through the D2 register. This is the most common case.
HostSelIndicates that the selector number should be passed on the stack as an extra parameter to the function. This mode is notably used to declare functions provided by the Palm OS Emulator whose prototypes can be found in the HostControl.h header file.
StackSelIndicates that the selector number should be passed on the stack as an extra parameter to the function, but that this parameter should be popped by the callee instead of being popped by the caller. This mode is used for some licensee SDK such as Handspring Treo 600.

If you declare a C function in a library you have written, you can choose these numbers freely, and should simply make sure that they are the same both in the library and in your HB++ program. If on the other hand you declare a native PalmOS® function, you should refer to the C header files in the Palm OS® SDK to find out these numbers and how selectors should be specified. Note that this point may require good C knowledge.

The Type parameter indicates, in the case of a function, the type of the value returned by the external function. Only basic and enumerated types are allowed here. It is not possible to return a value of type String, Variant or an object because an external function has no way to create and return data of these types. In addition to basic types, you can also use the Pointer keyword which is strictly equivalent to the type Long but indicates to the compiler that the external function returns the value to the A0 register instead of the D0 register. This particularity is necessary because of the function return convention of the CodeWarrior™ and GCC compilers on the Motorola® 68000. For example, the Palm OS® MemPtrNew function should be declared as below:

Public Declare Function MemPtrNew(ByVal lSize as Long) As Pointer Trap &HA013

If you do not plan to use the return value, you can also declare an external function as a procedure. The value returned is simply ignored by HB++, and the code generated is more compact and faster.

The table below summarises the types authorised for the Type parameter with their equivalent in C.

HB++ Return TypeC Return TypeRemarks
BooleanBoolean, UInt8, char, unsigned char...See note (1) below.
ByteUInt8, unsigned char...
IntegerInt16, short, int...
LongInt32, long...
SinglefloatSee note (2) below.
DoubledoubleSee notes (2) and (3) below.
DateUInt32, unsigned long...See note (4) below.
PointerAny pointer type
Any enumerated typeAny type of the same size as the enumerated typeSee note (5) below.

(1) If the value returned by the external function is zero, this is interpreted as False. Any other values is interpreted as True.

(2) Some special values defined by the IEEE 754 standard are not managed by the HB++ mathematical library, and cannot therefore be returned by the external function. Refer to the introduction page on Mathematical Functions for more information.

(3) HB++ is expecting values of type Double in the pair of registers D0 - D1. Some C compilers do not adhere to this convention (noteably CodeWarrior™ with which the Palm OS® operating system is compiled), and uses a hidden pointer parameter to return values whose length is greater than 4 bytes.

(4) The value returned by the external function is interpreted as the number of seconds elapsed since 1 January 1904. Because the HB++ execution library cannot handle dates after 31 December 2031, the external function should not return a value greater than 4 039 372 800.

(5) Depending on the value of the constants making up an enumerated type, this occupies 1, 2 or 4 bytes, and is equivalent respectively to a Byte, Integer, or Long which means that the external function must return a UInt8, Int16, or Int32. Refer to the page on Enumerations for more information.

Finally, the ArgList parameter describes the list of parameters expected by the external function. As with a function or procedure declaration, each parameter should be separated by a comma, and can contain ByVal or ByRef. It is also possible to specify optional parameters. Refer to the description of the Sub statement for more information on the syntax of declaring parameters.

For basic and enumerated types, using the ByVal keyword causes the parameter value to be passed to the external function, whilst using the ByRef keyword causes a pointer to be passed. For types String and StreamMemory, a pointer to the first byte of the data is passed whichever convention is specified. Other types like Variant for example or object variables cannot be passed to external procedures. The table below summarises the types with their equivalent in C.

ParameterPassedExpected ParameterRemarks
BooleanByValBoolean, UInt8, char, unsigned char...See note (1) below
BooleanByRefBoolean *, UInt8 *, char *, unsigned char *...See note (1) below
ByteByValUInt8, unsigned char...
ByteByRefUint8 *, unsigned char *...
IntegerByValInt16, int, short...
IntegerByRefInt16 *, int *, short *...
LongByValInt32, long...
LongByRefInt32 *, long *...
SingleByValfloatSee note (2) below
SingleByReffloat *See note (2) below
DoubleByValdoubleSee note (2) below
DoubleByRefdouble *See note (2) below
DateByValUInt32, unsigned longSee note (3) below
DateByRefUInt32 *, unsigned long *See note (3) below
StringByVal ByRefchar *See note (4) below
StreamMemoryByVal ByRefvoid * or any type of pointer
Any enumerated typeByValAny type of the same size as the enumerated type.
Any enumerated typeByRefA pointer of any type of the same size as the enumerated type

(1) If the parameter is True, the external function receives the value 1. If the parameter is False, the external function receives the value 0.

(2) Some special values defined by the IEEE 754 standard are not managed by the HB++ mathematical library, and cannot therefore be received by the external function. Refer to the introduction page on Mathematical Functions for more information.

(3) The value received by the external function is interpreted as the number of seconds elapsed since 1 January 1904.

(4) The external function receives a pointer to the first character in the string. If an empty string is passed, the external function receives a NULL pointer.

(5) The external function receives a pointer to the first byte of the data, even if the StreamMemory is empty. To pass a NULL pointer, pass the value Nothing.

When you pass a pointer to an external function using arguments of type String or StreamMemory, you should take into account the fact that the memory block passed is allocated and maintained by HB++. The external function must not attempt to destroy it or modify its size. In the same way, if the external function must modify the data contained in the memory block, you must make sure that it is large enough. In the case of a String, you can use the Space function for example.

For further information on shared libraries and communication between HB++ and the C language, refer to the Shared Libraries chapter in the Programmer's Guide. You can also see refer to the MathLib Sinus sample.

System requirements

SystemMinimal versionRemarks
Palm OSPalm OS 3.0N/A