External functions datatype mapping

This table depicts which Gambas datatype must be used in an extern function declaration according to its corresponding declaration in C.

C datatype Gambas datatype
char Byte
bool Boolean
short Short
int

long (32 bits arch.)
Integer
int64_t

long (64 bits arch.)
Long
float Single
double Float
void * pointer
char * String or Pointer See below.
wchar_t * String or Pointer See below.
struct ABC * ABC or STRUCT ABC See below.

Output arguments

When dealing with an argument in a C function, you must know (by reading the documentation or by being clever) if a pointer argument (xxx *) is actually an output argument or not.

If you see const at the beginning, the datatype is not an output argument, as that means the function will not modified it.

If you know that a function argument is an output argument:
  1. You must declare it as a pointer.

  2. You must declare a Gambas variable according to the datatype the argument points to: remove the last star, and look in the previous table.

  3. When calling the function, pass the address of that variable using VarPtr.

Example:

' void get_device_name(void *device_id, char **name, int *len)
' This function gets a device id and returns its name.
 
Extern get_device_name(device_id As Pointer, name As Pointer, len As Pointer)

Dim name As Pointer ' actually a 'char *'
Dim len As Integer

get_device_name(device_id, VarPtr(name), VarPtr(len))

Print "The name of the device is:";; String@(name, len))

String arguments

In C, strings of characters are represented by the char * datatype or const char * datatype. It's a pointer that points at the string contents, and the end of the string is the first byte whose value is zero.

But a char * could just be a pointer to a byte. So you must be sure first, even if it is rare.

If an argument is a const char *, then you can declare it as a String.

Gambas will just pass a pointer to the beginning of the string. So you must ensure that the string is null-terminated.

This is the case if you don't use any function inside the call, i.e. if your string is store in some variable that you pass to the function.

If an argument is a char *, then maybe the function just wants a pointer to an allocation, and will fill it.

So you can declare the argument as a pointer. When calling the function you will allocate enough space with the Alloc function, and give the resulting pointer to the function.

Do not forget to call Free once the allocation is not needed anymore. Only you can know.

If an argument is a char **, the function will return a pointer to a string.

You can declare the argument as a Pointer, declare a variable X As Pointer, and pass its address to the function with VarPtr(X). Then you will use StrPtr(X) to get the string pointed by X.

If the function returns a char *, you can declare the return value as a String or as a Pointer.

If you use String, then Gambas will return a copy of the pointed string. If you use Pointer, you will get the real returned string by using StrPtr on the returned pointer.

To know what to do, you must read the function documentation that must tell you the life duration of the memory pointed by the returned pointer.

Wide-character string arguments

In C, wide-character strings are associated with the wchar_t * datatype. It represents a string, whose each character uses the same number of bytes.

You have now four problems:

  1. The number of bytes is greater or equal than two, and system-dependent. It's normally four on Linux.

  2. Consequently, the character encoding may be little or big endian.

  3. The exact character set corresponding to wchar_t * is also system dependent.

  4. The wide-character string is null terminated, but that null character is also multi-bytes. And Gambas only ensures one null byte at the end of strings.

To solve these problems, you have to:

  1. Use the Conv$ function to convert your strings to the special "WCHAR_T" charset.

  2. Add a null byte to the string before converting it: Conv(MyString & Chr$(0), "UTF-8", "WCHAR_T")
    That way, you will be sure that the string is null-terminated in the target character set.

Structure arguments

A C structure can be declared in Gambas with the STRUCT instruction. Normally, any C structure can be mimicked in Gambas. See Structure declaration for more details. The structure must be declared prior to the External Function Declaration that uses it.

There is no support for the union C declaration.

In C, a structure can be passed by value (the entire structure is put on the stack) or by reference (a pointer to the structure is sent).

Gambas handles only the second case, so this may be an unsolvable problem if your function wants a structure passed by value.

If an argument is a struct ABC * or const struct ABC *, then you mimic the structure ABC declaration, and you declare the argument as ABC.

Gambas will pass a pointer to the structure data to the function.

If the function returns a struct ABC *, then you mimic the structure ABC declaration, and you declare the return value as ABC.

Gambas will return a structure who takes its values directly from the pointer returned by the function. You won't get a copy!