Extending the language / C-Extensions |
To pass values between a C function and a program, the C function and the runtime system use the runtime stack.
The parameters passed to the C function must be popped from the stack at the beginning of the C function, and the return values expected by the Genero BDL call must be pushed on the stack before leaving the C function.
The int parameter of the C function defines the number of input parameters passed on the stack, and the function must return an int value defining the number of values returned on the stack.
The runtime system library includes a set of functions to retrieve the values passed as parameters on the stack. This table shows the library functions provided to pop values from the stack into C buffers:
Function | Data type | Details |
---|---|---|
void popdate(int4 *dst); | DATE | 4-byte integer value corresponding to days since 12/31/1899. |
void popbigint(bigint *dst); | BIGINT | 8-byte integer value. |
void popint(mint *dst); | INTEGER | System dependent integer value (int) |
void popshort(int2 *dst); | SMALLINT | 2-byte integer value |
void poplong(int4 *dst); | INTEGER | 4-byte integer value |
void popflo(float *dst); | SMALLFLOAT | 4-byte floating point value |
void popdub(double *dst); | FLOAT | 8-byte floating point value |
void popdec(dec_t *dst); | DECIMAL | See structure definition in $FGLDIR/include/f2c headers |
void popquote(char *dst, int size); | CHAR(n) | The size parameter defines the size of the char buffer (with
the '\0'). The trailing blanks are kept. |
void popvchar(char *dst, int size); | VARCHAR(n) | The size parameter defines the size of the char buffer (with
the '\0'). The trailing blanks are kept. |
void popstring(char *dst, int size); | VARCHAR(n) | The size parameter defines the size of the char buffer (with
the '\0'). This function trims all the trailing spaces, even the last one. There is no way to distinguish from NULL if the string has only spaces. |
void popdtime(dtime_t *dst, int size); | DATETIME | See structure definition in $FGLDIR/include/f2c
headerssize = TU_DTENCODE(start, end) |
void popinv(intrvl_t *dst, int size); | INTERVAL | See structure definition in $FGLDIR/include/f2c headers size = TU_IENCODE(len, start, end) |
void poplocator(loc_t **dst); | BYTE, TEXT | See structure definition in $FGLDIR/include/f2c
headers Important: this function pops the pointer of a loc_t
object!
|
When using a pop function, the value is copied from the stack to the local C variable and the value is removed from the stack.
In a Genero program, strings (CHAR, VARCHAR) are not terminated by '\0'. Therefore, the C variable must have one additional character to store the '\0'. For example, the equivalent of a VARCHAR(100) in Genero BDL programs is a char x[101] in C.
A set of C API functions are provided to query information on the parameters passed on the stack to a C function. Query for the parameter type and the actual size of a character string value, to adapt the buffer receiving the parameter.
Function | Description |
---|---|
const char *fglcapi_peekStackType(void) | Returns the type name of the topmost value on the stack as a string. For
example, if the value on the stack is a CHAR(100), the function
returns the string "CHAR(100)".
Note: If the current value on the
stack is a string literal ("foo") then the type name is "STRING" not
"CHAR(3)".
|
int fglcapi_peekStackBufferSize(void) | Returns the proposed size of a C char buffer, when getting character strings
from the stack with a pop* function. String pop functions such as popquote() and popvchar() require a C char buffer to be allocated. To allocate the buffer dynamically, use the fglcapi_peekStackBufferSize() function to get the actual size of the string parameter passed on the stack. Allocating char buffers with the proposed size avoids truncating values returned from
the stack.
Important: The size returned by this function depends on the encoding (LC_CTYPE) and the character length
semantics.
For example, assuming the value passed on the stack is a CHAR(100), the function
returns:
See Length semantics settings for more details about these
concepts.
|
int my_function(int n) { int sz; char *buf; sz = fglcapi_peekStackBufferSize(); buf = malloc(sz); popstring(buf, sz); // ... free(buf); return 0; }
To return a value from the C function, you must use one of the functions provided in the runtime system library.
Function | Data type | Details |
---|---|---|
void pushdate(int4 val); | DATE | 4-byte integer value corresponding to days since 12/31/1899. |
void pushbigint(bigint val); | BIGINT | 8-byte integer value. |
void pushdec(const dec_t *val, const unsigned decp); | DECIMAL | See structure definition in $FGLDIR/include/f2c headers |
void pushint(mint val); | INTEGER | System dependent integer value (int) |
void pushlong(int4 val); | INTEGER | 4-byte integer value |
void pushshort(int2 val); | SMALLINT | 2-byte integer value |
void pushflo(float *val); | SMALLFLOAT | 4-byte floating point value. Important: This function takes a
pointer!
|
void pushdub(double *val); | FLOAT | 8-byte floating point value. Important: This function takes a
pointer!
|
void pushquote(const char *val, int len); | CHAR(n) | len = strlen(val) (without '\0') |
void pushvchar(const char *val, int len); | VARCHAR(n) | len = strlen(val) (without '\0') |
void pushdtime(const dtime_t *val); | DATETIME | See structure definition in $FGLDIR/include/f2c headers |
void pushinv(const intrvl_t *val); | INTERVAL | See structure definition in $FGLDIR/include/f2c headers |
When using a push function, the value of the C variable is copied at the top of the stack; therefore the scope and lifespan of the C variable does not matter.
To simplify migration of IBM I4GL legacy C extensions using ret*() style functions, Genero supports the following synonyms:
Function | Equivalent |
---|---|
void retdate(int4 val) | pushdate |
void retdec(const dec_t *val) | pushdec |
void retmoney(const dec_t *val) | pushdec |
void retint(int val) | pushint |
void retlong(int4 val) | pushlong |
void retshort(int2 val) | pushshort |
void retflo(float *val) | pushflo |
void retdub(double *val) | pushdub |
void retquote(const char *val) | pushquote |
void retstring(const char *val) | pushquote |
void retvchar(const char *val) | pushvchar |
void retdtime(const dtime_t *val) | pushdtime |
void retinv(const intrvl_t *val) | pushinv |