Extending the language / User-defined front calls |
Custom front call modules for the desktop front-end are implemented by using the API for GDC front calls in C language.
In order to extend the GDC with your own front calls, you must be familiar with C++ programming, and have a C++ compiler installed on your development platform.
GDC front call modules must be implemented as a Dynamic Linked Library (.DLL) on Windows™ platforms, as a shared library (.so) on Linux™, or as a Dynamic Library (.dyLib) under Mac Os X. This shared library must be deployed on each platform where the GDC front-end executes.
The GDC is able to automatically load the front call module and find the function, based on the module name and function name used in the Genero BDL front call (ui.Interface.frontCall).
The API for GDC front calls is based on the frontEndInterface front call interface structure, that is used to interface with the GDC core, in order to pass/return values to/from a front call.
struct frontEndInterface { short (* getParamCount) (); short (* getReturnCount) (); void (* popInteger) (long &, short &); void (* pushInteger) (const long, short); void (* popString) (char *, short &, short &); void (* pushString) (const char *, short, short); void (* getFrontEndEnv) (const char *, char *, short &); void (* popWString) (wchar_t *, short &, short &); void (* pushWString) (const wchar_t*, short, short); };
The prototype of each front call function must be:
int function_name ( const struct frontEndInterface &fci );
The fci structure will be filled by the GDC and passed to the custom function. You can then use this structure to pop/push values from/to the stack, and get environment information from the core GDC.
The function must return 0 on success, -1 otherwise.
The front call function can query the GDC for front call environment variables, to get information about the context.
The following front call environment variables are supported:
Environment Variable | Description |
---|---|
frontEndPath | The path where the GDC front-end is installed. |
The font-call module can define initialization and finalization functions. GDC will automatically call these functions as follows:
This function is called when the front call module library is loaded. If needed, perform variable initialization and resource allocation in this function.
This function is called when the GDC front-end stops. If needed, perform resource release in this function.
Function | Description |
---|---|
short getParamCount(); |
This function returns the number of parameters given to the function called. |
short getReturnCount(); |
This function returns the number of returning values of the function called. |
void ( * getFrontEndEnv ) (const char * name, char * value, short & length ); |
This function is used to
get context information from the front-end.
|
void popInteger( long & value, short & isNull ); |
This function is used to
get an integer from the stack.
|
void pushInteger( const long value, short isNull ); |
This function is used to
push an integer on the stack.
|
void popString( char * value, short & length, short & isNull ); |
This function is used to
get a string from the stack.
|
void pushString( const char * value, short length, short isNull ); |
This function is used to
push a string on the stack.
|
void ( * popWString ) (wchar_t *value, short & length, short & isNull); |
This function is used to
get a WideChar string from the stack.
|
void ( * pushWString ) (wchar_t *value, short length, short isNull); |
This function is used to
push a WideChar string on the stack.
|
In the Genero program, use the ui.Interface.frontCall() API to call the front-end function. This method takes the front call module name as the first parameter and the front call function name as second parameter. The front call module name is defined by the name of the dynamic library (module_name.DLL, module_name.so or module_name.dylib).
CALL ui.Interface.frontCall("mymodule", "myfunction", ["John DOE"], [msg])
The shared library implementing the custom front call functions must be deployed on the platform where the GDC executes: Copy your custom front call modules in the bin directory of the GDC installation directory (i.e. %GDCDIR%\bin). This is also true when the GDC is deployed as ActiveX over the GAS.
This example implements a simple front call function that computes the sum of two integer numbers. It takes two parameters and returns two values.
mymodule.h:
struct frontEndInterface { short (* getParamCount) (); short (* getReturnCount) (); void (* popInteger) (long &, short &); void (* pushInteger) (const long, short); void (* popString) (char *, short &, short &); void (* pushString) (const char *, short, short); void (* getFrontEndEnv) (const char *, char *, short &); void (* popWString) (wchar_t *, short &, short &); void (* pushWString) (const wchar_t*, short, short); }; #ifdef WIN32 #define EXPORT extern "C" __declspec(dllexport) #else #define EXPORT extern "C" #endif EXPORT void initialize(); EXPORT void finalize(); EXPORT int mysum(const frontEndInterface &fx);
#include "mymodule.h" #include <stdio.h> #include <string.h> void initialize() { } void finalize() { } int mysum(const struct frontEndInterface &fci) { long param1, param2; short isNull1, isNull2; long sum; char msg[255]; if (fci.getParamCount() != 2 || fci.getReturnCount() != 2) { return -1; } fci.popInteger(param2, isNull2); fci.popInteger(param1, isNull1); sum = param1 + param2; if (!isNull1 && !isNull2) { sum = param1 + param2; sprintf(msg, "%d + %d = %d", param1, param2, sum); } else { sum = 0; sprintf(msg, "Parameters are NULL"); } fci.pushInteger(sum, 0); fci.pushString(msg, strlen(msg), 0); return 0; }
MAIN DEFINE res INT, msg STRING MENU ON ACTION frontcall ATTRIBUTES(TEXT="Call custom front call") CALL ui.Interface.frontCall("mymodule", "mysum", [100,250], [res,msg]) DISPLAY "Result: ", res, "\n", msg ON ACTION quit EXIT MENU END MENU END MAIN