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.
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:
-
You must declare it as a
pointer
.
-
You must declare a Gambas variable according to the datatype the argument points to: remove the last star, and look in the previous table.
-
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:
-
The number of bytes is greater or equal than two, and system-dependent. It's normally four on Linux.
-
Consequently, the character encoding may be little or big endian.
-
The exact character set corresponding to
wchar_t *
is also system dependent.
-
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:
-
Use the Conv$ function to convert your strings to the special
"WCHAR_T"
charset.
-
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!